1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <unistd.h>
17#include <cstdlib>
18#include <cstring>
19#include <cerrno>
20#include <dirent.h>
21#include <fcntl.h>
22#include <sys/stat.h>
23#include "log.h"
24#include "libfs.h"
25#include "KernelConstants.h"
26using namespace std;
27
28int MakeDir(const char *dirname)
29{
30    if (access(dirname, F_OK) == 0) {
31        LOG("dir:%s exists", dirname);
32        return 1;
33    } else {
34        int rt = mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IXOTH);
35        if (rt) {
36            LOG("create dir failed! path=%s, errno=%d:%s", dirname, errno, strerror(errno));
37            return -1;
38        }
39    }
40    return 0;
41}
42
43int RemoveDir(const char *dirname)
44{
45    char subDir[MAX_PATH_SIZE];
46    struct stat dirStat = {0};
47
48    if (stat(dirname, &dirStat) < 0) {
49        LOG("get directory stat error, errno=%d:%s", errno, strerror(errno));
50        return -1;
51    }
52
53    if (S_ISDIR(dirStat.st_mode)) {
54        DIR *pDir = opendir(dirname);
55        struct dirent *entry;
56        while ((entry = readdir(pDir))) {
57            std::string fname = entry->d_name;
58            if (!strcmp(fname, ".") || !strcmp(fname, "..")) {
59                continue; // skip . and ..
60            }
61            // MAX_PATH_SIZE is the max length of allowed path string, so it safe to use sprintf here.
62            size_t rt = sprintf_s(subDir, sizeof(subDir), "%s/%s", dirname, fname.c_str());
63            if (rt < 0) {
64                LOG("output failed, dirname=%s, errno=%d:%s", dirname, errno, strerror(errno));
65            }
66            RemoveDir(subDir);   // remove sub dir or file
67        }
68        closedir(pDir);
69        if (rmdir(dirname) == -1) {  // delete empty dir
70            LOG("delete empty directory failed, path=%s, errno=%d:%s", dirname, errno, strerror(errno));
71            return -1;
72        }
73    } else {
74        if (remove(dirname) == -1) {
75            LOG("remove regular file failed, path=%s, errno=%d:%s", dirname, errno, strerror(errno));
76            return -1;
77        }
78    }
79
80    return 0;
81}
82
83int RemoveFile(const char *fpath)
84{
85    if (!remove(fpath)) {
86        LOG("remove file success");
87    } else {
88        LOG("remove file failed! path=%s: errno=%d:%s", fpath, errno, strerror(errno));
89        return -1;
90    }
91    return 0;
92}
93
94int CopyFile(const char *srcFile, const char *dstFile)
95{
96    int rt = 0;
97    FILE *srcFp = fopen(srcFile, "rb");
98    if (srcFp == nullptr) {
99        LOG("Cannot open source file %s: errno=%d,%s \n", srcFile, errno, strerror(errno));
100        return -1;
101    }
102    FILE *dstFp = fopen(dstFile, "wb");
103    if (dstFp == nullptr) {
104        LOG("Cannot create dest file %s: errno=%d,%s \n", dstFile, errno, strerror(errno));
105        fclose(srcFp);
106        return -1;
107    }
108
109    const int bufSize = 100 * 1024;
110    char buffer[bufSize];
111    size_t bytes;
112    while ((bytes = fread(buffer, 1, sizeof(buffer), srcFp)) > 0) {
113        if (fwrite(buffer, 1, bytes, dstFp) != bytes) {
114            LOG("write to dest file failed: errno=%d,%s \n", errno, strerror(errno));
115            rt = -1;
116            break;
117        }
118    }
119    if (fclose(srcFp)) {
120        LOG("close to src file failed: errno=%d,%s \n", errno, strerror(errno));
121        return -1;
122    }
123    if (fclose(dstFp)) {
124        LOG("close to dst file failed: errno=%d,%s \n", errno, strerror(errno));
125        return -1;
126    }
127    return rt;
128}
129
130string GetCurrentPath()
131{
132    static char path1[MAX_PATH_SIZE];
133    string path = getcwd(path1, MAX_PATH_SIZE);
134    LOG("current Path = %s,path1=%s", path, path1);
135    return path1;
136}
137