1 /*
2  * Copyright (C) 2021 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 "nstackx_file_list.h"
17 #include "nstackx_error.h"
18 #include "nstackx_util.h"
19 #include "nstackx_dfile_log.h"
20 #include "nstackx_dfile_frame.h"
21 #include "securec.h"
22 
23 #define TAG "nStackXDFile"
24 
FileListAllFileNameAcked(const FileList * fileList)25 uint8_t FileListAllFileNameAcked(const FileList *fileList)
26 {
27     uint32_t i;
28     if ((fileList->userDataFlag & NSTACKX_DFILE_HEADER_FRAME_USER_DATA_FLAG) &&
29         !(fileList->userDataFlag & NSTACKX_FLAGS_USER_DATA_ACK)) {
30         DFILE_LOGI(TAG, "user data not acked");
31         return NSTACKX_FALSE;
32     }
33 
34     if (fileList->tarFlag == NSTACKX_TRUE) {
35         if (!(fileList->list[0].flags & NSTACKX_FLAGS_FILE_NAME_ACK)) {
36             DFILE_LOGI(TAG, "file name 1 is not ACKED yet");
37             return NSTACKX_FALSE;
38         } else {
39             return NSTACKX_TRUE;
40         }
41     }
42 
43     for (i = 0; i < fileList->num; i++) {
44         if (!(fileList->list[i].flags & NSTACKX_FLAGS_FILE_NAME_ACK)) {
45             DFILE_LOGI(TAG, "file name id %u is not ACKED yet", i + 1);
46             return NSTACKX_FALSE;
47         }
48     }
49 
50     return NSTACKX_TRUE;
51 }
52 
FileListAllFileNameReceived(const FileList * fileList)53 uint8_t FileListAllFileNameReceived(const FileList *fileList)
54 {
55     uint32_t i;
56 
57     if (!fileList->num) {
58         return NSTACKX_FALSE;
59     }
60 
61     if ((fileList->userDataFlag & NSTACKX_DFILE_HEADER_FRAME_USER_DATA_FLAG) &&
62         !(fileList->userDataFlag & NSTACKX_FLAGS_FILE_NAME_RECEIVED)) {
63         return NSTACKX_FALSE;
64     }
65 
66     if (fileList->tarFlag == NSTACKX_TRUE) {
67         if (!(fileList->list[0].flags & NSTACKX_FLAGS_FILE_NAME_RECEIVED)) {
68             DFILE_LOGI(TAG, "file name id 1 is not RECEIVED yet");
69             return NSTACKX_FALSE;
70         } else {
71             return NSTACKX_TRUE;
72         }
73     }
74 
75     for (i = 0; i < fileList->num; i++) {
76         if (!(fileList->list[i].flags & NSTACKX_FLAGS_FILE_NAME_RECEIVED)) {
77             DFILE_LOGI(TAG, "file name id %u is not RECEIVED yet", i + 1);
78             return NSTACKX_FALSE;
79         }
80     }
81 
82     return NSTACKX_TRUE;
83 }
84 
FileListAllFileReceived(const FileList * fileList)85 uint8_t FileListAllFileReceived(const FileList *fileList)
86 {
87     uint32_t i;
88 
89     if (fileList->tarFlag == NSTACKX_TRUE) {
90         if (!(fileList->list[0].flags & NSTACKX_FLAGS_FILE_RECEIVE_SUCCESS)) {
91             return NSTACKX_FALSE;
92         } else {
93             return NSTACKX_TRUE;
94         }
95     }
96 
97     for (i = 0; i < fileList->num; i++) {
98         if (!(fileList->list[i].flags & NSTACKX_FLAGS_FILE_RECEIVE_SUCCESS)) {
99             return NSTACKX_FALSE;
100         }
101     }
102 
103     return NSTACKX_TRUE;
104 }
105 
FileListSetSendFileList(FileList * fileList,FileListInfo * fileListInfo)106 int32_t FileListSetSendFileList(FileList *fileList, FileListInfo *fileListInfo)
107 {
108     uint16_t i;
109     FileListEntry *fileListEntry = NULL;
110     FileListEntry *entryList = NULL;
111     int32_t ret;
112 
113     if (fileListInfo->files == NULL || fileListInfo->fileNum == 0 ||
114         fileListInfo->fileNum > NSTACKX_DFILE_MAX_FILE_NUM) {
115         DFILE_LOGE(TAG, "invalid input");
116         return NSTACKX_EINVAL;
117     }
118 
119     if (fileList->list != NULL) {
120         DFILE_LOGE(TAG, "invalid fileList->list");
121         return NSTACKX_EFAILED;
122     }
123 
124     entryList = calloc(fileListInfo->fileNum, sizeof(FileListEntry));
125     if (entryList == NULL) {
126         DFILE_LOGE(TAG, "entryList calloc NULL");
127         return NSTACKX_ENOMEM;
128     }
129 
130     for (i = 0; i < fileListInfo->fileNum; i++) {
131         fileListEntry = &entryList[i];
132         /* Reuse the input memory. */
133         fileListEntry->fullFileName = fileListInfo->files[i];
134         if (fileListInfo->remotePath != NULL) {
135             fileListEntry->remotePath = fileListInfo->remotePath[i];
136         }
137         ret = GetFileName(fileListEntry->fullFileName, fileListEntry->fileName, sizeof(fileListEntry->fileName));
138         if (ret != NSTACKX_EOK) {
139             DFILE_LOGE(TAG, "GetFileName error: %d", ret);
140             goto L_FIN;
141         }
142         ret = GetTargetFileSize(fileListEntry->fullFileName, &fileListEntry->fileSize);
143         if ((ret != NSTACKX_EOK) || (fileListEntry->fileSize > NSTACKX_MAX_FILE_SIZE)) {
144             DFILE_LOGE(TAG, "GetTargetFileSize error: %d", ret);
145             goto L_FIN;
146         }
147         if (fileListInfo->vtransFlag) {
148             fileListEntry->startOffset = fileListInfo->startOffset[i];
149             fileListEntry->fileSize = fileListInfo->fileSize[i];
150         }
151         fileListEntry->fileId = i + 1;
152     }
153 
154     fileList->list = entryList;
155     fileList->num = fileListInfo->fileNum;
156     return NSTACKX_EOK;
157 
158 L_FIN:
159     /* Something wrong, clear file list */
160     free(entryList);
161     entryList = NULL;
162     return ret;
163 }
164 
FileListSetNum(FileList * fileList,uint32_t fileNum)165 int32_t FileListSetNum(FileList *fileList, uint32_t fileNum)
166 {
167     if (fileNum == 0 || fileNum > NSTACKX_DFILE_MAX_FILE_NUM) {
168         return NSTACKX_EINVAL;
169     }
170 
171     if (fileList->list != NULL) {
172         return NSTACKX_EOK;
173     }
174 
175     fileList->list = calloc(fileNum, sizeof(FileListEntry));
176     if (fileList->list == NULL) {
177         return NSTACKX_ENOMEM;
178     }
179     fileList->num = fileNum;
180     return NSTACKX_EOK;
181 }
182 
FileListAddFile(FileList * fileList,uint16_t fileId,const uint8_t * fileName,size_t fileNameLength,uint64_t fileSize)183 int32_t FileListAddFile(FileList *fileList, uint16_t fileId, const uint8_t *fileName, size_t fileNameLength,
184                         uint64_t fileSize)
185 {
186     FileListEntry *fileListEntry = NULL;
187 
188     if (fileList->list == NULL || fileList->num == 0) {
189         return NSTACKX_EINVAL;
190     }
191 
192     if (fileId == 0 || fileId > fileList->num) {
193         return NSTACKX_EINVAL;
194     }
195 
196     if (fileNameLength + 1 > NSTACKX_MAX_REMOTE_PATH_LEN) {
197         return NSTACKX_EINVAL;
198     }
199 
200     if (fileSize > NSTACKX_MAX_FILE_SIZE) {
201         return NSTACKX_EINVAL;
202     }
203 
204     fileListEntry = &fileList->list[fileId - 1];
205 
206     if (fileListEntry->flags & NSTACKX_FLAGS_FILE_NAME_RECEIVED) {
207         /* duplicate frame */
208         return NSTACKX_EOK;
209     }
210 
211     if (memcpy_s(fileListEntry->fileName, sizeof(fileListEntry->fileName) - 1, fileName, fileNameLength) != EOK) {
212         return NSTACKX_EFAILED;
213     }
214     fileListEntry->fileId = fileId;
215     fileListEntry->fileSize = fileSize;
216     fileListEntry->flags |= NSTACKX_FLAGS_FILE_NAME_RECEIVED;
217     if (fileSize == 0) {
218         fileListEntry->flags |= NSTACKX_FLAGS_LAST_BLOCK_RECEIVED;
219     }
220 
221     return NSTACKX_EOK;
222 }
223 
ParsePackedDFileUserData(const uint8_t * buf,size_t userDataLength,uint16_t * pathType,char ** userData,uint8_t flag)224 static int32_t ParsePackedDFileUserData(const uint8_t *buf, size_t userDataLength, uint16_t *pathType, char **userData,
225                                         uint8_t flag)
226 {
227     char *validUserData = NULL;
228     uint16_t userDataStrLen;
229     const UserDataUnit *userDataUnit = NULL;
230     if (userDataLength < sizeof(UserDataUnit)) {
231         DFILE_LOGE(TAG, "userDataLength is too small");
232         return NSTACKX_EFAILED;
233     }
234     userDataUnit = (UserDataUnit *)buf;
235     *pathType = userDataUnit->pathType;
236     if (*pathType == 0) {
237         DFILE_LOGE(TAG, "path type is 0");
238         return NSTACKX_EFAILED;
239     }
240     if (!(flag & NSTACKX_DFILE_HEADER_FRAME_USER_DATA_FLAG)) {
241         return NSTACKX_EOK;
242     }
243     userDataStrLen = (uint16_t)(userDataLength - sizeof(UserDataUnit));
244     validUserData = (char *)calloc(userDataStrLen + 1, 1);
245     if (validUserData == NULL) {
246         return NSTACKX_EFAILED;
247     }
248     if (userDataStrLen > 0 &&
249         memcpy_s(validUserData, userDataStrLen + 1, userDataUnit->userData, userDataStrLen) != EOK) {
250         free(validUserData);
251         return NSTACKX_EFAILED;
252     }
253     *userData = validUserData;
254     return NSTACKX_EOK;
255 }
256 
FileListAddUserData(FileList * fileList,const uint8_t * userData,size_t userDataLength,uint8_t flag)257 int32_t FileListAddUserData(FileList *fileList, const uint8_t *userData, size_t userDataLength, uint8_t flag)
258 {
259     if (fileList->userDataFlag & NSTACKX_FLAGS_FILE_NAME_RECEIVED) {
260         /* duplicate frame */
261         return NSTACKX_EOK;
262     }
263     if (flag & NSTACKX_DFILE_HEADER_FRAME_PATH_TYPE_FLAG) {
264         if (ParsePackedDFileUserData(userData, userDataLength, &fileList->pathType, &fileList->userData, flag) !=
265             NSTACKX_EOK) {
266             DFILE_LOGE(TAG, "ParsePackedDFileUserData failed");
267         }
268     } else if (flag & NSTACKX_DFILE_HEADER_FRAME_USER_DATA_FLAG) {
269         fileList->userData = calloc(1, userDataLength + 1);
270         if (fileList->userData == NULL) {
271             return NSTACKX_ENOMEM;
272         }
273         if (userDataLength) {
274             if (memcpy_s(fileList->userData, userDataLength + 1, userData, userDataLength) != EOK) {
275                 free(fileList->userData);
276                 fileList->userData = NULL;
277                 return NSTACKX_EFAILED;
278             }
279         }
280     } else {
281         DFILE_LOGE(TAG, "invalid flag %2X", flag);
282         return NSTACKX_EFAILED;
283     }
284     fileList->userDataFlag |= NSTACKX_FLAGS_FILE_NAME_RECEIVED;
285     return NSTACKX_EOK;
286 }
287 
FileListGetNames(FileList * fileList,char * files[],uint32_t * fileNum,uint8_t fileNameType)288 void FileListGetNames(FileList *fileList, char *files[], uint32_t *fileNum, uint8_t fileNameType)
289 {
290     uint32_t i;
291 
292     for (i = 0; i < fileList->num && i < *fileNum; i++) {
293         /* Soft copy */
294         if (fileList->tarFlag == NSTACKX_TRUE) {
295             files[i] = fileList->tarFile;
296             *fileNum = 1;
297             return;
298         }
299         if (fileNameType == NOTICE_FULL_FILE_NAME_TYPE) {
300             files[i] = fileList->list[i].fullFileName;
301         } else if (fileNameType == NOTICE_FILE_NAME_TYPE) {
302             files[i] = fileList->list[i].fileName;
303         } else {
304             DFILE_LOGE(TAG, "invalid fileName type %u", fileNameType);
305             break;
306         }
307     }
308     *fileNum = i;
309 }
310 
FileListGetReceivedFileIdList(FileList * fileList,uint16_t fileIdList[],uint32_t * fileNum)311 void FileListGetReceivedFileIdList(FileList *fileList, uint16_t fileIdList[], uint32_t *fileNum)
312 {
313     uint32_t i;
314     uint32_t count = 0;
315 
316     for (i = 0; i < fileList->num && i < *fileNum; i++) {
317         if (fileList->list[i].flags & NSTACKX_FLAGS_FILE_RECEIVE_SUCCESS) {
318             fileIdList[count] = fileList->list[i].fileId;
319             count++;
320         }
321     }
322     *fileNum = count;
323 }
324 
FileListGetFilesByFlag(FileList * fileList,uint8_t flags,char * files[],uint32_t * fileNum,uint8_t fileNameType)325 static void FileListGetFilesByFlag(FileList *fileList, uint8_t flags, char *files[], uint32_t *fileNum,
326                                    uint8_t fileNameType)
327 {
328     uint32_t i;
329     uint32_t count = 0;
330 
331     for (i = 0; i < fileList->num && i < *fileNum; i++) {
332         if (fileList->list[i].flags & flags) {
333             if (fileList->tarFlag == NSTACKX_TRUE) {
334                 files[count] = fileList->tarFile;
335                 count++;
336                 break;
337             }
338             if (fileNameType == NOTICE_FULL_FILE_NAME_TYPE) {
339                 files[count] = fileList->list[i].fullFileName;
340                 count++;
341             } else if (fileNameType == NOTICE_FILE_NAME_TYPE) {
342                 files[count] = fileList->list[i].fileName;
343                 count++;
344             } else {
345                 DFILE_LOGE(TAG, "invalid fileName type %u", fileNameType);
346                 break;
347             }
348         } else {
349             DFILE_LOGE(TAG, "the %uth file is not with target flag %2X", i, flags);
350         }
351     }
352     *fileNum = count;
353 }
354 
FileListGetReceivedFiles(FileList * fileList,char * files[],uint32_t * fileNum)355 void FileListGetReceivedFiles(FileList *fileList, char *files[], uint32_t *fileNum)
356 {
357     FileListGetFilesByFlag(fileList, NSTACKX_FLAGS_FILE_RECEIVE_SUCCESS, files, fileNum, NOTICE_FILE_NAME_TYPE);
358 }
359 
FileListGetSentFiles(FileList * fileList,char * files[],uint32_t * fileNum)360 void FileListGetSentFiles(FileList *fileList, char *files[], uint32_t *fileNum)
361 {
362     FileListGetFilesByFlag(fileList, NSTACKX_FLAGS_FILE_SEND_SUCCESS, files, fileNum, fileList->noticeFileNameType);
363 }
364 
FileListSetFileNameAcked(FileList * fileList,uint16_t fileId)365 void FileListSetFileNameAcked(FileList *fileList, uint16_t fileId)
366 {
367     if (fileId == 1 || fileId == fileList->num) {
368         DFILE_LOGI(TAG, "set file id: %u acked", fileId);
369     }
370     if (fileId == 0) {
371         fileList->userDataFlag |= NSTACKX_FLAGS_USER_DATA_ACK;
372     } else {
373         (fileList)->list[(fileId) - 1].flags |= NSTACKX_FLAGS_FILE_NAME_ACK;
374     }
375 }
376 
FileListGetFileNameAcked(FileList * fileList,uint16_t fileId)377 uint8_t FileListGetFileNameAcked(FileList *fileList, uint16_t fileId)
378 {
379     if (fileId == 0) {
380         return (fileList->userDataFlag & NSTACKX_FLAGS_USER_DATA_ACK);
381     } else {
382         return ((fileList)->list[(fileId) - 1].flags & NSTACKX_FLAGS_FILE_NAME_ACK);
383     }
384 }
385 
FileListCreate(void)386 FileList *FileListCreate(void)
387 {
388     FileList *fileList = NULL;
389 
390     fileList = malloc(sizeof(FileList));
391     if (fileList == NULL) {
392         return NULL;
393     }
394     (void)memset_s(fileList, sizeof(FileList), 0, sizeof(FileList));
395 
396     return fileList;
397 }
398 
FileListDestroy(FileList * fileList)399 void FileListDestroy(FileList *fileList)
400 {
401     uint32_t i;
402     FileListEntry *fileListEntry = NULL;
403     if (fileList->userData != NULL) {
404         free(fileList->userData);
405         fileList->userData = NULL;
406     }
407 
408     if (fileList->packedUserData != NULL) {
409         free(fileList->packedUserData);
410         fileList->packedUserData = NULL;
411     }
412 
413     if (fileList->tarFile != NULL) {
414         free(fileList->tarFile);
415         fileList->tarFile = NULL;
416     }
417 
418     for (i = 0; i < fileList->num; i++) {
419         fileListEntry = &fileList->list[i];
420         free(fileListEntry->fullFileName);
421         fileListEntry->fullFileName = NULL;
422         if (fileListEntry->remotePath != NULL) {
423             free(fileListEntry->remotePath);
424             fileListEntry->remotePath = NULL;
425         }
426     }
427     free(fileList->list);
428     free(fileList);
429     fileList = NULL;
430 }
431 
GetFilesTotalBytes(FileList * fileList)432 uint64_t GetFilesTotalBytes(FileList *fileList)
433 {
434     uint64_t ret = 0;
435     uint32_t i;
436     if (fileList == NULL) {
437         return ret;
438     }
439     for (i = 0; i < fileList->num; i++) {
440         ret += fileList->list[i].fileSize;
441     }
442     return ret;
443 }
444 
PreparePackedDFileUserData(uint16_t pathType,const char * userData,uint16_t * packedLen)445 static uint8_t *PreparePackedDFileUserData(uint16_t pathType, const char *userData, uint16_t *packedLen)
446 {
447     UserDataUnit *userDataUnit = NULL;
448     uint32_t userDataLen = 0;
449     uint16_t packeUserDataLen;
450 
451     if (userData != NULL) {
452         userDataLen = (uint32_t)strlen(userData);
453     }
454 
455     packeUserDataLen = (uint16_t)(sizeof(pathType) + userDataLen);
456 
457     userDataUnit = (UserDataUnit *)calloc(packeUserDataLen, 1);
458     if (userDataUnit == NULL) {
459         DFILE_LOGE(TAG, "userDataUnit calloc error");
460         return NULL;
461     }
462     userDataUnit->pathType = pathType;
463     if (userDataLen > 0 && memcpy_s(userDataUnit->userData, userDataLen, userData, userDataLen) != EOK) {
464         DFILE_LOGE(TAG, "userData memcpy error");
465         free(userDataUnit);
466         return NULL;
467     }
468     *packedLen = packeUserDataLen;
469     return (uint8_t *)userDataUnit;
470 }
471 
FileListAddExtraInfo(FileList * fileList,uint16_t pathType,uint8_t noticeFileNameType,char * userData)472 int32_t FileListAddExtraInfo(FileList *fileList, uint16_t pathType, uint8_t noticeFileNameType, char *userData)
473 {
474     if (noticeFileNameType != NOTICE_FILE_NAME_TYPE && noticeFileNameType != NOTICE_FULL_FILE_NAME_TYPE) {
475         DFILE_LOGE(TAG, "invalid noticeFileNameType");
476         return NSTACKX_EFAILED;
477     }
478     fileList->noticeFileNameType = noticeFileNameType;
479 
480     if (pathType == 0 && userData == NULL) {
481         return NSTACKX_EOK;
482     }
483     /*
484      * the first bit of userDataFlag means whether fileId 0 is vailid, and both pathType and userdata are
485      * transferred as part of the fileName of fileId 0.
486      */
487     fileList->userDataFlag = NSTACKX_DFILE_HEADER_FRAME_USER_DATA_FLAG;
488 
489     fileList->userData = userData;
490     fileList->pathType = pathType;
491 
492     if (pathType > 0) {
493         fileList->packedUserData = PreparePackedDFileUserData(pathType, userData, &fileList->packedUserDataLen);
494         if (fileList->packedUserData == NULL) {
495             DFILE_LOGE(TAG, "PreparePackedDFileUserData fail");
496             return NSTACKX_EFAILED;
497         }
498     }
499     return NSTACKX_EOK;
500 }
501 
FileListRenameFile(FileList * fileList,uint16_t fileId,const char * newFileName)502 int32_t FileListRenameFile(FileList *fileList, uint16_t fileId, const char *newFileName)
503 {
504     if (fileList == NULL || fileId == 0 || fileId > fileList->num || newFileName == NULL ||
505         strlen(newFileName) == 0 || strlen(newFileName) >= NSTACKX_MAX_REMOTE_PATH_LEN) {
506         return NSTACKX_EINVAL;
507     }
508     if (strcpy_s(fileList->list[fileId - 1].fileName, NSTACKX_MAX_REMOTE_PATH_LEN, newFileName) != EOK) {
509         DFILE_LOGE(TAG, "strcpy_s error");
510         return NSTACKX_EFAILED;
511     }
512     return NSTACKX_EOK;
513 }
514 
FreeFileListInfo(FileListInfo * fileListInfo,uint32_t end)515 static void FreeFileListInfo(FileListInfo *fileListInfo, uint32_t end)
516 {
517     while (end != 0) {
518         free(fileListInfo->files[end - 1]);
519         end--;
520     }
521     free(fileListInfo->files);
522     fileListInfo->files = NULL;
523 }
524 
CopyFilesListInfo(FileListInfo * fileListInfo,FileListPara * fileListPara)525 static int32_t CopyFilesListInfo(FileListInfo *fileListInfo, FileListPara *fileListPara)
526 {
527     uint32_t i;
528     uint32_t end = 0;
529     char tmpFileName[PATH_MAX];
530 
531     for (i = 0; i < fileListPara->fileNum; i++) {
532         /* When second parameter is NULL, realpath() uses malloc() to allocate a buffer of up to PATH_MAX bytes. */
533         if (realpath(fileListPara->files[i], tmpFileName) == NULL) {
534             DFILE_LOGE(TAG, "CreateFileListInfo realpath %s failed errno %d", fileListPara->files[i], errno);
535             end = i;
536             goto L_ERR_FILE;
537         }
538         fileListInfo->files[i] = calloc(1, strlen(fileListPara->files[i]) + 1);
539         if (fileListInfo->files[i] == NULL) {
540             DFILE_LOGE(TAG, "CreateFileListInfo calloc failed");
541             end = i;
542             goto L_ERR_FILE;
543         }
544         if (memcpy_s(fileListInfo->files[i], strlen(fileListPara->files[i]) + 1, fileListPara->files[i],
545             strlen(fileListPara->files[i])) != NSTACKX_EOK) {
546             DFILE_LOGE(TAG, "memcpy_s failed");
547             end = i + 1;
548             goto L_ERR_FILE;
549         }
550         uint32_t len = GetFileNameLen(fileListInfo->files[i]);
551         if (len > NSTACKX_MAX_FILE_NAME_LEN || len == 0 || !IsAccessiblePath(fileListInfo->files[i], R_OK, S_IFREG)) {
552             DFILE_LOGE(TAG, "file name %s is too long or the file is not a readable file", fileListPara->files[i]);
553             end = i + 1;
554             goto L_ERR_FILE;
555         }
556 
557         if (fileListPara->startOffset) {
558             fileListInfo->startOffset[i] = fileListPara->startOffset[i];
559         }
560         if (fileListPara->fileSize) {
561             fileListInfo->fileSize[i] = fileListPara->fileSize[i];
562         }
563     }
564     return NSTACKX_EOK;
565 
566 L_ERR_FILE:
567     FreeFileListInfo(fileListInfo, end);
568     return NSTACKX_EFAILED;
569 }
570 
FileListInfoAddRemotePath(FileListInfo * fileListInfo,const char * remotePath[],uint32_t fileNum)571 static int32_t FileListInfoAddRemotePath(FileListInfo *fileListInfo, const char *remotePath[], uint32_t fileNum)
572 {
573     uint32_t i;
574     uint32_t end = 0;
575     if (fileListInfo == NULL || remotePath == NULL || fileNum == 0) {
576         DFILE_LOGE(TAG, "invalid input");
577         return NSTACKX_EINVAL;
578     }
579     fileListInfo->remotePath = calloc(fileNum, sizeof(char *));
580     if (fileListInfo->remotePath == NULL) {
581         return NSTACKX_EFAILED;
582     }
583 
584     for (i = 0; i < fileNum; i++) {
585         if (fileListInfo->tarFlag != NSTACKX_TRUE) {
586             fileListInfo->remotePath[i] = strdup(remotePath[i]);
587         } else {
588             fileListInfo->remotePath[i] = strdup(remotePath[0]);
589         }
590         if (fileListInfo->remotePath[i] == NULL) {
591             DFILE_LOGE(TAG, "failed for copy %uth remotePath, errno(%d)", i, errno);
592             end = i;
593             goto L_ERR_FILE;
594         }
595         if (strlen(fileListInfo->remotePath[i]) + 1 > NSTACKX_MAX_REMOTE_PATH_LEN) {
596             DFILE_LOGE(TAG, "remotePath is too long");
597             end = i + 1;
598             goto L_ERR_FILE;
599         }
600     }
601 
602     return NSTACKX_EOK;
603 
604 L_ERR_FILE:
605     while (end > 0) {
606         free(fileListInfo->remotePath[end - 1]);
607         end--;
608     }
609     free(fileListInfo->remotePath);
610     fileListInfo->remotePath = NULL;
611     return NSTACKX_EFAILED;
612 }
613 
CreateFileListInfo(FileListPara * fileListPara)614 FileListInfo *CreateFileListInfo(FileListPara *fileListPara)
615 {
616     if (fileListPara->fileNum == 0) {
617         return NULL;
618     }
619     FileListInfo *fileListInfo = calloc(1, sizeof(FileListInfo));
620     if (fileListInfo == NULL) {
621         return NULL;
622     }
623     fileListInfo->fileNum = fileListPara->fileNum;
624     fileListInfo->files = calloc(fileListPara->fileNum, sizeof(char *));
625     if (fileListInfo->files == NULL) {
626         goto L_ERR_LIST;
627     }
628     fileListInfo->tarFlag = fileListPara->tarFlag;
629     fileListInfo->noSyncFlag = NSTACKX_FALSE;
630 
631     if (CopyFilesListInfo(fileListInfo, fileListPara) != NSTACKX_EOK) {
632         goto L_ERR_LIST;
633     }
634 
635     if (fileListPara->userData != NULL) {
636         fileListInfo->userData = strdup(fileListPara->userData);
637         if (fileListInfo->userData == NULL) {
638             goto L_ERR_FILE;
639         }
640     }
641 
642     if (fileListPara->remotePath != NULL &&
643         FileListInfoAddRemotePath(fileListInfo, fileListPara->remotePath, fileListPara->fileNum) != NSTACKX_EOK) {
644         if (fileListPara->userData != NULL) {
645             free(fileListInfo->userData);
646             fileListInfo->userData = NULL;
647         }
648         DFILE_LOGE(TAG, "CreateFileListInfo FileListInfoAddRemotePath failed");
649         goto L_ERR_FILE;
650     }
651 
652     return fileListInfo;
653 
654 L_ERR_FILE:
655     FreeFileListInfo(fileListInfo, fileListPara->fileNum);
656 L_ERR_LIST:
657     free(fileListInfo);
658     return NULL;
659 }
660 
DestroyFileListInfo(FileListInfo * fileListInfo)661 void DestroyFileListInfo(FileListInfo *fileListInfo)
662 {
663     uint32_t i;
664 
665     if (fileListInfo == NULL) {
666         return;
667     }
668 
669     for (i = 0; i < fileListInfo->fileNum; i++) {
670         free(fileListInfo->files[i]);
671     }
672     free(fileListInfo->files);
673     fileListInfo->files = NULL;
674 
675     if (fileListInfo->remotePath != NULL) {
676         for (i = 0; i < fileListInfo->fileNum; i++) {
677             free(fileListInfo->remotePath[i]);
678         }
679         free(fileListInfo->remotePath);
680         fileListInfo->remotePath = NULL;
681     }
682 
683     if (fileListInfo->userData != NULL) {
684         free(fileListInfo->userData);
685         fileListInfo->userData = NULL;
686     }
687     if (fileListInfo->tarFile != NULL) {
688         free(fileListInfo->tarFile);
689         fileListInfo->tarFile = NULL;
690     }
691     free(fileListInfo);
692 }
693