1 /*
2  * Copyright (c) 2024-2024 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 "hks_iterative_reader.h"
17 
18 #include <dirent.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <stdio.h>
23 #include <sys/stat.h>
24 
25 #include "hks_file_operator.h"
26 #include "hks_log.h"
27 #include "hks_mem.h"
28 #include "hks_template.h"
29 #include "hks_type_inner.h"
30 
31 #define DEFAULT_PATH_LEN 256
32 
33 #define DEFAULT_FILE_INFO_NUM 64
34 
35 #define DIR_TYPE 4
36 
HksFreeFileInfo(struct HksReadFileInfo * info)37 static void HksFreeFileInfo(struct HksReadFileInfo *info)
38 {
39     HKS_FREE(info->path);
40     HKS_FREE(info->fileName);
41 }
42 
HksFreeFileInfoList(struct HksReadFileInfoList ** infos)43 static void HksFreeFileInfoList(struct HksReadFileInfoList **infos)
44 {
45     if (*infos == NULL) {
46         return;
47     }
48     if ((*infos)->infos != NULL && (*infos)->occu > 0) {
49         for (uint32_t i = 0; i < (*infos)->occu; ++i) {
50             HksFreeFileInfo(&(*infos)->infos[i]);
51         }
52     }
53     HKS_FREE((*infos)->infos);
54     HKS_FREE(*infos);
55 }
56 
HksInitFileInfoList(void)57 static struct HksReadFileInfoList *HksInitFileInfoList(void)
58 {
59     struct HksReadFileInfoList *infos;
60     do {
61         infos = (struct HksReadFileInfoList *)HksMalloc(sizeof(struct HksReadFileInfoList));
62         if (infos == NULL) {
63             HKS_LOG_E("malloc HksReadFileInfoList failed.");
64             break;
65         }
66         infos->infos = (struct HksReadFileInfo *)HksMalloc(sizeof(struct HksReadFileInfo) * DEFAULT_FILE_INFO_NUM);
67         if (infos->infos == NULL) {
68             break;
69         }
70         infos->occu = 0;
71         infos->cap = DEFAULT_FILE_INFO_NUM;
72         return infos;
73     } while (false);
74     HksFreeFileInfoList(&infos);
75     return NULL;
76 }
77 
78 // each time for re-alloc, the capacity of OldFileInfoList will be added with DEFAULT_FILE_INFO_NUM.
HksReAllocFileInfoList(struct HksReadFileInfoList * infos)79 static int32_t HksReAllocFileInfoList(struct HksReadFileInfoList *infos)
80 {
81     struct HksReadFileInfo *newInfo =
82         (struct HksReadFileInfo *)HksMalloc(sizeof(struct HksReadFileInfo) * (infos->cap + DEFAULT_FILE_INFO_NUM));
83     if (newInfo == NULL) {
84         return HKS_ERROR_MALLOC_FAIL;
85     }
86     (void)memcpy_s(newInfo, (infos->cap + DEFAULT_FILE_INFO_NUM) * sizeof(struct HksReadFileInfo),
87         infos->infos, infos->occu * sizeof(struct HksReadFileInfo));
88     HKS_FREE(infos->infos);
89     infos->infos = newInfo;
90     infos->cap += DEFAULT_FILE_INFO_NUM;
91     return HKS_SUCCESS;
92 }
93 
AppendFilePath(const char * path,const char * fileName,struct HksReadFileInfoList * infos)94 static int32_t AppendFilePath(const char *path, const char *fileName, struct HksReadFileInfoList *infos)
95 {
96     int32_t ret;
97     if (infos->occu == infos->cap) {
98         ret = HksReAllocFileInfoList(infos);
99         HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "re-alloc old file info list failed.")
100     }
101     struct HksReadFileInfo *info = &infos->infos[infos->occu]; // the (infos->occu + 1)th info
102     do {
103         info->path = (char *)HksMalloc(strlen(path) + 1);
104         HKS_IF_NULL_BREAK(info->path)
105         info->fileName = (char *)HksMalloc(strlen(fileName) + 1);
106         HKS_IF_NULL_BREAK(info->fileName)
107         (void)memcpy_s(info->path, strlen(path), path, strlen(path));
108         (void)memcpy_s(info->fileName, strlen(fileName), fileName, strlen(fileName));
109         infos->occu += 1;
110 
111         return HKS_SUCCESS;
112     } while (false);
113     HksFreeFileInfo(info);
114     return ret;
115 }
116 
ConstructSubPath(const struct dirent * ptr,const char * curPath,char * subPath)117 static int ConstructSubPath(const struct dirent *ptr, const char *curPath, char *subPath)
118 {
119     int ret = strcpy_s(subPath, DEFAULT_PATH_LEN, curPath);
120     if (ret != EOK) {
121         return ret;
122     }
123     ret = strcat_s(subPath, DEFAULT_PATH_LEN, "/");
124     if (ret != EOK) {
125         return ret;
126     }
127 
128     ret = strcat_s(subPath, DEFAULT_PATH_LEN, ptr->d_name);
129     if (ret != EOK) {
130         return ret;
131     }
132 
133     return EOK;
134 }
135 
HksGetOldStoreFileInfo(const char * path,struct HksReadFileInfoList * infos)136 static int32_t HksGetOldStoreFileInfo(const char *path, struct HksReadFileInfoList *infos)
137 {
138     DIR *dir = opendir(path);
139     if (dir == NULL) {
140         HKS_LOG_E("open dir %" LOG_PUBLIC "s failed.", path);
141         return HKS_ERROR_MAKE_DIR_FAIL;
142     }
143     struct dirent *ptr;
144     int ret = EOK;
145     while ((ptr = readdir(dir)) != NULL) {
146         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
147             continue;
148         }
149         if (ptr->d_type == DIR_TYPE) {
150             char subPath[DEFAULT_PATH_LEN] = { 0 };
151 
152             ret = ConstructSubPath(ptr, path, subPath);
153             if (ret != EOK) {
154                 HKS_LOG_E("construct src and target path failed!");
155                 break;
156             }
157             HKS_IF_NOT_SUCC_LOGE_BREAK(HksGetOldStoreFileInfo(subPath, infos),
158                 "HksGetOldStoreFileInfo failed, path is %" LOG_PUBLIC "s", subPath)
159         } else {
160             AppendFilePath(path, ptr->d_name, infos);
161         }
162     }
163     closedir(dir);
164     return HKS_SUCCESS;
165 }
166 
HksInitFileIterativeReader(struct HksIterativeReader * reader,char * path)167 int32_t HksInitFileIterativeReader(struct HksIterativeReader *reader, char *path)
168 {
169     reader->fileLists = HksInitFileInfoList();
170     if (reader->fileLists == NULL) {
171         return HKS_ERROR_MALLOC_FAIL;
172     }
173     reader->curIndex = 0;
174     int32_t ret = HksGetOldStoreFileInfo(path, reader->fileLists);
175     if (ret != HKS_SUCCESS) {
176         HksFreeFileInfoList(&reader->fileLists);
177     }
178     return ret;
179 }
180 
HksDestroyFileIterativeReader(struct HksIterativeReader * reader)181 void HksDestroyFileIterativeReader(struct HksIterativeReader *reader)
182 {
183     HksFreeFileInfoList(&reader->fileLists);
184 }
185 
HksReadFileWithIterativeReader(struct HksIterativeReader * reader,struct HksBlob * fileContent,struct HksBlob * alias,struct HksBlob * path)186 int32_t HksReadFileWithIterativeReader(struct HksIterativeReader *reader, struct HksBlob *fileContent,
187     struct HksBlob *alias, struct HksBlob *path)
188 {
189     if (reader->curIndex == reader->fileLists->occu) {
190         return HKS_ERROR_BUFFER_TOO_SMALL;
191     }
192 
193     int32_t ret = HKS_SUCCESS;
194     do {
195         uint32_t size = HksFileSize(reader->fileLists->infos[reader->curIndex].path,
196             reader->fileLists->infos[reader->curIndex].fileName);
197         if (size == 0) {
198             ret = HKS_ERROR_FILE_SIZE_FAIL;
199             break;
200         }
201         fileContent->data = (uint8_t *)HksMalloc(size);
202         if (fileContent->data == NULL) {
203             HKS_LOG_E("malloc fileContent->data failed.");
204             ret = HKS_ERROR_MALLOC_FAIL;
205             break;
206         }
207         fileContent->size = size;
208         alias->data = (uint8_t *)HksMalloc(strlen(reader->fileLists->infos[reader->curIndex].fileName) + 1);
209         if (alias->data == NULL) {
210             HKS_LOG_E("malloc alias->data failed.");
211             ret = HKS_ERROR_MALLOC_FAIL;
212             break;
213         }
214         alias->size = strlen(reader->fileLists->infos[reader->curIndex].fileName) + 1;
215         (void)memcpy_s(alias->data, strlen(reader->fileLists->infos[reader->curIndex].fileName),
216             reader->fileLists->infos[reader->curIndex].fileName,
217             strlen(reader->fileLists->infos[reader->curIndex].fileName));
218         path->data = (uint8_t *)HksMalloc(strlen(reader->fileLists->infos[reader->curIndex].path) + 1);
219         if (path->data == NULL) {
220             HKS_LOG_E("malloc path->data failed.");
221             ret = HKS_ERROR_MALLOC_FAIL;
222             break;
223         }
224         path->size = strlen(reader->fileLists->infos[reader->curIndex].path) + 1;
225         (void)memcpy_s(path->data, strlen(reader->fileLists->infos[reader->curIndex].path),
226             reader->fileLists->infos[reader->curIndex].path, strlen(reader->fileLists->infos[reader->curIndex].path));
227         ret = HksFileRead(reader->fileLists->infos[reader->curIndex].path,
228             reader->fileLists->infos[reader->curIndex].fileName, 0, fileContent, &fileContent->size);
229         reader->curIndex++;
230         return ret;
231     } while (false);
232     HKS_FREE_BLOB(*fileContent);
233     HKS_FREE_BLOB(*alias);
234     HKS_FREE_BLOB(*path);
235     return ret;
236 }