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 }