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