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 <stdio.h>
17 #include <stdlib.h>
18 #include <limits.h>
19 #include <errno.h>
20
21 #include <dirent.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 #ifdef _WIN32
25 #include <windows.h>
26 #endif
27
28 #include "hnp_base.h"
29
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33
GetFileSizeByHandle(FILE * file,int * size)34 int GetFileSizeByHandle(FILE *file, int *size)
35 {
36 int ret;
37 int len;
38
39 ret = fseek(file, 0, SEEK_END);
40 if (ret != 0) {
41 HNP_LOGE("fseek end unsuccess.");
42 return HNP_ERRNO_BASE_FILE_SEEK_FAILED;
43 }
44 len = ftell(file);
45 if (len < 0) {
46 HNP_LOGE("ftell unsuccess. len=%{public}d", len);
47 return HNP_ERRNO_BASE_FILE_TELL_FAILED;
48 }
49 ret = fseek(file, 0, SEEK_SET);
50 if (ret != 0) {
51 HNP_LOGE("fseek set unsuccess. ");
52 return HNP_ERRNO_BASE_FILE_SEEK_FAILED;
53 }
54 *size = len;
55 return 0;
56 }
57
ReadFileToStream(const char * filePath,char ** stream,int * streamLen)58 int ReadFileToStream(const char *filePath, char **stream, int *streamLen)
59 {
60 int ret;
61 FILE *file;
62 int size = 0;
63 char *streamTmp;
64
65 file = fopen(filePath, "rb");
66 if (file == NULL) {
67 HNP_LOGE("open file[%{public}s] unsuccess. ", filePath);
68 return HNP_ERRNO_BASE_FILE_OPEN_FAILED;
69 }
70 ret = GetFileSizeByHandle(file, &size);
71 if (ret != 0) {
72 HNP_LOGE("get file[%{public}s] size unsuccess.", filePath);
73 (void)fclose(file);
74 return ret;
75 }
76 if (size == 0) {
77 HNP_LOGE("get file[%{public}s] size is null.", filePath);
78 (void)fclose(file);
79 return HNP_ERRNO_BASE_GET_FILE_LEN_NULL;
80 }
81 streamTmp = (char*)malloc(size);
82 if (streamTmp == NULL) {
83 HNP_LOGE("malloc unsuccess. size%{public}d", size);
84 (void)fclose(file);
85 return HNP_ERRNO_NOMEM;
86 }
87 size_t readLen = fread(streamTmp, sizeof(char), size, file);
88 if (readLen != (size_t)size) {
89 HNP_LOGE("fread unsuccess. readLen=%{public}zu, size=%{public}d", readLen, size);
90 (void)fclose(file);
91 free(streamTmp);
92 return HNP_ERRNO_BASE_FILE_READ_FAILED;
93 }
94 *stream = streamTmp;
95 *streamLen = size;
96 (void)fclose(file);
97 return 0;
98 }
99
GetRealPath(char * srcPath,char * realPath)100 int GetRealPath(char *srcPath, char *realPath)
101 {
102 char dstTmpPath[MAX_FILE_PATH_LEN];
103
104 if (srcPath == NULL || realPath == NULL) {
105 return HNP_ERRNO_PARAM_INVALID;
106 }
107 #ifdef _WIN32
108 // 使用wchar_t支持处理字符串长度超过260的路径字符串
109 wchar_t wideSrcPath[MAX_FILE_PATH_LEN] = {0};
110 wchar_t wideDstPathExt[MAX_FILE_PATH_LEN] = {0};
111 MultiByteToWideChar(CP_ACP, 0, srcPath, -1, wideSrcPath, MAX_FILE_PATH_LEN);
112 DWORD ret = GetFullPathNameW(wideSrcPath, MAX_FILE_PATH_LEN, wideDstPathExt, NULL);
113 WideCharToMultiByte(CP_ACP, 0, wideDstPathExt, -1, dstTmpPath, MAX_FILE_PATH_LEN, NULL, NULL);
114 #else
115 char *ret = realpath(srcPath, dstTmpPath);
116 #endif
117 if (ret == 0) {
118 HNP_LOGE("realpath unsuccess. path=%{public}s", srcPath);
119 return HNP_ERRNO_BASE_REALPATHL_FAILED;
120 }
121 if (strlen(dstTmpPath) >= MAX_FILE_PATH_LEN) {
122 HNP_LOGE("realpath over max path len. len=%{public}d", (int)strlen(dstTmpPath));
123 return HNP_ERRNO_BASE_STRING_LEN_OVER_LIMIT;
124 }
125 if (strcpy_s(realPath, MAX_FILE_PATH_LEN, dstTmpPath) != EOK) {
126 HNP_LOGE("strcpy unsuccess.");
127 return HNP_ERRNO_BASE_COPY_FAILED;
128 }
129 return 0;
130 }
131
HnpDeleteAllFileInPath(const char * path,DIR * dir)132 static int HnpDeleteAllFileInPath(const char *path, DIR *dir)
133 {
134 int ret = 0;
135 #ifdef _WIN32
136 return ret;
137 #else
138 struct dirent *entry;
139 struct stat statbuf;
140 char filePath[MAX_FILE_PATH_LEN];
141
142 while ((entry = readdir(dir)) != NULL) {
143 if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
144 continue;
145 }
146
147 ret = sprintf_s(filePath, MAX_FILE_PATH_LEN, "%s/%s", path, entry->d_name);
148 if (ret < 0) {
149 HNP_LOGE("delete folder sprintf path[%{public}s], file[%{public}s] unsuccess.", path, entry->d_name);
150 return HNP_ERRNO_BASE_SPRINTF_FAILED;
151 }
152
153 if (lstat(filePath, &statbuf) < 0) {
154 unlink(filePath); // 如果是已被删除源文件的软链,是获取不到文件信息的,此处作删除处理
155 continue;
156 }
157
158 if (S_ISDIR(statbuf.st_mode)) {
159 /* 如果是文件夹,递归删除 */
160 ret = HnpDeleteFolder(filePath);
161 if (ret != 0) {
162 return ret;
163 }
164 } else {
165 ret = unlink(filePath);
166 if (ret != 0) {
167 HNP_LOGE("delete file unsuccess.ret=%{public}d, path=%{public}s, errno=%{public}d", ret, filePath,
168 errno);
169 return HNP_ERRNO_BASE_UNLINK_FAILED;
170 }
171 }
172 }
173
174 return 0;
175 #endif
176 }
177
HnpDeleteFolder(const char * path)178 int HnpDeleteFolder(const char *path)
179 {
180 if (access(path, F_OK) != 0) {
181 return 0;
182 }
183 DIR *dir = opendir(path);
184 if (dir == NULL) {
185 HNP_LOGE("delete folder open dir=%{public}s unsuccess ", path);
186 return HNP_ERRNO_BASE_DIR_OPEN_FAILED;
187 }
188
189 int ret = HnpDeleteAllFileInPath(path, dir);
190 closedir(dir);
191 if (ret != 0) {
192 return ret;
193 }
194
195 ret = rmdir(path);
196 if (ret != 0) {
197 HNP_LOGE("rmdir path unsuccess.ret=%{public}d, path=%{public}s, errno=%{public}d", ret, path, errno);
198 }
199 return ret;
200 }
201
HnpCreateFolder(const char * path)202 int HnpCreateFolder(const char* path)
203 {
204 int ret = 0;
205 #ifdef _WIN32
206 return ret;
207 #else
208 char *p = NULL;
209 struct stat buffer;
210
211 if (path == NULL) {
212 HNP_LOGE("delete folder param path is null");
213 return HNP_ERRNO_BASE_PARAMS_INVALID;
214 }
215
216 /* 如果目录存在,则返回 */
217 if (stat(path, &buffer) == 0) {
218 return 0;
219 }
220
221 p = strdup(path);
222 if (p == NULL) {
223 HNP_LOGE("delete folder strdup unsuccess, path=%{public}s, errno=%{public}d", path, errno);
224 return HNP_ERRNO_BASE_STRDUP_FAILED;
225 }
226
227 for (char *q = p + 1; *q; q++) {
228 if (*q != '/') {
229 continue;
230 }
231 *q = '\0';
232 if (stat(path, &buffer) != 0) {
233 ret = mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
234 if ((ret != 0) && (errno != EEXIST)) {
235 HNP_LOGE("delete folder unsuccess, ret=%{public}d, p=%{public}s, errno:%{public}d", ret, p, errno);
236 }
237 }
238 *q = '/';
239 }
240
241 if (path[strlen(path) - 1] != '/') {
242 ret = mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
243 if ((ret != 0) && (errno != EEXIST)) {
244 HNP_LOGE("delete folder unsuccess, ret=%{public}d, path=%{public}s, errno:%{public}d", ret, path, errno);
245 }
246 }
247 free(p);
248
249 if (errno == EEXIST) {
250 ret = 0;
251 }
252 return ret;
253 #endif
254 }
255
256 #ifdef __cplusplus
257 }
258 #endif