• 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 #include "cert_manager_file_operator.h"
17 
18 #include <dirent.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <limits.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24 
25 #include "securec.h"
26 
27 #include "cert_manager_mem.h"
28 #include "cm_log.h"
29 
GetFileName(const char * path,const char * fileName,char * fullFileName,uint32_t fullFileNameLen)30 static int32_t GetFileName(const char *path, const char *fileName, char *fullFileName, uint32_t fullFileNameLen)
31 {
32     if (path != NULL) {
33         if (strncpy_s(fullFileName, fullFileNameLen, path, strlen(path)) != EOK) {
34             return CMR_ERROR_INVALID_OPERATION;
35         }
36 
37         if (path[strlen(path) - 1] != '/') {
38             if (strncat_s(fullFileName, fullFileNameLen, "/", strlen("/")) != EOK) {
39                 return CMR_ERROR_INVALID_OPERATION;
40             }
41         }
42 
43         if (strncat_s(fullFileName, fullFileNameLen, fileName, strlen(fileName)) != EOK) {
44             return CMR_ERROR_INVALID_OPERATION;
45         }
46     } else {
47         if (strncpy_s(fullFileName, fullFileNameLen, fileName, strlen(fileName)) != EOK) {
48             return CMR_ERROR_INVALID_OPERATION;
49         }
50     }
51     return CMR_OK;
52 }
53 
GetFullFileName(const char * path,const char * fileName,char ** fullFileName)54 static int32_t GetFullFileName(const char *path, const char *fileName, char **fullFileName)
55 {
56     uint32_t nameLen = CM_MAX_FILE_NAME_LEN;
57     char *tmpFileName = (char *)CMMalloc(nameLen);
58     if (tmpFileName == NULL) {
59         return CMR_ERROR_MALLOC_FAIL;
60     }
61     (void)memset_s(tmpFileName, nameLen, 0, nameLen);
62 
63     int32_t ret = GetFileName(path, fileName, tmpFileName, nameLen);
64     if (ret != CMR_OK) {
65         CM_LOG_E("get full fileName failed");
66         CM_FREE_PTR(tmpFileName);
67         return ret;
68     }
69     *fullFileName = tmpFileName;
70 
71     return CMR_OK;
72 }
73 
IsFileExist(const char * fileName)74 static int32_t IsFileExist(const char *fileName)
75 {
76     if (access(fileName, F_OK) != 0) {
77         return CMR_ERROR_NOT_EXIST;
78     }
79 
80     return CMR_OK;
81 }
82 
CmIsDirExist(const char * path)83 int32_t CmIsDirExist(const char *path)
84 {
85     if (path == NULL) {
86         return CMR_ERROR_NULL_POINTER;
87     }
88     return IsFileExist(path);
89 }
90 
FileRead(const char * fileName,uint32_t offset,uint8_t * buf,uint32_t len)91 static uint32_t FileRead(const char *fileName, uint32_t offset, uint8_t *buf, uint32_t len)
92 {
93     (void)offset;
94     if (IsFileExist(fileName) != CMR_OK) {
95         return 0;
96     }
97 
98     char filePath[PATH_MAX + 1] = {0};
99     (void)realpath(fileName, filePath);
100     if (strstr(filePath, "../") != NULL) {
101         CM_LOG_E("invalid filePath");
102         return 0;
103     }
104 
105     FILE *fp = fopen(filePath, "rb");
106     if (fp == NULL) {
107         CM_LOG_E("failed to open file");
108         return 0;
109     }
110 
111     uint32_t size = fread(buf, 1, len, fp);
112     if (fclose(fp) < 0) {
113         CM_LOG_E("failed to close file");
114         return 0;
115     }
116 
117     return size;
118 }
119 
FileSize(const char * fileName)120 static uint32_t FileSize(const char *fileName)
121 {
122     if (IsFileExist(fileName) != CMR_OK) {
123         CM_LOG_E("file IsFileExist fail.");
124         return 0;
125     }
126 
127     struct stat fileStat;
128     (void)memset_s(&fileStat, sizeof(fileStat), 0, sizeof(fileStat));
129 
130     if (stat(fileName, &fileStat) != 0) {
131         CM_LOG_E("file stat fail.");
132         return 0;
133     }
134 
135     return (uint32_t)fileStat.st_size;
136 }
137 
FileWrite(const char * fileName,uint32_t offset,const uint8_t * buf,uint32_t len)138 static int32_t FileWrite(const char *fileName, uint32_t offset, const uint8_t *buf, uint32_t len)
139 {
140     (void)offset;
141     char filePath[PATH_MAX + 1] = {0};
142     if (memcpy_s(filePath, sizeof(filePath) - 1, fileName, strlen(fileName)) != EOK) {
143         return CMR_ERROR_INVALID_OPERATION;
144     }
145     (void)realpath(fileName, filePath);
146     if (strstr(filePath, "../") != NULL) {
147         CM_LOG_E("invalid filePath");
148         return CMR_ERROR_NOT_EXIST;
149     }
150 
151     int32_t fd = open(filePath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
152     if (fd < 0) {
153         CM_LOG_E("open file failed, errno = 0x%x", errno);
154         return CMR_ERROR_OPEN_FILE_FAIL;
155     }
156 
157     int32_t size = write(fd, buf, len);
158     if (size < 0) {
159         CM_LOG_E("write file failed, errno = 0x%x", errno);
160         close(fd);
161         return CMR_ERROR_WRITE_FILE_FAIL;
162     }
163     if (fsync(fd) < 0) {
164         CM_LOG_E("sync file failed");
165         close(fd);
166         return CMR_ERROR_WRITE_FILE_FAIL;
167     }
168     close(fd);
169     return CMR_OK;
170 }
171 
FileRemove(const char * fileName)172 static int32_t FileRemove(const char *fileName)
173 {
174     int32_t ret = IsFileExist(fileName);
175     if (ret != CMR_OK) {
176         return CMR_OK; /* if file not exist, return ok */
177     }
178 
179     struct stat tmp;
180     if (stat(fileName, &tmp) != 0) {
181         return CMR_ERROR_INVALID_OPERATION;
182     }
183 
184     if (S_ISDIR(tmp.st_mode)) {
185         return CMR_ERROR_INVALID_ARGUMENT;
186     }
187 
188     if ((unlink(fileName) != 0) && (errno != ENOENT)) {
189         CM_LOG_E("failed to remove file: errno = 0x%x", errno);
190         return CMR_ERROR_REMOVE_FILE_FAIL;
191     }
192 
193     return CMR_OK;
194 }
195 
CmFileRemove(const char * path,const char * fileName)196 int32_t CmFileRemove(const char *path, const char *fileName)
197 {
198     if (fileName == NULL) {
199         return CMR_ERROR_INVALID_ARGUMENT;
200     }
201 
202     char *fullFileName = NULL;
203     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
204     if (ret != CMR_OK) {
205         return ret;
206     }
207 
208     ret = FileRemove(fullFileName);
209     CM_FREE_PTR(fullFileName);
210     return ret;
211 }
212 
CmMakeDir(const char * path)213 int32_t CmMakeDir(const char *path)
214 {
215     if ((access(path, F_OK)) != -1) {
216         CM_LOG_I("path exist");
217         return CMR_OK;
218     }
219 
220     if (mkdir(path, S_IRWXU) == 0) {
221         return CMR_OK;
222     } else {
223         if (errno == EEXIST  || errno == EAGAIN) {
224             return CMR_ERROR_ALREADY_EXISTS;
225         } else {
226             return CMR_ERROR_MAKE_DIR_FAIL;
227         }
228     }
229 }
230 
CmOpenDir(const char * path)231 void *CmOpenDir(const char *path)
232 {
233     return (void *)opendir(path);
234 }
235 
CmCloseDir(void * dirp)236 int32_t CmCloseDir(void *dirp)
237 {
238     return closedir((DIR *)dirp);
239 }
240 
CmGetDirFile(void * dirp,struct CmFileDirentInfo * direntInfo)241 int32_t CmGetDirFile(void *dirp, struct CmFileDirentInfo *direntInfo)
242 {
243     DIR *dir = (DIR *)dirp;
244     struct dirent *dire = readdir(dir);
245 
246     while (dire != NULL) {
247         if (dire->d_type != DT_REG) { /* only care about files. */
248             dire = readdir(dir);
249             continue;
250         }
251 
252         uint32_t len = strlen(dire->d_name);
253         if (memcpy_s(direntInfo->fileName, sizeof(direntInfo->fileName) - 1, dire->d_name, len) != EOK) {
254             return CMR_ERROR_INVALID_OPERATION;
255         }
256         direntInfo->fileName[len] = '\0';
257         return CMR_OK;
258     }
259 
260     return CMR_ERROR_NOT_EXIST;
261 }
262 
CmFileRead(const char * path,const char * fileName,uint32_t offset,uint8_t * buf,uint32_t len)263 uint32_t CmFileRead(const char *path, const char *fileName, uint32_t offset, uint8_t *buf, uint32_t len)
264 {
265     if ((fileName == NULL) || (buf == NULL) || (len == 0)) {
266         return 0;
267     }
268 
269     char *fullFileName = NULL;
270     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
271     if (ret != CMR_OK) {
272         return 0;
273     }
274 
275     uint32_t size = FileRead(fullFileName, offset, buf, len);
276     CM_FREE_PTR(fullFileName);
277     return size;
278 }
279 
CmFileWrite(const char * path,const char * fileName,uint32_t offset,const uint8_t * buf,uint32_t len)280 int32_t CmFileWrite(const char *path, const char *fileName, uint32_t offset, const uint8_t *buf, uint32_t len)
281 {
282     if ((fileName == NULL) || (buf == NULL) || (len == 0)) {
283         return CMR_ERROR_INVALID_ARGUMENT;
284     }
285 
286     char *fullFileName = NULL;
287     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
288     if (ret != CMR_OK) {
289         return ret;
290     }
291 
292     ret = FileWrite(fullFileName, offset, buf, len);
293     CM_FREE_PTR(fullFileName);
294     return ret;
295 }
296 
CmFileSize(const char * path,const char * fileName)297 uint32_t CmFileSize(const char *path, const char *fileName)
298 {
299     if (fileName == NULL) {
300         CM_LOG_E("fileName is NULL");
301         return 0;
302     }
303 
304     char *fullFileName = NULL;
305     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
306     if (ret != CMR_OK) {
307         CM_LOG_E("GetFullFileName failed");
308         return 0;
309     }
310 
311     uint32_t size = FileSize(fullFileName);
312     CM_FREE_PTR(fullFileName);
313     return size;
314 }
315 
CmUidLayerGetFileNames(const char * filePath,struct CmBlob * fileNames,const uint32_t arraySize,uint32_t count)316 static int32_t CmUidLayerGetFileNames(const char *filePath, struct CmBlob *fileNames,
317     const uint32_t arraySize, uint32_t count)
318 {
319     if (count >= arraySize) {
320         return CMR_ERROR_BUFFER_TOO_SMALL;
321     }
322     uint32_t filePathLen = strlen(filePath);
323     if (filePathLen >= CM_MAX_FILE_NAME_LEN) {
324         CM_LOG_E("CmUidLayerGetFileNames filePathLen:%u", filePathLen);
325         return CMR_ERROR_BUFFER_TOO_SMALL;
326     }
327 
328     fileNames[count].data = (uint8_t *)CMMalloc(filePathLen + 1);
329     if (fileNames[count].data == NULL) {
330         return CMR_ERROR_MALLOC_FAIL;
331     }
332     (void)memset_s(fileNames[count].data, filePathLen + 1, 0, filePathLen + 1);
333     if (memcpy_s(fileNames[count].data, CM_MAX_FILE_NAME_LEN, filePath, filePathLen) != EOK) {
334         /* fileNames memory free in top layer function */
335         return CMR_ERROR_BUFFER_TOO_SMALL;
336     }
337     fileNames[count].size = filePathLen + 1; /* include '\0' at end */
338     return CM_SUCCESS;
339 }
340 
CmUidLayerGetFileCountAndNames(const char * path,struct CmBlob * fileNames,const uint32_t arraySize,uint32_t * fileCount)341 int32_t CmUidLayerGetFileCountAndNames(const char *path, struct CmBlob *fileNames,
342     const uint32_t arraySize, uint32_t *fileCount)
343 {
344     /* do nothing when dir is not exist */
345     if (CmIsDirExist(path) != CMR_OK) {
346         CM_LOG_I("Uid layer dir is not exist");
347         return CM_SUCCESS;
348     }
349     DIR *dir = opendir(path);
350     if (dir == NULL) {
351         CM_LOG_E("open uid layer dir failed");
352         return CMR_ERROR_OPEN_FILE_FAIL;
353     }
354 
355     int32_t ret = CM_SUCCESS;
356     uint32_t count = *fileCount;
357     struct dirent *dire = readdir(dir);
358     while (dire != NULL) {
359         char uidPath[CM_MAX_FILE_NAME_LEN] = {0};
360         if (strncpy_s(uidPath, sizeof(uidPath), path, strlen(path)) != EOK) {
361             ret = CMR_ERROR_INVALID_OPERATION;
362             break;
363         }
364 
365         if (uidPath[strlen(uidPath) - 1] != '/') {
366             if (strncat_s(uidPath, sizeof(uidPath), "/", strlen("/")) != EOK) {
367                 ret = CMR_ERROR_INVALID_OPERATION;
368                 break;
369             }
370         }
371 
372         if (strncat_s(uidPath, sizeof(uidPath), dire->d_name, strlen(dire->d_name)) != EOK) {
373             ret = CMR_ERROR_INVALID_OPERATION;
374             break;
375         }
376 
377         if ((dire->d_type == DT_REG) && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
378             ret = CmUidLayerGetFileNames(uidPath, fileNames, arraySize, count);
379             if (ret != CM_SUCCESS) {
380                 break;
381             }
382             count++;
383         }
384         dire = readdir(dir);
385     }
386     *fileCount = count;
387     closedir(dir);
388     return ret;
389 }
390 
CmUserIdLayerGetFileCountAndNames(const char * path,struct CmBlob * fileNames,const uint32_t arraySize,uint32_t * fileCount)391 int32_t CmUserIdLayerGetFileCountAndNames(const char *path, struct CmBlob *fileNames,
392     const uint32_t arraySize, uint32_t *fileCount)
393 {
394     char userIdPath[CM_MAX_FILE_NAME_LEN] = { 0 };
395     /* do nothing when dir is not exist */
396     if (CmIsDirExist(path) != CMR_OK) {
397         CM_LOG_I("UserId layer dir is not exist");
398         return CM_SUCCESS;
399     }
400     DIR *dir = opendir(path);
401     if (dir  == NULL) {
402         CM_LOG_E("open userId layer dir failed");
403         return CMR_ERROR_OPEN_FILE_FAIL;
404     }
405     struct dirent *dire = readdir(dir);
406     while (dire != NULL) {
407         (void)memset_s(userIdPath, CM_MAX_FILE_NAME_LEN, 0, CM_MAX_FILE_NAME_LEN);
408         if (strncpy_s(userIdPath, sizeof(userIdPath), path, strlen(path)) != EOK) {
409             closedir(dir);
410             return CMR_ERROR_INVALID_OPERATION;
411         }
412 
413         if (userIdPath[strlen(userIdPath) - 1] != '/') {
414             if (strncat_s(userIdPath, sizeof(userIdPath), "/", strlen("/")) != EOK) {
415                 closedir(dir);
416                 return CMR_ERROR_INVALID_OPERATION;
417             }
418         }
419 
420         if (strncat_s(userIdPath, sizeof(userIdPath), dire->d_name, strlen(dire->d_name)) != EOK) {
421             closedir(dir);
422             return CMR_ERROR_INVALID_OPERATION;
423         }
424 
425         if ((dire->d_type == DT_DIR) && (strcmp("..", dire->d_name) != 0) && (strcmp(".", dire->d_name) != 0)) {
426             if (CmUidLayerGetFileCountAndNames(userIdPath, fileNames, arraySize, fileCount) != CM_SUCCESS) {
427                 CM_LOG_E("CmUidLayerGetFileCountAndNames faild");
428                 closedir(dir);
429                 return CM_FAILURE;
430             }
431         } else if (dire->d_type != DT_DIR) {
432             (void)remove(userIdPath);
433         }
434         dire = readdir(dir);
435     }
436     closedir(dir);
437     return CM_SUCCESS;
438 }
439 
CmIsFileExist(const char * path,const char * fileName)440 int32_t CmIsFileExist(const char *path, const char *fileName)
441 {
442     if (fileName == NULL) {
443         CM_LOG_E("fileName is NULL");
444         return CMR_ERROR_INVALID_ARGUMENT;
445     }
446 
447     char *fullFileName = NULL;
448     int32_t ret = GetFullFileName(path, fileName, &fullFileName);
449     if (ret != CM_SUCCESS) {
450         CM_LOG_E("GetFullFileName failed");
451         return ret;
452     }
453 
454     ret = IsFileExist(fullFileName);
455     CM_FREE_PTR(fullFileName);
456     return ret;
457 }
458 
CmGetSubDir(void * dirp,struct CmFileDirentInfo * direntInfo)459 int32_t CmGetSubDir(void *dirp, struct CmFileDirentInfo *direntInfo)
460 {
461     DIR *dir = (DIR *)dirp;
462     struct dirent *dire = readdir(dir);
463 
464     while (dire != NULL) {
465         if ((dire->d_type != DT_DIR) || (strcmp(dire->d_name, ".") == 0) ||
466             (strcmp(dire->d_name, "..") == 0)) {
467             dire = readdir(dir);
468             continue;
469         }
470 
471         uint32_t dirLen = strlen(dire->d_name);
472         if (memcpy_s(direntInfo->fileName, sizeof(direntInfo->fileName) - 1, dire->d_name, dirLen) != EOK) {
473             return CMR_ERROR_INVALID_OPERATION;
474         }
475         direntInfo->fileName[dirLen] = '\0';
476         return CMR_OK;
477     }
478 
479     return CMR_ERROR_NOT_EXIST;
480 }
481 
DirRemove(const char * path)482 static int32_t DirRemove(const char *path)
483 {
484     if (access(path, F_OK) != 0) {
485         return CMR_ERROR_NOT_EXIST;
486     }
487 
488     struct stat tmp;
489     if (stat(path, &tmp) != 0) {
490         return CMR_ERROR_INVALID_OPERATION;
491     }
492 
493     if (S_ISDIR(tmp.st_mode)) {
494         uint32_t i = 0;
495         struct dirent *dire = NULL;
496         DIR *dirp = opendir(path);
497         if (dirp == NULL) {
498             CM_LOG_E("open dir failed");
499             return CMR_ERROR_OPEN_FILE_FAIL;
500         }
501         while ((dire = readdir(dirp)) != NULL) {
502             if ((strcmp(dire->d_name, ".") == 0) || (strcmp(dire->d_name, "..") == 0)) {
503                 continue;
504             }
505             i++;
506         }
507         closedir(dirp);
508 
509         if (i != 0) {
510             CM_LOG_E("Dir is not empty");
511             return CMR_ERROR_INVALID_ARGUMENT;
512         }
513         rmdir(path);
514         return CMR_OK;
515     }
516     return CMR_ERROR_INVALID_ARGUMENT;
517 }
518 
CmDirRemove(const char * path)519 int32_t CmDirRemove(const char *path)
520 {
521     if (path == NULL) {
522         return CMR_ERROR_INVALID_ARGUMENT;
523     }
524 
525     return DirRemove(path);
526 }
527