1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci
16fb299fa2Sopenharmony_ci#include "utils_fs.h"
17fb299fa2Sopenharmony_ci#include <algorithm>
18fb299fa2Sopenharmony_ci#include <cerrno>
19fb299fa2Sopenharmony_ci#include <cstdint>
20fb299fa2Sopenharmony_ci#include <cstdlib>
21fb299fa2Sopenharmony_ci#include <dirent.h>
22fb299fa2Sopenharmony_ci#include <fcntl.h>
23fb299fa2Sopenharmony_ci#include <limits>
24fb299fa2Sopenharmony_ci#include <linux/reboot.h>
25fb299fa2Sopenharmony_ci#include <string>
26fb299fa2Sopenharmony_ci#include <sys/reboot.h>
27fb299fa2Sopenharmony_ci#include <sys/stat.h>
28fb299fa2Sopenharmony_ci#include <sys/syscall.h>
29fb299fa2Sopenharmony_ci#include <unistd.h>
30fb299fa2Sopenharmony_ci#include <vector>
31fb299fa2Sopenharmony_ci#include "log/log.h"
32fb299fa2Sopenharmony_ci
33fb299fa2Sopenharmony_cinamespace Updater {
34fb299fa2Sopenharmony_cinamespace Utils {
35fb299fa2Sopenharmony_ci
36fb299fa2Sopenharmony_ciint MkdirRecursive(const std::string &pathName, mode_t mode)
37fb299fa2Sopenharmony_ci{
38fb299fa2Sopenharmony_ci    size_t slashPos = 0;
39fb299fa2Sopenharmony_ci    struct stat info {};
40fb299fa2Sopenharmony_ci    while (true) {
41fb299fa2Sopenharmony_ci        slashPos = pathName.find_first_of("/", slashPos);
42fb299fa2Sopenharmony_ci        if (slashPos == std::string::npos) {
43fb299fa2Sopenharmony_ci            break;
44fb299fa2Sopenharmony_ci        }
45fb299fa2Sopenharmony_ci        if (slashPos == 0) {
46fb299fa2Sopenharmony_ci            slashPos++;
47fb299fa2Sopenharmony_ci            continue;
48fb299fa2Sopenharmony_ci        }
49fb299fa2Sopenharmony_ci        if (slashPos > PATH_MAX) {
50fb299fa2Sopenharmony_ci            LOG(ERROR) << "path too long for mkdir";
51fb299fa2Sopenharmony_ci            return -1;
52fb299fa2Sopenharmony_ci        }
53fb299fa2Sopenharmony_ci        auto subDir = pathName.substr(0, slashPos);
54fb299fa2Sopenharmony_ci        LOG(INFO) << "subDir : " << subDir;
55fb299fa2Sopenharmony_ci        if (stat(subDir.c_str(), &info) != 0) {
56fb299fa2Sopenharmony_ci            int ret = mkdir(subDir.c_str(), mode);
57fb299fa2Sopenharmony_ci            if (ret && errno != EEXIST) {
58fb299fa2Sopenharmony_ci                return ret;
59fb299fa2Sopenharmony_ci            }
60fb299fa2Sopenharmony_ci        }
61fb299fa2Sopenharmony_ci        slashPos++;
62fb299fa2Sopenharmony_ci    }
63fb299fa2Sopenharmony_ci    int ret = mkdir(pathName.c_str(), mode);
64fb299fa2Sopenharmony_ci    if (ret && errno != EEXIST) {
65fb299fa2Sopenharmony_ci        return ret;
66fb299fa2Sopenharmony_ci    }
67fb299fa2Sopenharmony_ci    return 0;
68fb299fa2Sopenharmony_ci}
69fb299fa2Sopenharmony_ci
70fb299fa2Sopenharmony_ciint64_t GetFilesFromDirectory(const std::string &path, std::vector<std::string> &files,
71fb299fa2Sopenharmony_ci    bool isRecursive)
72fb299fa2Sopenharmony_ci{
73fb299fa2Sopenharmony_ci    struct stat sb {};
74fb299fa2Sopenharmony_ci    if (stat(path.c_str(), &sb) == -1) {
75fb299fa2Sopenharmony_ci        LOG(ERROR) << "Failed to stat";
76fb299fa2Sopenharmony_ci        return -1;
77fb299fa2Sopenharmony_ci    }
78fb299fa2Sopenharmony_ci    DIR *dirp = opendir(path.c_str());
79fb299fa2Sopenharmony_ci    struct dirent *dp;
80fb299fa2Sopenharmony_ci    int64_t totalSize = 0;
81fb299fa2Sopenharmony_ci    while ((dp = readdir(dirp)) != nullptr) {
82fb299fa2Sopenharmony_ci        std::string fileName = path + "/" + dp->d_name;
83fb299fa2Sopenharmony_ci        struct stat st {};
84fb299fa2Sopenharmony_ci        if (stat(fileName.c_str(), &st) == 0) {
85fb299fa2Sopenharmony_ci            std::string tmpName = dp->d_name;
86fb299fa2Sopenharmony_ci            if (tmpName == "." || tmpName == "..") {
87fb299fa2Sopenharmony_ci                continue;
88fb299fa2Sopenharmony_ci            }
89fb299fa2Sopenharmony_ci            if (isRecursive && S_ISDIR(st.st_mode)) {
90fb299fa2Sopenharmony_ci                totalSize += GetFilesFromDirectory(fileName, files, isRecursive);
91fb299fa2Sopenharmony_ci            }
92fb299fa2Sopenharmony_ci            files.push_back(fileName);
93fb299fa2Sopenharmony_ci            totalSize += st.st_size;
94fb299fa2Sopenharmony_ci        }
95fb299fa2Sopenharmony_ci    }
96fb299fa2Sopenharmony_ci    closedir(dirp);
97fb299fa2Sopenharmony_ci    return totalSize;
98fb299fa2Sopenharmony_ci}
99fb299fa2Sopenharmony_ci
100fb299fa2Sopenharmony_cibool RemoveDir(const std::string &path)
101fb299fa2Sopenharmony_ci{
102fb299fa2Sopenharmony_ci    if (path.empty()) {
103fb299fa2Sopenharmony_ci        LOG(ERROR) << "input path is empty.";
104fb299fa2Sopenharmony_ci        return false;
105fb299fa2Sopenharmony_ci    }
106fb299fa2Sopenharmony_ci    std::string strPath = path;
107fb299fa2Sopenharmony_ci    if (strPath.at(strPath.length() - 1) != '/') {
108fb299fa2Sopenharmony_ci        strPath.append("/");
109fb299fa2Sopenharmony_ci    }
110fb299fa2Sopenharmony_ci    DIR *d = opendir(strPath.c_str());
111fb299fa2Sopenharmony_ci    if (d != nullptr) {
112fb299fa2Sopenharmony_ci        struct dirent *dt = nullptr;
113fb299fa2Sopenharmony_ci        dt = readdir(d);
114fb299fa2Sopenharmony_ci        while (dt != nullptr) {
115fb299fa2Sopenharmony_ci            if (strcmp(dt->d_name, "..") == 0 || strcmp(dt->d_name, ".") == 0) {
116fb299fa2Sopenharmony_ci                dt = readdir(d);
117fb299fa2Sopenharmony_ci                continue;
118fb299fa2Sopenharmony_ci            }
119fb299fa2Sopenharmony_ci            struct stat st {};
120fb299fa2Sopenharmony_ci            auto file_name = strPath + std::string(dt->d_name);
121fb299fa2Sopenharmony_ci            stat(file_name.c_str(), &st);
122fb299fa2Sopenharmony_ci            if (S_ISDIR(st.st_mode)) {
123fb299fa2Sopenharmony_ci                RemoveDir(file_name);
124fb299fa2Sopenharmony_ci            } else {
125fb299fa2Sopenharmony_ci                remove(file_name.c_str());
126fb299fa2Sopenharmony_ci            }
127fb299fa2Sopenharmony_ci            dt = readdir(d);
128fb299fa2Sopenharmony_ci        }
129fb299fa2Sopenharmony_ci        closedir(d);
130fb299fa2Sopenharmony_ci    }
131fb299fa2Sopenharmony_ci    return rmdir(strPath.c_str()) == 0 ? true : false;
132fb299fa2Sopenharmony_ci}
133fb299fa2Sopenharmony_ci
134fb299fa2Sopenharmony_cibool IsFileExist(const std::string &path)
135fb299fa2Sopenharmony_ci{
136fb299fa2Sopenharmony_ci    struct stat st {};
137fb299fa2Sopenharmony_ci    if (stat(path.c_str(), &st) == 0 && S_ISREG(st.st_mode)) {
138fb299fa2Sopenharmony_ci        return true;
139fb299fa2Sopenharmony_ci    }
140fb299fa2Sopenharmony_ci    return false;
141fb299fa2Sopenharmony_ci}
142fb299fa2Sopenharmony_ci
143fb299fa2Sopenharmony_cibool IsDirExist(const std::string &path)
144fb299fa2Sopenharmony_ci{
145fb299fa2Sopenharmony_ci    struct stat st {};
146fb299fa2Sopenharmony_ci    if (stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {
147fb299fa2Sopenharmony_ci        return true;
148fb299fa2Sopenharmony_ci    }
149fb299fa2Sopenharmony_ci    return false;
150fb299fa2Sopenharmony_ci}
151fb299fa2Sopenharmony_ci} // Utils
152fb299fa2Sopenharmony_ci} // updater
153