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 }