• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21 
22 #include "hks_file_operator.h"
23 
24 #include <dirent.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 
30 #include "hks_log.h"
31 #include "hks_mem.h"
32 #include "hks_template.h"
33 #include "securec.h"
34 
GetFileName(const char * path,const char * fileName,char * fullFileName,uint32_t fullFileNameLen)35 static int32_t GetFileName(const char *path, const char *fileName, char *fullFileName, uint32_t fullFileNameLen)
36 {
37     if (path != NULL) {
38         if (strncpy_s(fullFileName, fullFileNameLen, path, strlen(path)) != EOK) {
39             return HKS_ERROR_INTERNAL_ERROR;
40         }
41 
42         if (path[strlen(path) - 1] != '/') {
43             if (strncat_s(fullFileName, fullFileNameLen, "/", strlen("/")) != EOK) {
44                 return HKS_ERROR_INTERNAL_ERROR;
45             }
46         }
47 
48         if (strncat_s(fullFileName, fullFileNameLen, fileName, strlen(fileName)) != EOK) {
49             return HKS_ERROR_INTERNAL_ERROR;
50         }
51     } else {
52         if (strncpy_s(fullFileName, fullFileNameLen, fileName, strlen(fileName)) != EOK) {
53             return HKS_ERROR_INTERNAL_ERROR;
54         }
55     }
56 
57     return HKS_SUCCESS;
58 }
59 
GetFullFileName(const char * path,const char * fileName,char ** fullFileName)60 static int32_t GetFullFileName(const char *path, const char *fileName, char **fullFileName)
61 {
62     uint32_t nameLen = HKS_MAX_FILE_NAME_LEN;
63     char *tmpFileName = (char *)HksMalloc(nameLen);
64     HKS_IF_NULL_RETURN(tmpFileName, HKS_ERROR_MALLOC_FAIL)
65     (void)memset_s(tmpFileName, nameLen, 0, nameLen);
66 
67     int32_t ret = GetFileName(path, fileName, tmpFileName, nameLen);
68     if (ret != HKS_SUCCESS) {
69         HKS_LOG_E("get full fileName failed");
70         HKS_FREE_PTR(tmpFileName);
71         return ret;
72     }
73 
74     *fullFileName = tmpFileName;
75     return HKS_SUCCESS;
76 }
77 
IsFileExist(const char * fileName)78 static int32_t IsFileExist(const char *fileName)
79 {
80     if (access(fileName, F_OK) != 0) {
81         return HKS_ERROR_NOT_EXIST;
82     }
83 
84     return HKS_SUCCESS;
85 }
86 
FileRead(const char * fileName,uint32_t offset,uint8_t * buf,uint32_t len)87 static uint32_t FileRead(const char *fileName, uint32_t offset, uint8_t *buf, uint32_t len)
88 {
89     (void)offset;
90     HKS_IF_NOT_SUCC_RETURN(IsFileExist(fileName), 0)
91 
92     if (strstr(fileName, "../") != NULL) {
93         HKS_LOG_E("invalid filePath, path %" LOG_PUBLIC "s", fileName);
94         return 0;
95     }
96 
97     char filePath[PATH_MAX + 1] = {0};
98     if (realpath(fileName, filePath) == NULL) {
99         HKS_LOG_E("invalid filePath, path %" LOG_PUBLIC "s", fileName);
100         return 0;
101     }
102 
103     FILE *fp = fopen(filePath, "rb");
104     HKS_IF_NULL_LOGE_RETURN(fp, 0, "failed to open file, errno = 0x%" LOG_PUBLIC "x", errno)
105 
106     uint32_t size = fread(buf, 1, len, fp);
107     if (fclose(fp) < 0) {
108         HKS_LOG_E("failed to close file, errno = 0x%" LOG_PUBLIC "x", errno);
109         return 0;
110     }
111 
112     return size;
113 }
114 
FileSize(const char * fileName)115 static uint32_t FileSize(const char *fileName)
116 {
117     HKS_IF_NOT_SUCC_RETURN(IsFileExist(fileName), 0)
118 
119     struct stat fileStat;
120     (void)memset_s(&fileStat, sizeof(fileStat), 0, sizeof(fileStat));
121     if (stat(fileName, &fileStat) != 0) {
122         HKS_LOG_E("file stat fail, errno = 0x%" LOG_PUBLIC "x", errno);
123         return 0;
124     }
125 
126     return fileStat.st_size;
127 }
128 
FileWrite(const char * fileName,uint32_t offset,const uint8_t * buf,uint32_t len)129 static int32_t FileWrite(const char *fileName, uint32_t offset, const uint8_t *buf, uint32_t len)
130 {
131     (void)offset;
132     char filePath[PATH_MAX + 1] = {0};
133     if (memcpy_s(filePath, sizeof(filePath) - 1, fileName, strlen(fileName)) != EOK) {
134         return HKS_ERROR_INSUFFICIENT_MEMORY;
135     }
136 
137     if (strstr(filePath, "../") != NULL) {
138         HKS_LOG_E("invalid filePath!");
139         return HKS_ERROR_INVALID_KEY_FILE;
140     }
141     (void)realpath(fileName, filePath);
142 
143     /* caller function ensures that the folder exists */
144     FILE *fp = fopen(filePath, "wb+");
145     HKS_IF_NULL_LOGE_RETURN(fp, HKS_ERROR_OPEN_FILE_FAIL, "open file fail, errno = 0x%" LOG_PUBLIC "x", errno)
146 
147     if (chmod(filePath, S_IRUSR | S_IWUSR) < 0) {
148         HKS_LOG_E("chmod file fail, errno = 0x%" LOG_PUBLIC "x", errno);
149         fclose(fp);
150         return HKS_ERROR_OPEN_FILE_FAIL;
151     }
152 
153     uint32_t size = fwrite(buf, 1, len, fp);
154     if (size != len) {
155         HKS_LOG_E("write file size fail, errno = 0x%" LOG_PUBLIC "x", errno);
156         fclose(fp);
157         return HKS_ERROR_WRITE_FILE_FAIL;
158     }
159 
160     if (fflush(fp) < 0) {
161         HKS_LOG_E("fflush file fail, errno = 0x%" LOG_PUBLIC "x", errno);
162         fclose(fp);
163         return HKS_ERROR_WRITE_FILE_FAIL;
164     }
165 
166     int fd = fileno(fp);
167     if (fd < 0) {
168         HKS_LOG_E("fileno fail, errno = 0x%" LOG_PUBLIC "x", errno);
169         fclose(fp);
170         return HKS_ERROR_WRITE_FILE_FAIL;
171     }
172 
173     if (fsync(fd) < 0) {
174         HKS_LOG_E("sync file fail, errno = 0x%" LOG_PUBLIC "x", errno);
175         fclose(fp);
176         return HKS_ERROR_WRITE_FILE_FAIL;
177     }
178 
179     if (fclose(fp) < 0) {
180         HKS_LOG_E("failed to close file, errno = 0x%" LOG_PUBLIC "x", errno);
181         return HKS_ERROR_CLOSE_FILE_FAIL;
182     }
183 
184     return HKS_SUCCESS;
185 }
186 
FileRemove(const char * fileName)187 static int32_t FileRemove(const char *fileName)
188 {
189     int32_t ret = IsFileExist(fileName);
190     HKS_IF_NOT_SUCC_RETURN(ret, HKS_SUCCESS) /* if file not exist, return ok */
191 
192     struct stat tmp;
193     if (stat(fileName, &tmp) != 0) {
194         return HKS_ERROR_INTERNAL_ERROR;
195     }
196 
197     if (S_ISDIR(tmp.st_mode)) {
198         return HKS_ERROR_INVALID_ARGUMENT;
199     }
200 
201     if ((unlink(fileName) != 0) && (errno != ENOENT)) {
202         HKS_LOG_E("failed to remove file: errno = 0x%" LOG_PUBLIC "x", errno);
203         return HKS_ERROR_REMOVE_FILE_FAIL;
204     }
205 
206     return HKS_SUCCESS;
207 }
208 
HksFileRemove(const char * path,const char * fileName)209 int32_t HksFileRemove(const char *path, const char *fileName)
210 {
211     HKS_IF_NULL_RETURN(fileName, HKS_ERROR_INVALID_ARGUMENT)
212 
213     char *fullFileName = NULL;
214     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
215     HKS_IF_NOT_SUCC_RETURN(ret, ret)
216 
217     ret = FileRemove(fullFileName);
218     HKS_FREE_PTR(fullFileName);
219     return ret;
220 }
221 
HksIsFileExist(const char * path,const char * fileName)222 int32_t HksIsFileExist(const char *path, const char *fileName)
223 {
224     HKS_IF_NULL_RETURN(fileName, HKS_ERROR_NULL_POINTER)
225 
226     char *fullFileName = NULL;
227     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
228     HKS_IF_NOT_SUCC_RETURN(ret, ret)
229 
230     ret = IsFileExist(fullFileName);
231     HKS_FREE_PTR(fullFileName);
232     return ret;
233 }
234 
HksIsDirExist(const char * path)235 int32_t HksIsDirExist(const char *path)
236 {
237     HKS_IF_NULL_RETURN(path, HKS_ERROR_NULL_POINTER)
238     return IsFileExist(path);
239 }
240 
HksMakeDir(const char * path)241 int32_t HksMakeDir(const char *path)
242 {
243     int result = mkdir(path, S_IRWXU);
244     if (result == 0) {
245         return HKS_SUCCESS;
246     } else {
247         switch (errno) {
248             case EEXIST:
249                 return HKS_ERROR_ALREADY_EXISTS;
250             default:
251                 return HKS_ERROR_MAKE_DIR_FAIL;
252         }
253     }
254 }
255 
HksOpenDir(const char * path)256 void *HksOpenDir(const char *path)
257 {
258     return (void *)opendir(path);
259 }
260 
HksCloseDir(void * dirp)261 int32_t HksCloseDir(void *dirp)
262 {
263     return closedir((DIR *)dirp);
264 }
265 
HksGetDirFile(void * dirp,struct HksFileDirentInfo * direntInfo)266 int32_t HksGetDirFile(void *dirp, struct HksFileDirentInfo *direntInfo)
267 {
268     DIR *dir = (DIR *)dirp;
269     struct dirent *dire = readdir(dir);
270 
271     while (dire != NULL) {
272         if (dire->d_type != DT_REG) { /* only care about files. */
273             dire = readdir(dir);
274             continue;
275         }
276 
277         uint32_t len = strlen(dire->d_name);
278         if (memcpy_s(direntInfo->fileName, sizeof(direntInfo->fileName) - 1, dire->d_name, len) != EOK) {
279             return HKS_ERROR_INSUFFICIENT_MEMORY;
280         }
281         direntInfo->fileName[len] = '\0';
282         return HKS_SUCCESS;
283     }
284 
285     return HKS_ERROR_NOT_EXIST;
286 }
287 
HksGetStoragePath(enum HksStoragePathType pathType,char * path,uint32_t * len)288 int32_t HksGetStoragePath(enum HksStoragePathType pathType, char *path, uint32_t *len)
289 {
290     if ((path == NULL) || (len == NULL) || (*len <= 1)) {
291         return HKS_ERROR_INVALID_ARGUMENT;
292     }
293     errno_t ret;
294     uint32_t pathLen;
295     if (pathType == HKS_STORAGE_MAIN_PATH) {
296         pathLen = strlen(HKS_KEY_STORE_PATH);
297         ret = memcpy_s(path, *len - 1, HKS_KEY_STORE_PATH, pathLen);
298     } else if (pathType == HKS_STORAGE_BACKUP_PATH) {
299         pathLen = strlen(HKS_KEY_STORE_BAK_PATH);
300         ret = memcpy_s(path, *len - 1, HKS_KEY_STORE_BAK_PATH, pathLen);
301     } else {
302         return HKS_ERROR_INVALID_ARGUMENT;
303     }
304     if (ret != EOK) {
305         HKS_LOG_E("memcpy failed");
306         return HKS_ERROR_INSUFFICIENT_MEMORY;
307     }
308     path[pathLen] = '\0';
309     *len = pathLen + 1;
310     return HKS_SUCCESS;
311 }
312 
HksRemoveDir(const char * dirPath)313 int32_t HksRemoveDir(const char *dirPath)
314 {
315     struct stat fileStat;
316     int32_t ret = stat(dirPath, &fileStat);
317     if (ret != 0) {
318         HKS_LOG_E("file stat failed");
319         return HKS_FAILURE;
320     }
321 
322     if (!S_ISDIR(fileStat.st_mode)) {
323         HKS_LOG_E("path is not dir");
324         return HKS_FAILURE;
325     }
326 
327     DIR *dir = opendir(dirPath);
328     HKS_IF_NULL_LOGE_RETURN(dir, HKS_ERROR_OPEN_FILE_FAIL, "open dir failed")
329 
330     struct dirent *dire = readdir(dir);
331     while (dire != NULL) {
332         if (dire->d_type == DT_REG) { /* only care about files. */
333             ret = HksFileRemove(dirPath, dire->d_name);
334             HKS_IF_NOT_SUCC_LOGE(ret, "remove file failed when remove dir files, ret = %" LOG_PUBLIC "d.", ret)
335         }
336         dire = readdir(dir);
337     }
338 
339     closedir(dir);
340     return HKS_SUCCESS;
341 }
342 
HksDeletDirPartTwo(const char * path)343 static int32_t HksDeletDirPartTwo(const char *path)
344 {
345     int32_t ret;
346     char deletePath[HKS_MAX_FILE_NAME_LEN] = {0};
347     DIR *dir = opendir(path);
348     HKS_IF_NULL_LOGE_RETURN(dir, HKS_ERROR_OPEN_FILE_FAIL, "open dir failed")
349     struct dirent *dire = readdir(dir);
350     while (dire != NULL) {
351         if (strncpy_s(deletePath, sizeof(deletePath), path, strlen(path)) != EOK) {
352             closedir(dir);
353             return HKS_ERROR_INTERNAL_ERROR;
354         }
355 
356         if (deletePath[strlen(deletePath) - 1] != '/') {
357             if (strncat_s(deletePath, sizeof(deletePath), "/", strlen("/")) != EOK) {
358                 closedir(dir);
359                 return HKS_ERROR_INTERNAL_ERROR;
360             }
361         }
362 
363         if (strncat_s(deletePath, sizeof(deletePath), dire->d_name, strlen(dire->d_name)) != EOK) {
364             closedir(dir);
365             return HKS_ERROR_INTERNAL_ERROR;
366         }
367 
368         if ((strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
369             (void)remove(deletePath);
370         }
371         dire = readdir(dir);
372     }
373     closedir(dir);
374     ret = remove(path);
375     return ret;
376 }
377 
HksDeletDirPartOne(const char * path)378 static int32_t HksDeletDirPartOne(const char *path)
379 {
380     int32_t ret;
381     char deletePath[HKS_MAX_FILE_NAME_LEN] = {0};
382     DIR *dir = opendir(path);
383     HKS_IF_NULL_LOGE_RETURN(dir, HKS_ERROR_OPEN_FILE_FAIL, "open dir failed")
384     struct dirent *dire = readdir(dir);
385     while (dire != NULL) {
386         if (strncpy_s(deletePath, sizeof(deletePath), path, strlen(path)) != EOK) {
387             closedir(dir);
388             return HKS_ERROR_INTERNAL_ERROR;
389         }
390 
391         if (deletePath[strlen(deletePath) - 1] != '/') {
392             if (strncat_s(deletePath, sizeof(deletePath), "/", strlen("/")) != EOK) {
393                 closedir(dir);
394                 return HKS_ERROR_INTERNAL_ERROR;
395             }
396         }
397 
398         if (strncat_s(deletePath, sizeof(deletePath), dire->d_name, strlen(dire->d_name)) != EOK) {
399             closedir(dir);
400             return HKS_ERROR_INTERNAL_ERROR;
401         }
402 
403         if (dire->d_type == DT_DIR && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
404             HksDeletDirPartTwo(deletePath);
405         } else if (dire->d_type != DT_DIR) {
406             (void)remove(deletePath);
407         }
408         dire = readdir(dir);
409     }
410     closedir(dir);
411     ret = remove(path);
412     return ret;
413 }
414 
HksDeleteDir(const char * path)415 int32_t HksDeleteDir(const char *path)
416 {
417     int32_t ret;
418     char deletePath[HKS_MAX_FILE_NAME_LEN] = { 0 };
419 
420     DIR *dir = opendir(path);
421     HKS_IF_NULL_LOGE_RETURN(dir, HKS_ERROR_OPEN_FILE_FAIL, "open dir failed")
422     struct dirent *dire = readdir(dir);
423     while (dire != NULL) {
424         if (strncpy_s(deletePath, sizeof(deletePath), path, strlen(path)) != EOK) {
425             closedir(dir);
426             return HKS_ERROR_INTERNAL_ERROR;
427         }
428 
429         if (deletePath[strlen(deletePath) - 1] != '/') {
430             if (strncat_s(deletePath, sizeof(deletePath), "/", strlen("/")) != EOK) {
431                 closedir(dir);
432                 return HKS_ERROR_INTERNAL_ERROR;
433             }
434         }
435 
436         if (strncat_s(deletePath, sizeof(deletePath), dire->d_name, strlen(dire->d_name)) != EOK) {
437             closedir(dir);
438             return HKS_ERROR_INTERNAL_ERROR;
439         }
440 
441         if (dire->d_type == DT_DIR && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
442             HksDeletDirPartOne(deletePath);
443         } else if (dire->d_type != DT_DIR) {
444             (void)remove(deletePath);
445         }
446         dire = readdir(dir);
447     }
448     closedir(dir);
449     ret = remove(path);
450     return ret;
451 }
452 
HksFileRead(const char * path,const char * fileName,uint32_t offset,uint8_t * buf,uint32_t len)453 uint32_t HksFileRead(const char *path, const char *fileName, uint32_t offset, uint8_t *buf, uint32_t len)
454 {
455     if ((fileName == NULL) || (buf == NULL) || (len == 0)) {
456         return 0;
457     }
458 
459     char *fullFileName = NULL;
460     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
461     HKS_IF_NOT_SUCC_RETURN(ret, 0)
462 
463     uint32_t size = FileRead(fullFileName, offset, buf, len);
464     HKS_FREE_PTR(fullFileName);
465     return size;
466 }
467 
HksFileWrite(const char * path,const char * fileName,uint32_t offset,const uint8_t * buf,uint32_t len)468 int32_t HksFileWrite(const char *path, const char *fileName, uint32_t offset, const uint8_t *buf, uint32_t len)
469 {
470     if ((fileName == NULL) || (buf == NULL) || (len == 0)) {
471         return HKS_ERROR_INVALID_ARGUMENT;
472     }
473 
474     char *fullFileName = NULL;
475     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
476     HKS_IF_NOT_SUCC_RETURN(ret, ret)
477 
478     ret = FileWrite(fullFileName, offset, buf, len);
479     HKS_FREE_PTR(fullFileName);
480     return ret;
481 }
482 
HksFileSize(const char * path,const char * fileName)483 uint32_t HksFileSize(const char *path, const char *fileName)
484 {
485     HKS_IF_NULL_RETURN(fileName, 0)
486 
487     char *fullFileName = NULL;
488     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
489     HKS_IF_NOT_SUCC_RETURN(ret, 0)
490 
491     uint32_t size = FileSize(fullFileName);
492     HKS_FREE_PTR(fullFileName);
493     return size;
494 }
495 
HksGetFileName(const char * path,const char * fileName,char * fullFileName,uint32_t fullFileNameLen)496 int32_t HksGetFileName(const char *path, const char *fileName, char *fullFileName, uint32_t fullFileNameLen)
497 {
498     return GetFileName(path, fileName, fullFileName, fullFileNameLen);
499 }