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 "file_utils.h"
17
18 #include <fcntl.h>
19 #include <fstream>
20 #include <sys/time.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23
24 #include "font_hilog.h"
25 #include "securec.h"
26
27 namespace OHOS {
28 namespace Global {
29 namespace FontManager {
30 static constexpr int32_t MAX_SIZE = 1024 * 20;
31 static constexpr uint32_t TIME_STRING_LENGTH = 20;
32 static constexpr uint32_t BEGIN_YEAR = 1900;
33
CheckPathExist(const std::string & pathName)34 bool FileUtils::CheckPathExist(const std::string &pathName)
35 {
36 if (pathName.empty()) {
37 FONT_LOGE("CheckPathExsit pathName is empty.");
38 return false;
39 }
40 std::error_code errorCode;
41 bool ret = std::filesystem::exists(pathName, errorCode);
42 if (errorCode.operator bool()) {
43 FONT_LOGE("CheckPathExsit %{public}s exists error, error code = %{public}d",
44 pathName.c_str(), errorCode.value());
45 return false;
46 }
47 return ret;
48 }
49
CreateFileWithPermission(const std::string & filePath,const std::string & defalutStr)50 bool FileUtils::CreateFileWithPermission(const std::string &filePath, const std::string &defalutStr)
51 {
52 if (filePath.empty() || strstr(filePath.c_str(), "/.") != NULL || strstr(filePath.c_str(), "./") != NULL) {
53 FONT_LOGE("filePath %{public}s is invalid", filePath.c_str());
54 return false;
55 }
56 std::error_code errorCode;
57 std::filesystem::path path(filePath);
58 std::fstream file(path, std::ios::out | std::ios::trunc);
59 if (!file) {
60 FONT_LOGE("Create File path %{public}s failed", filePath.c_str());
61 return false;
62 }
63 if (!defalutStr.empty()) {
64 file << defalutStr;
65 }
66 file.close();
67
68 std::filesystem::permissions(
69 filePath, std::filesystem::perms::others_write, std::filesystem::perm_options::remove, errorCode);
70 if (errorCode.operator bool()) {
71 FONT_LOGE("Assign permissions failed, path = %{public}s,error message : %{public}s",
72 filePath.c_str(), errorCode.message().c_str());
73 return false;
74 }
75 return true;
76 }
77
CreatDirWithPermission(const std::string & fileDir)78 bool FileUtils::CreatDirWithPermission(const std::string &fileDir)
79 {
80 if (fileDir.empty() || strstr(fileDir.c_str(), "/.") != NULL || strstr(fileDir.c_str(), "./") != NULL) {
81 FONT_LOGE("dirName %{public}s is invalid", fileDir.c_str());
82 return false;
83 }
84 std::error_code errorCode;
85 std::filesystem::create_directory(fileDir, errorCode);
86 if (errorCode.operator bool()) {
87 FONT_LOGE("Create directory dir %{public}s fail, error message : %{public}s", fileDir.c_str(),
88 errorCode.message().c_str());
89 return false;
90 }
91 std::filesystem::permissions(fileDir, std::filesystem::perms::others_write,
92 std::filesystem::perm_options::remove, errorCode);
93 if (errorCode.operator bool()) {
94 FONT_LOGE("Assign permissions failed, path = %{public}s,error message : %{public}s", fileDir.c_str(),
95 errorCode.message().c_str());
96 return false;
97 }
98 return true;
99 }
100
GetFilePathByFd(const int32_t & fd)101 std::string FileUtils::GetFilePathByFd(const int32_t &fd)
102 {
103 auto filePath = std::make_unique<char[]>(PATH_MAX);
104 if (filePath == nullptr) {
105 FONT_LOGE("make_unique failed , filePath is null !");
106 return "";
107 }
108 std::string linkPath = std::string("/proc/") + std::to_string(getpid()) + "/fd/" + std::to_string(fd);
109 ssize_t pathLen = readlink(linkPath.c_str(), filePath.get(), PATH_MAX - 1);
110 if (pathLen < 0) {
111 FONT_LOGE("fd readlink: %{private}s failed, errno: %{public}d", linkPath.c_str(), errno);
112 return "";
113 }
114 filePath[pathLen] = '\0';
115 return std::string(filePath.get());
116 }
117
GetFileName(const std::string & path)118 std::string FileUtils::GetFileName(const std::string &path)
119 {
120 std::string split = "/";
121 size_t pos = path.find_last_of(split);
122 if (pos == std::string::npos) {
123 return path;
124 }
125 return path.substr(pos + 1);
126 }
127
CopyFile(int32_t sourceFd,const std::string & path)128 bool FileUtils::CopyFile(int32_t sourceFd, const std::string& path)
129 {
130 constexpr int32_t filePermission = 0644;
131 int32_t targetFd = open(path.c_str(), O_WRONLY | O_CREAT | O_SYNC, filePermission);
132 bool ret = CopyFileByFd(sourceFd, targetFd);
133 if (targetFd >= 0) {
134 close(targetFd);
135 }
136 return ret;
137 }
138
CopyFileByFd(int32_t sourceFd,int32_t targetFd)139 bool FileUtils::CopyFileByFd(int32_t sourceFd, int32_t targetFd)
140 {
141 if (sourceFd < 0) {
142 FONT_LOGE("Failed to open source file");
143 return false;
144 }
145 struct stat sourceStat;
146 if (fstat(sourceFd, &sourceStat) < 0) {
147 FONT_LOGE("Failed to get source file stat");
148 return false;
149 }
150 if (targetFd < 0) {
151 FONT_LOGE("Failed to write to target file");
152 return false;
153 }
154 lseek(sourceFd, 0, SEEK_SET);
155 lseek(targetFd, 0, SEEK_SET);
156 constexpr int32_t bufferSize = MAX_SIZE;
157 char buffer[bufferSize];
158 int32_t bytesRead = 0;
159 int32_t bytesWritten = 0;
160 while ((bytesRead = read(sourceFd, buffer, sizeof(buffer))) > 0) {
161 bytesWritten = write(targetFd, buffer, bytesRead);
162 if (bytesWritten != bytesRead) {
163 FONT_LOGE("Failed to write to target file");
164 return false;
165 }
166 }
167 return true;
168 }
169
GetFileTime()170 std::string FileUtils::GetFileTime()
171 {
172 struct timeval time;
173 gettimeofday(&time, nullptr);
174 struct tm timeInfo;
175 localtime_r(&time.tv_sec, &timeInfo);
176
177 char timeBuf[TIME_STRING_LENGTH] = {0};
178 int result = sprintf_s(timeBuf, TIME_STRING_LENGTH, "%04u%02d%02d-%02d%02d%02d",
179 timeInfo.tm_year + BEGIN_YEAR,
180 timeInfo.tm_mon + 1,
181 timeInfo.tm_mday,
182 timeInfo.tm_hour,
183 timeInfo.tm_min,
184 timeInfo.tm_sec);
185 if (result < 0) {
186 FONT_LOGE("GetFileTimeStr sprintf_s error");
187 return "";
188 }
189 return timeBuf;
190 }
191
RenameFile(const std::string & src,const std::string & dest)192 bool FileUtils::RenameFile(const std::string& src, const std::string& dest)
193 {
194 if (!CheckPathExist(src)) {
195 FONT_LOGI("file %{public}s is not exist", src.c_str());
196 return false;
197 }
198 std::error_code errorCode;
199 std::filesystem::rename(src, dest, errorCode);
200 if (errorCode.operator bool()) {
201 FONT_LOGE("filesystem::rename error, error code = %{public}d", errorCode.value());
202 return false;
203 }
204 return true;
205 }
206
RemoveFile(const std::string & fileName)207 bool FileUtils::RemoveFile(const std::string &fileName)
208 {
209 if (!CheckPathExist(fileName)) {
210 FONT_LOGI("file %{public}s is not exist", fileName.c_str());
211 return true;
212 }
213 return RemoveAll(fileName);
214 }
215
DeleteDir(const std::string & rootPath,bool isDeleteRootDir)216 void FileUtils::DeleteDir(const std::string &rootPath, bool isDeleteRootDir)
217 {
218 if (!CheckPathExist(rootPath)) {
219 FONT_LOGI("dir %{public}s is not exist", rootPath.c_str());
220 return;
221 }
222 auto myPath = std::filesystem::path(rootPath);
223 if (isDeleteRootDir) {
224 RemoveAll(myPath);
225 return;
226 }
227
228 for (auto const &dirEntry : std::filesystem::directory_iterator{ myPath }) {
229 RemoveAll(dirEntry.path());
230 }
231 }
232
RemoveAll(const std::filesystem::path & path)233 bool FileUtils::RemoveAll(const std::filesystem::path &path)
234 {
235 std::error_code errorCode;
236 std::filesystem::remove_all(path, errorCode);
237 if (errorCode.operator bool()) {
238 FONT_LOGI("remove dir %{public}s fail, error message : %{public}s", path.c_str(),
239 errorCode.message().c_str());
240 return false;
241 }
242 return true;
243 }
244 } // namespace FontManager
245 } // namespace Global
246 } // namespace OHOS
247
248