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 failed");
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), "HksGetOldStoreFileInfo failed")
158 } else {
159 AppendFilePath(path, ptr->d_name, infos);
160 }
161 }
162 closedir(dir);
163 return HKS_SUCCESS;
164 }
165
HksInitFileIterativeReader(struct HksIterativeReader *reader, char *path)166 int32_t HksInitFileIterativeReader(struct HksIterativeReader *reader, char *path)
167 {
168 reader->fileLists = HksInitFileInfoList();
169 if (reader->fileLists == NULL) {
170 return HKS_ERROR_MALLOC_FAIL;
171 }
172 reader->curIndex = 0;
173 int32_t ret = HksGetOldStoreFileInfo(path, reader->fileLists);
174 if (ret != HKS_SUCCESS) {
175 HksFreeFileInfoList(&reader->fileLists);
176 }
177 return ret;
178 }
179
HksDestroyFileIterativeReader(struct HksIterativeReader *reader)180 void HksDestroyFileIterativeReader(struct HksIterativeReader *reader)
181 {
182 HksFreeFileInfoList(&reader->fileLists);
183 }
184
HksReadFileWithIterativeReader(struct HksIterativeReader *reader, struct HksBlob *fileContent, struct HksBlob *alias, struct HksBlob *path)185 int32_t HksReadFileWithIterativeReader(struct HksIterativeReader *reader, struct HksBlob *fileContent,
186 struct HksBlob *alias, struct HksBlob *path)
187 {
188 if (reader->curIndex == reader->fileLists->occu) {
189 return HKS_ERROR_BUFFER_TOO_SMALL;
190 }
191
192 int32_t ret = HKS_SUCCESS;
193 do {
194 uint32_t size = HksFileSize(reader->fileLists->infos[reader->curIndex].path,
195 reader->fileLists->infos[reader->curIndex].fileName);
196 if (size == 0) {
197 ret = HKS_ERROR_FILE_SIZE_FAIL;
198 break;
199 }
200 fileContent->data = (uint8_t *)HksMalloc(size);
201 if (fileContent->data == NULL) {
202 HKS_LOG_E("malloc fileContent->data failed.");
203 ret = HKS_ERROR_MALLOC_FAIL;
204 break;
205 }
206 fileContent->size = size;
207 alias->data = (uint8_t *)HksMalloc(strlen(reader->fileLists->infos[reader->curIndex].fileName) + 1);
208 if (alias->data == NULL) {
209 HKS_LOG_E("malloc alias->data failed.");
210 ret = HKS_ERROR_MALLOC_FAIL;
211 break;
212 }
213 alias->size = strlen(reader->fileLists->infos[reader->curIndex].fileName) + 1;
214 (void)memcpy_s(alias->data, strlen(reader->fileLists->infos[reader->curIndex].fileName),
215 reader->fileLists->infos[reader->curIndex].fileName,
216 strlen(reader->fileLists->infos[reader->curIndex].fileName));
217 path->data = (uint8_t *)HksMalloc(strlen(reader->fileLists->infos[reader->curIndex].path) + 1);
218 if (path->data == NULL) {
219 HKS_LOG_E("malloc path->data failed.");
220 ret = HKS_ERROR_MALLOC_FAIL;
221 break;
222 }
223 path->size = strlen(reader->fileLists->infos[reader->curIndex].path) + 1;
224 (void)memcpy_s(path->data, strlen(reader->fileLists->infos[reader->curIndex].path),
225 reader->fileLists->infos[reader->curIndex].path, strlen(reader->fileLists->infos[reader->curIndex].path));
226 ret = HksFileRead(reader->fileLists->infos[reader->curIndex].path,
227 reader->fileLists->infos[reader->curIndex].fileName, 0, fileContent, &fileContent->size);
228 reader->curIndex++;
229 return ret;
230 } while (false);
231 HKS_FREE_BLOB(*fileContent);
232 HKS_FREE_BLOB(*alias);
233 HKS_FREE_BLOB(*path);
234 return ret;
235 }