1 /*
2  * Copyright (C) 2022 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 #include <dirent.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <unistd.h>
19 
20 #include <algorithm>
21 #include <cstdio>
22 #include <filesystem>
23 
24 #include "file_deal.h"
25 #include "hilog_wrapper.h"
26 
27 namespace fs = std::filesystem;
28 namespace OHOS {
29 namespace WallpaperMgrService {
30 constexpr mode_t MODE = 0740;
FileDeal(void)31 FileDeal::FileDeal(void)
32 {
33 }
~FileDeal()34 FileDeal::~FileDeal()
35 {
36 }
IsDirExist(std::string path)37 bool FileDeal::IsDirExist(std::string path)
38 {
39     DIR *dp;
40     if ((dp = opendir(path.c_str())) == NULL) {
41         HILOG_ERROR("FileDeal : openDir  is not exist, errInfo=%{public}s", strerror(errno));
42         return false;
43     }
44     closedir(dp);
45     return true;
46 }
47 
Mkdir(const std::string & path)48 bool FileDeal::Mkdir(const std::string &path)
49 {
50     if (!IsDirExist(path)) {
51         if (mkdir(path.c_str(), MODE) != 0) {
52             HILOG_ERROR("FileDeal : mkdir errInfo=%{public}s", strerror(errno));
53             return false;
54         }
55     }
56     return true;
57 }
58 
CopyFile(const std::string & sourceFile,const std::string & newFile)59 bool FileDeal::CopyFile(const std::string &sourceFile, const std::string &newFile)
60 {
61     std::filesystem::path dstPath(newFile);
62     std::filesystem::path srcPath(sourceFile);
63     std::error_code errCode;
64     if (!std::filesystem::copy_file(srcPath, dstPath, std::filesystem::copy_options::overwrite_existing, errCode)) {
65         HILOG_ERROR("Failed to copy file, error code: %{public}d", errCode.value());
66         return false;
67     }
68     if (!ForcedRefreshDisk(newFile)) {
69         HILOG_WARN("ForcedRefreshDisk failed!");
70     }
71     return true;
72 }
73 
DeleteFile(const std::string & sourceFile)74 bool FileDeal::DeleteFile(const std::string &sourceFile)
75 {
76     if (!IsFileExist(sourceFile)) {
77         return true;
78     }
79     if (remove(sourceFile.c_str()) < 0) {
80         HILOG_ERROR("Failed to remove source file, errInfo=%{public}s.", strerror(errno));
81         return false;
82     }
83     return true;
84 }
85 
DeleteDir(const std::string & path,bool deleteRootDir)86 bool FileDeal::DeleteDir(const std::string &path, bool deleteRootDir)
87 {
88     DIR *dir = opendir(path.c_str());
89     if (dir == nullptr) {
90         return false;
91     }
92     dirent *dirent;
93     while ((dirent = readdir(dir)) != nullptr) {
94         if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) {
95             continue;
96         }
97         std::string fullPath = path;
98         if (path[path.size() - 1] != '/') {
99             fullPath += '/';
100         }
101         fullPath += dirent->d_name;
102         if (dirent->d_type == DT_DIR) {
103             if (!DeleteDir(fullPath)) {
104                 closedir(dir);
105                 return false;
106             }
107         } else if (remove(fullPath.c_str()) < 0) {
108             HILOG_ERROR("remove failed, fullPath=%{public}s, errInfo=%{public}s", fullPath.c_str(), strerror(errno));
109             closedir(dir);
110             return false;
111         }
112     }
113     closedir(dir);
114     if (deleteRootDir && rmdir(path.c_str()) != 0) {
115         HILOG_ERROR("remove failed, path=%{public}s, errInfo=%{public}s", path.c_str(), strerror(errno));
116         return false;
117     }
118     return true;
119 }
120 
IsFileExist(const std::string & name)121 bool FileDeal::IsFileExist(const std::string &name)
122 {
123     if (access(name.c_str(), F_OK) != 0) {
124         HILOG_DEBUG("FileDeal : access errInfo=%{public}s", strerror(errno));
125         return false;
126     }
127     return true;
128 }
129 
GetExtension(const std::string & filePath)130 std::string FileDeal::GetExtension(const std::string &filePath)
131 {
132     std::string filename = filePath;
133     std::string extension = "";
134     std::string::size_type pos = filePath.find_last_of('/');
135     if (pos != std::string::npos) {
136         if (pos + 1 < filePath.length()) {
137             filename = filePath.substr(pos + 1);
138         }
139     }
140 
141     pos = filename.find_last_of('.');
142     if (pos != std::string::npos && pos + 1 < filename.length()) {
143         extension = filename.substr(pos);
144         std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
145     }
146     return extension;
147 }
GetRealPath(const std::string & inOriPath,std::string & outRealPath)148 bool FileDeal::GetRealPath(const std::string &inOriPath, std::string &outRealPath)
149 {
150     char realPath[PATH_MAX + 1] = { 0x00 };
151     if (inOriPath.size() > PATH_MAX || realpath(inOriPath.c_str(), realPath) == nullptr) {
152         HILOG_ERROR("get real path fail!");
153         return false;
154     }
155     outRealPath = std::string(realPath);
156     if (!IsFileExist(outRealPath)) {
157         HILOG_ERROR("real path file is not exist! %{public}s", outRealPath.c_str());
158         return false;
159     }
160     if (outRealPath != inOriPath) {
161         HILOG_ERROR("illegal file path input %{public}s", inOriPath.c_str());
162         return false;
163     }
164     return true;
165 }
IsZipFile(const std::string & filePath)166 bool FileDeal::IsZipFile(const std::string &filePath)
167 {
168     fs::path file(filePath);
169     if (fs::exists(file) && fs::is_regular_file(file)) {
170         std::string extension = file.extension().string();
171         if (extension == ".zip") {
172             return true;
173         }
174     }
175     HILOG_ERROR("this is not a zip.filePath:%{private}s", filePath.c_str());
176     return false;
177 }
ForcedRefreshDisk(const std::string & sourcePath)178 bool FileDeal::ForcedRefreshDisk(const std::string &sourcePath)
179 {
180     std::string fileRealPath;
181     if (!GetRealPath(sourcePath, fileRealPath)) {
182         HILOG_ERROR("get real path file failed!");
183         return false;
184     }
185     FILE *file = std::fopen(fileRealPath.c_str(), "rb");
186     if (file == nullptr) {
187         HILOG_ERROR("Fopen failed, %{public}s, %{public}s", fileRealPath.c_str(), strerror(errno));
188         return false;
189     }
190     if (fflush(file) != 0) {
191         HILOG_ERROR("fflush file failed, errno=%{public}d", errno);
192         fclose(file);
193         return false;
194     }
195     if (fsync(fileno(file)) != 0) {
196         HILOG_ERROR("fsync file failed, errno=%{public}d", errno);
197         fclose(file);
198         return false;
199     }
200     (void)fclose(file);
201     return true;
202 }
203 } // namespace WallpaperMgrService
204 } // namespace OHOS
205