xref: /base/update/updater/utils/utils_fs.cpp (revision fb299fa2)
1/*
2 * Copyright (c) 2024 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 "utils_fs.h"
17#include <algorithm>
18#include <cerrno>
19#include <cstdint>
20#include <cstdlib>
21#include <dirent.h>
22#include <fcntl.h>
23#include <limits>
24#include <linux/reboot.h>
25#include <string>
26#include <sys/reboot.h>
27#include <sys/stat.h>
28#include <sys/syscall.h>
29#include <unistd.h>
30#include <vector>
31#include "log/log.h"
32
33namespace Updater {
34namespace Utils {
35
36int MkdirRecursive(const std::string &pathName, mode_t mode)
37{
38    size_t slashPos = 0;
39    struct stat info {};
40    while (true) {
41        slashPos = pathName.find_first_of("/", slashPos);
42        if (slashPos == std::string::npos) {
43            break;
44        }
45        if (slashPos == 0) {
46            slashPos++;
47            continue;
48        }
49        if (slashPos > PATH_MAX) {
50            LOG(ERROR) << "path too long for mkdir";
51            return -1;
52        }
53        auto subDir = pathName.substr(0, slashPos);
54        LOG(INFO) << "subDir : " << subDir;
55        if (stat(subDir.c_str(), &info) != 0) {
56            int ret = mkdir(subDir.c_str(), mode);
57            if (ret && errno != EEXIST) {
58                return ret;
59            }
60        }
61        slashPos++;
62    }
63    int ret = mkdir(pathName.c_str(), mode);
64    if (ret && errno != EEXIST) {
65        return ret;
66    }
67    return 0;
68}
69
70int64_t GetFilesFromDirectory(const std::string &path, std::vector<std::string> &files,
71    bool isRecursive)
72{
73    struct stat sb {};
74    if (stat(path.c_str(), &sb) == -1) {
75        LOG(ERROR) << "Failed to stat";
76        return -1;
77    }
78    DIR *dirp = opendir(path.c_str());
79    struct dirent *dp;
80    int64_t totalSize = 0;
81    while ((dp = readdir(dirp)) != nullptr) {
82        std::string fileName = path + "/" + dp->d_name;
83        struct stat st {};
84        if (stat(fileName.c_str(), &st) == 0) {
85            std::string tmpName = dp->d_name;
86            if (tmpName == "." || tmpName == "..") {
87                continue;
88            }
89            if (isRecursive && S_ISDIR(st.st_mode)) {
90                totalSize += GetFilesFromDirectory(fileName, files, isRecursive);
91            }
92            files.push_back(fileName);
93            totalSize += st.st_size;
94        }
95    }
96    closedir(dirp);
97    return totalSize;
98}
99
100bool RemoveDir(const std::string &path)
101{
102    if (path.empty()) {
103        LOG(ERROR) << "input path is empty.";
104        return false;
105    }
106    std::string strPath = path;
107    if (strPath.at(strPath.length() - 1) != '/') {
108        strPath.append("/");
109    }
110    DIR *d = opendir(strPath.c_str());
111    if (d != nullptr) {
112        struct dirent *dt = nullptr;
113        dt = readdir(d);
114        while (dt != nullptr) {
115            if (strcmp(dt->d_name, "..") == 0 || strcmp(dt->d_name, ".") == 0) {
116                dt = readdir(d);
117                continue;
118            }
119            struct stat st {};
120            auto file_name = strPath + std::string(dt->d_name);
121            stat(file_name.c_str(), &st);
122            if (S_ISDIR(st.st_mode)) {
123                RemoveDir(file_name);
124            } else {
125                remove(file_name.c_str());
126            }
127            dt = readdir(d);
128        }
129        closedir(d);
130    }
131    return rmdir(strPath.c_str()) == 0 ? true : false;
132}
133
134bool IsFileExist(const std::string &path)
135{
136    struct stat st {};
137    if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
138        return true;
139    }
140    return false;
141}
142
143bool IsDirExist(const std::string &path)
144{
145    struct stat st {};
146    if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
147        return true;
148    }
149    return false;
150}
151} // Utils
152} // updater
153