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