From: Antoni Adaszkiewicz Date: Thu, 8 Sep 2022 09:45:04 +0000 (+0200) Subject: upgrade-apply-deltafs: Rewrite code responsible for reading archive files (deltas... X-Git-Tag: accepted/tizen/unified/20221220.041635~12 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=32e6d7f7e5bd1d2cc9d011e4bca0bf87774ea4b7;p=platform%2Fcore%2Fsystem%2Fupgrade.git upgrade-apply-deltafs: Rewrite code responsible for reading archive files (deltas in tar format) in order to speed up patch application and to allow gziped archives Changes include: - removing the requirement for archives to be named "delta*" - adding support for archives with .tar.gz and .tgz file extensions - using libtar to read archives - reducing the amount of times the archive is read - dropping legacy code along the way Change-Id: Ibbce6a7c36b5520dab21b113200113c48a6b2058 --- diff --git a/src/upgrade-apply-deltafs/CMakeLists.txt b/src/upgrade-apply-deltafs/CMakeLists.txt index a7e335e..b53d7f8 100644 --- a/src/upgrade-apply-deltafs/CMakeLists.txt +++ b/src/upgrade-apply-deltafs/CMakeLists.txt @@ -8,7 +8,6 @@ SET(SRCS ../upgrade-apply/sha1/sha1.c engine/SS_UPI.c engine/SS_FSUpdate.c - engine/fota_tar.c engine/SS_ApplyPatch.c engine/SS_PatchDelta.c engine/fota_log.c @@ -31,5 +30,7 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(EXECNAME "upgrade-apply-deltafs") SET(BINDIR "/usr/bin") ADD_EXECUTABLE(${EXECNAME} ${SRCS}) -TARGET_LINK_LIBRARIES(${EXECNAME} ${${PROJECT_NAME}_pkgs_LDFLAGS} "-g" "-pthread") + +TARGET_LINK_LIBRARIES(${EXECNAME} PRIVATE ${${PROJECT_NAME}_pkgs_LDFLAGS} "-g" "-pthread") +TARGET_LINK_LIBRARIES(${EXECNAME} PRIVATE libtar.a) INSTALL(TARGETS ${EXECNAME} DESTINATION ${BINDIR}) diff --git a/src/upgrade-apply-deltafs/engine/SS_PatchDelta.c b/src/upgrade-apply-deltafs/engine/SS_PatchDelta.c index 299f126..414e1a0 100755 --- a/src/upgrade-apply-deltafs/engine/SS_PatchDelta.c +++ b/src/upgrade-apply-deltafs/engine/SS_PatchDelta.c @@ -26,7 +26,7 @@ #include #include #include -#include "../../upgrade-apply/sha1/sha1.h" +#include "sha1.h" #include "SS_PatchDelta.h" #include "fota_common.h" #include "SS_Engine_Errors.h" @@ -136,7 +136,33 @@ int SS_LoadFile(const char *filename, FileInfo * file) } extern int gvalid_session; -extern void create_dir(char *pathname, int mode); +static void create_dir(char *pathname, int mode) +{ + char *p; + int r; + + /* Strip trailing '/' */ + if (pathname[strlen(pathname) - 1] == '/') + pathname[strlen(pathname) - 1] = '\0'; + + /* Try creating the directory. */ + r = mkdir(pathname, mode); + + if (r != 0) { + /* On failure, try creating parent directory. */ + p = strrchr(pathname, '/'); + if (p != NULL) { + *p = '\0'; + create_dir(pathname, 0755); + *p = '/'; + r = mkdir(pathname, mode); + } + } + if (r != 0) { + if (r != EEXIST && r != -1) + LOG("Could not create directory [%s] Error[%d]\n", pathname, r); + } +} /*! ********************************************************************************* @@ -158,140 +184,34 @@ extern void create_dir(char *pathname, int mode); int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename, const char *source_sha1_str, const char *target_sha1_str, int patch_data_size, char *delta_folder) { - char backup_path[MAX_FILE_PATH], patchfile_source_path[MAX_FILE_PATH]; - snprintf(backup_path, MAX_FILE_PATH, "%s/%s", delta_folder, SS_BACKUP_SOURCE); + char patchfile_source_path[MAX_FILE_PATH]; snprintf(patchfile_source_path, MAX_FILE_PATH, "%s/%s", delta_folder, SS_PATCHFILE_SOURCE); uint8_t target_sha1[SHA_DIGEST_SIZE] = { 0, }; - uint8_t source_sha1[SHA_DIGEST_SIZE] = { 0, }; SHA1_CTX ctx1; int output; int retry = 1; - int use_backup = 0; char *outname = NULL; - int backupsrc = -1; int result = 0; char buf[256]; - FileInfo source_file; - FileInfo target_file; if (ParseSha1(target_sha1_str, target_sha1) != 0) { LOGE("failed to parse tgt-sha1 \"%s\"\n", target_sha1_str); return E_SS_FAILURE; } - /* - if battery removed in between update gvalid_session becomes 0 - need to check file integrity in that case - */ - if (0 == gvalid_session) { - if (ParseSha1(source_sha1_str, source_sha1) != 0) { - LOGE("failed to parse tgt-sha1 \"%s\"\n", source_sha1_str); - return E_SS_FAILURE; - } - if (SS_LoadFile(source_filename, &source_file) == 0) { - SS_Free(source_file.data); - - if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) { - LOGL(LOG_SSENGINE, "Patch Can be applied\n"); - } else if (memcmp(source_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) { - LOGL(LOG_SSENGINE, "Patch Already applied\n"); - return S_SS_SUCCESS; - } else { - //Check for backup file SHA - LOGL(LOG_SSENGINE, "Source was currupted, Try loading from backup source\n"); - - if (SS_LoadFile(target_filename, &target_file) == 0) { - SS_Free(target_file.data); - - if (memcmp(target_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) { - LOGL(LOG_SSENGINE, "Patch Already applied\n"); - return S_SS_SUCCESS; - } - } - - if (SS_LoadFile(backup_path, &source_file) == 0) { - SS_Free(source_file.data); - - if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) { - if (SS_CopyFile(backup_path, source_filename) != S_SS_SUCCESS) { - strerror_r(errno, buf, sizeof(buf)); - LOGE("copy of backup to \"%s\" failed: %s\n", source_filename, buf); - SS_SetUpgradeState(E_SS_FSUPDATEFAILED); - return E_SS_FAILURE; - } - LOGL(LOG_SSENGINE, - "Patch Can be applied from using backup file as source\n"); - } else { - SS_SetUpgradeState(E_SS_FSSRCCURRUPTED); - return E_SS_FAILURE; - } - } else { - SS_SetUpgradeState(E_SS_FSSRCCURRUPTED); - return E_SS_FAILURE; - } - } - } else { - LOGL(LOG_SSENGINE, "Source was deleted!!\n"); - if (SS_LoadFile(target_filename, &target_file) == 0) { - SS_Free(target_file.data); - - if (memcmp(target_file.sha1, target_sha1, SHA_DIGEST_SIZE) == 0) { - LOGL(LOG_SSENGINE, "Patch Already applied\n"); - return S_SS_SUCCESS; - } - } - - LOGL(LOG_SSENGINE, "Try loading from backup source\n"); - if (SS_LoadFile(backup_path, &source_file) == 0) { - SS_Free(source_file.data); - - if (memcmp(source_file.sha1, source_sha1, SHA_DIGEST_SIZE) == 0) { - use_backup = 1; - LOGL(LOG_SSENGINE, "Patch Can be applied from using backup file as source\n"); - } else { - SS_SetUpgradeState(E_SS_FSSRCCURRUPTED); - return E_SS_FAILURE; - } - } else { - LOGE(" SS_LoadFile from backup source failed!!\n"); - SS_SetUpgradeState(E_SS_FSSRCCURRUPTED); - return E_SS_FAILURE; - } - } - } - //Now proceed wit patch application since patch can be applied do { int enough_space = 0; size_t free_space = 0; - char *tok; if (retry > 0) { - if (use_backup) { - tok = strrchr(source_filename, '/'); - *tok = '\0'; - } SS_GetAvailableFreeSpace(source_filename, &free_space); enough_space = (free_space > (256 << 10)) && // 256k (two-block) minimum (free_space > (patch_data_size * 3 / 2)); // 50% margin of error - if (use_backup) - *tok = '/'; - } - - if (!use_backup) { -#ifndef ENHANCED_BSDIFF - backupsrc = SS_BackupSource(source_filename, backup_path); - if (backupsrc != 0) { - LOGE("failed to Backup source File:[%s] \n", source_filename); - SS_SetUpgradeState(E_SS_FSSRCBACKUPFAILED); - return E_SS_FAILURE; - } -#endif } if (!enough_space) { LOGL(LOG_SSENGINE, "For %s: free space %ld bytes; enough %d\n", source_filename, (long)free_space, enough_space); retry = 0; - use_backup = 1; unlink(source_filename); } //LOGL(LOG_SSENGINE, "For %s: target %ld bytes; free space %ld bytes; enough %d\n", @@ -336,10 +256,7 @@ int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename, token = &output; } SHA1Init(&ctx1); - if (use_backup) - result = SS_ApplyBsdiff(backup_path, outname, patchfile_source_path, sink, token, &ctx1); - else - result = SS_ApplyBsdiff((char *)source_filename, outname, patchfile_source_path, sink, token, &ctx1); + result = SS_ApplyBsdiff((char *)source_filename, outname, patchfile_source_path, sink, token, &ctx1); if (output >= 0) { fsync(output); close(output); @@ -393,7 +310,6 @@ int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename, //remove source file if target is not same if (strcmp(source_filename, target_filename) != 0) unlink(source_filename); - SS_BackupSourceClear(backup_path); #endif SS_PatchSourceClear(patchfile_source_path); SS_Free(outname); diff --git a/src/upgrade-apply-deltafs/engine/SS_PatchDelta.h b/src/upgrade-apply-deltafs/engine/SS_PatchDelta.h index 09e5b9d..ba43685 100755 --- a/src/upgrade-apply-deltafs/engine/SS_PatchDelta.h +++ b/src/upgrade-apply-deltafs/engine/SS_PatchDelta.h @@ -50,7 +50,5 @@ extern void SS_Free(void * pMemBlock); extern long SS_CopyFile(const char * strFromPath, const char * strToPath); extern long SS_DeleteFolder(const char * strPath); extern long SS_DeleteFile(const char * strPath); -extern int tar_get_item_size(char * tar, char * item); -extern int tar_extract_file(char * tar, char * item, char * pathname); extern int _system_cmd_wait(const char * command); #endif diff --git a/src/upgrade-apply-deltafs/engine/SS_UPI.c b/src/upgrade-apply-deltafs/engine/SS_UPI.c index 87cccc0..bfc3a6e 100755 --- a/src/upgrade-apply-deltafs/engine/SS_UPI.c +++ b/src/upgrade-apply-deltafs/engine/SS_UPI.c @@ -41,8 +41,8 @@ Function Prototypes Mandatory #include "SS_PatchDelta.h" #include "SS_Engine_Errors.h" #include "SS_FSUpdate.h" +#include "fota_tar.h" -int gtotalFSCnt = 0; int FS_UpgradeState = E_SS_FAILURE; int gvalid_session = 0; //used as fail-safe in case device is turmed off or battery removed during update fs_list *headptr_list; @@ -122,7 +122,6 @@ int SS_rename1(const char *old_file_name, const char *new_file_name) int SS_FSVerifyNode(const char *path, const char *patchname, const char *sha1src, int type, char *patchpath_name, int *data_size, int *data_offset) { - char patch[MAX_FILE_PATH] = { 0 }; FileInfo source_file; uint8_t source_sha1[SHA_DIGEST_SIZE]; @@ -132,20 +131,6 @@ int SS_FSVerifyNode(const char *path, const char *patchname, const char *sha1src SS_SetUpgradeState(E_SS_FSBADNODES); return E_SS_FAILURE; } - snprintf(patch, MAX_FILE_PATH, "%s%s%s", patchpath_name, "/", patchname); - if ((type == DIFFS/*||type == NEWFILES */)) { // allowing size 0 also for folders - if (tar_get_item_size_from_struct(&tar_cfg_data, patchname, data_size, data_offset) - != S_SS_SUCCESS) { - LOGE("failed to get item size from struct, Patch : [%s]\n", patchname); - SS_SetUpgradeState(E_SS_FSBADNODES); - return E_SS_FAILURE; - } - if (*data_size < 0) { - LOGE("failed to verifyNodes [delta absent], Patch : [%s] Type[%d]\n", patch, type); - SS_SetUpgradeState(E_SS_FSBADNODES); - return E_SS_FAILURE; - } - } //For other types (NEWs, SYMs, Folders), SHA check not required if ((type == DIFFS || type == MOVES/* ||type == DELETES */) && (strcmp(sha1src, SS_NULLENTRY) != 0)) { @@ -166,22 +151,6 @@ int SS_FSVerifyNode(const char *path, const char *patchname, const char *sha1src } SS_Free(source_file.data); } - } else { - LOGL(LOG_SSENGINE, "FS partition Already verified - Filling only size and offset \n"); - snprintf(patch, MAX_FILE_PATH, "%s%s%s", patchpath_name, "/", patchname); - if ((type == DIFFS/* ||type == NEWFILES */)) { // allowing size 0 also for folders - if (tar_get_item_size_from_struct(&tar_cfg_data, patchname, data_size, data_offset) - != S_SS_SUCCESS) { - LOGE("failed to get item size from struct, Patch : [%s] \n", patchname); - SS_SetUpgradeState(E_SS_FSBADNODES); - return E_SS_FAILURE; - } - if (*data_size < 0) { - LOGE("failed to verifyNodes [delta absent], Patch : [%s] Type[%d]\n", patch, type); - SS_SetUpgradeState(E_SS_FSBADNODES); - return E_SS_FAILURE; - } - } } return S_SS_SUCCESS; } @@ -215,8 +184,9 @@ int SS_AppendNode(const char *ubDeltaPath, fs_params ** headparam, fs_params ** SS_SetUpgradeState(E_SS_FSINVALIDNODEPARAMS); return E_SS_FAILURE; } + if ((E_SS_FAILURE == - SS_FSVerifyNode(old_path, patchname, sha1src, type, patchpath_name, &data_size, &data_offset))) { + SS_FSVerifyNode(old_path, patchname, sha1src, type, patchpath_name, &data_size, &data_offset))) { LOGE("Bad Nodes, Failed to pass verification - [Delta Path - %s][OldPath - %s] [NewPath - %s] \n", ubDeltaPath, old_path, new_path); return E_SS_FAILURE; @@ -382,17 +352,19 @@ void SS_FSClearNodes() ********************************************************************************* */ -struct details *SS_FSGetDeltaCount(char *ubDeltaPath, char *ubDeltaInfoFile, char *patchlist_backup_patch) +struct details *SS_FSGetDeltaCount(ua_dataSS_t *ua_dataSS) { - int size = 0, bckupsize = 0, ret = 1; + char *ubDeltaPath = ua_dataSS->update_data->ua_delta_path; + char *ubDeltaInfoFile = ua_dataSS->update_delta->ua_patch_info; + int size = 0, read_size = 0, ret = 1; char *token = NULL; char *FileData = NULL; - int data_size = -1; char *line = NULL; char *saveptr = NULL; char buf[256]; struct details *refer_copy = NULL; - FILE *filename_bkup = NULL; + FILE *filename_extract = NULL; + int gtotalFSCnt = 0; if (!(ubDeltaPath && ubDeltaInfoFile)) { LOGE("failed to Parse DELTA count information: \n"); @@ -408,14 +380,17 @@ struct details *SS_FSGetDeltaCount(char *ubDeltaPath, char *ubDeltaInfoFile, cha LOGL(LOG_SSENGINE, "Delta File Info =%s\n", ubDeltaInfoFile); - size = tar_get_item_size(ubDeltaPath, ubDeltaInfoFile); - if (size < 0) { - LOGE("failed to Access DELTA info file DPath:[%s] File: [%s]\n", ubDeltaPath, ubDeltaInfoFile); - SS_SetUpgradeState(E_SS_FSBADDELTA); + filename_extract = fopen(ua_dataSS->tar_data->text_files_info[PATCHLIST_FILE].extracted_name, "r"); + if (filename_extract == NULL) { + strerror_r(errno, buf, sizeof(buf)); + LOGE("Failed to open file Error:[%s]\n", buf); + SS_SetUpgradeState(E_SS_FSFAILEDTOBACKUPPATCHINFO); ret = 0; goto cleanup; } + size = ua_dataSS->tar_data->text_files_info[PATCHLIST_FILE].size; + FileData = SS_Malloc(size + 1); if (FileData == NULL) { LOGE("Failed to Allocate Memory\n"); @@ -424,30 +399,14 @@ struct details *SS_FSGetDeltaCount(char *ubDeltaPath, char *ubDeltaInfoFile, cha goto cleanup; } - memset(FileData, 0, size + 1); - data_size = tar_get_cfg_data(ubDeltaPath, ubDeltaInfoFile, FileData, size); - if (data_size <= 0) { // == 0 is NOT okay?? - LOGE("Failed to read cfg data from Delta\n"); - SS_SetUpgradeState(E_SS_FSBADDELTA); - ret = 0; - goto cleanup; - } - filename_bkup = fopen(patchlist_backup_patch, "wb+"); - if (filename_bkup == NULL) { - strerror_r(errno, buf, sizeof(buf)); - LOGE("Failed to create BACKUP file Error:[%s]\n", buf); + read_size = fread(FileData, 1, size, filename_extract); + if (read_size < size) { SS_SetUpgradeState(E_SS_FSFAILEDTOBACKUPPATCHINFO); ret = 0; goto cleanup; } - bckupsize = fwrite(FileData, 1, data_size, filename_bkup); //RECHECK SIZE 1 - if (bckupsize <= 0) { - SS_SetUpgradeState(E_SS_FSFAILEDTOBACKUPPATCHINFO); - ret = 0; - goto cleanup; - } - LOGL(LOG_SSENGINE, " Size [%d] DataSize [%d] BakUpSize [%d]\n", size, data_size, bckupsize); + LOGL(LOG_SSENGINE, " Size [%d]\n", size); line = strstr(FileData, SS_FSCOUNT_MAGIC_KEY); if (line) { @@ -539,16 +498,13 @@ struct details *SS_FSGetDeltaCount(char *ubDeltaPath, char *ubDeltaInfoFile, cha } cleanup: + SS_Free(FileData); + if (filename_extract) + fclose(filename_extract); if (ret) { - SS_Free(FileData); - if (filename_bkup) - fclose(filename_bkup); return refer_copy; } else { - SS_Free(FileData); SS_Free(refer_copy); - if (filename_bkup) - fclose(filename_bkup); return NULL; } @@ -575,8 +531,6 @@ fs_list *SS_FSBuildNodes(ua_dataSS_t * ua_dataSS) { FILE *fp = NULL; char line[SS_TOKEN_MAXLINE_LEN] = { '\0' }; - char patchlist_backup_patch[MAX_FILE_PATH]; - snprintf(patchlist_backup_patch, MAX_FILE_PATH, "%s/%s",ua_dataSS->update_data->ua_delta_folder, SS_PATCHLIST_BKUPLOC); char string_na[] = "NA"; char *patch_name = NULL; char *source_name = NULL; @@ -612,27 +566,17 @@ fs_list *SS_FSBuildNodes(ua_dataSS_t * ua_dataSS) return NULL; } LOGL(LOG_SSENGINE, " Build Nodes Entry \n"); - if (tar_cfg_data == NULL) - tar_cfg_data = tar_build_cfg_table(ua_dataSS->update_data->ua_delta_path); - if (!tar_cfg_data) { - LOGE(" tar_build_cfg_table Failed \n"); - SS_SetUpgradeState(E_SS_BAD_PARAMS); - return NULL; - } - local = SS_FSGetDeltaCount(ua_dataSS->update_data->ua_delta_path, ua_dataSS->update_delta->ua_patch_info, patchlist_backup_patch); + + local = SS_FSGetDeltaCount(ua_dataSS); if (local == NULL) { LOGE(" Build Nodes Failed \n"); - if (tar_cfg_data) - tar_free_cfg_table(&tar_cfg_data); SS_SetUpgradeState(E_SS_BAD_PARAMS); return NULL; } - fp = fopen(patchlist_backup_patch, "r"); + fp = fopen(ua_dataSS->tar_data->text_files_info[PATCHLIST_FILE].extracted_name, "r"); if (!fp) { SS_SetUpgradeState(E_SS_FSFAILEDTOOPENPATCHINFO); - if (tar_cfg_data) - tar_free_cfg_table(&tar_cfg_data); SS_Free(local); return NULL; } @@ -734,7 +678,7 @@ HARD:NEW:system/lib/firmware/vbc_eq:/opt/system/vbc_eq if (local && (local->news) > 0) { //check if new files archive is present in the delta char new_patch_path[MAX_FILE_PATH] = { 0, }; snprintf(new_patch_path, MAX_FILE_PATH, "%s%s", ua_dataSS->parti_info->ua_subject_name, SS_COMPRESSED_FILE); - if (tar_get_item_size(ua_dataSS->update_data->ua_delta_path, new_patch_path) <= 0) { + if (ua_dataSS->tar_data->new_files_info.offset <= 0) { SS_SetUpgradeState(E_SS_FSFAILEDTOPARSEDELTAINFO); LOGE("New files not present in Patch and they should be\n"); retval = E_SS_FAILURE; @@ -963,10 +907,8 @@ HARD:NEW:system/lib/firmware/vbc_eq:/opt/system/vbc_eq CleanUp: fclose(fp); SS_Free(local); - unlink(patchlist_backup_patch); - if (retval == E_SS_FAILURE) - if (tar_cfg_data) - tar_free_cfg_table(&tar_cfg_data); + unlink(ua_dataSS->tar_data->text_files_info[PATCHLIST_FILE].extracted_name); + ua_dataSS->tar_data->text_files_info[PATCHLIST_FILE].size = 0; return fs_head_node; } @@ -1010,29 +952,32 @@ int SS_FSSetAttributes(ua_dataSS_t * ua_dataSS) int ulAttribSize = 0; int result = S_SS_SUCCESS; int fail_cnt = 0; + int fd = -1; if (!(ua_dataSS && ua_dataSS->update_delta && ua_dataSS->update_data->ua_delta_path)) { LOGE("Bad params for SS_FSSetAttributes\n"); SS_SetUpgradeState(E_SS_BAD_PARAMS); return E_SS_FAILURE; } - LOGL(LOG_SSENGINE, "ATTRIB PATH: [%s] \n", ua_dataSS->update_delta->ua_attrib_path); - - int item_size = tar_get_item_size(ua_dataSS->update_data->ua_delta_path, ua_dataSS->update_delta->ua_attrib_path); - + LOGL(LOG_SSENGINE, "ATTRIB PATH: [%s] \n", ua_dataSS->tar_data->text_files_info[ATTR_FILE].extracted_name); + int item_size = ua_dataSS->tar_data->text_files_info[ATTR_FILE].size; if (item_size <= 0) { LOGL(LOG_SSENGINE, "No Attributes to SET\n"); return S_SS_SUCCESS; // Delta with ONLY deletes } + char *item_data = SS_Malloc(item_size + 1); if (item_data == NULL) { LOGE("SS_Malloc failed!! - item_data\n"); SS_SetUpgradeState(E_SS_MALLOC_ERROR); return E_SS_FAILURE; } - int read_data = - tar_get_cfg_data(ua_dataSS->update_data->ua_delta_path, ua_dataSS->update_delta->ua_attrib_path, item_data, - item_size); + if ((fd = open(ua_dataSS->tar_data->text_files_info[ATTR_FILE].extracted_name, O_RDONLY)) < 0) { + LOGE("Cannot open attr file!\n"); + unlink(ua_dataSS->tar_data->text_files_info[ATTR_FILE].extracted_name); + ua_dataSS->tar_data->text_files_info[ATTR_FILE].size = 0; + } + int read_data = read(fd, item_data, item_size); if (read_data <= 0) { LOGE("read_data failed!!\n"); SS_SetUpgradeState(E_SS_FSBADDELTA); @@ -1040,6 +985,9 @@ int SS_FSSetAttributes(ua_dataSS_t * ua_dataSS) SS_Free(item_data); item_data = NULL; } + close(fd); + unlink(ua_dataSS->tar_data->text_files_info[ATTR_FILE].extracted_name); + ua_dataSS->tar_data->text_files_info[ATTR_FILE].size = 0; return E_SS_FAILURE; } item_data[read_data] = '\0'; @@ -1051,6 +999,9 @@ int SS_FSSetAttributes(ua_dataSS_t * ua_dataSS) SS_Free(item_data); item_data = NULL; } + close(fd); + unlink(ua_dataSS->tar_data->text_files_info[ATTR_FILE].extracted_name); + ua_dataSS->tar_data->text_files_info[ATTR_FILE].size = 0; return E_SS_FAILURE; } @@ -1105,6 +1056,9 @@ int SS_FSSetAttributes(ua_dataSS_t * ua_dataSS) else result = S_SS_SUCCESS; + close(fd); + unlink(ua_dataSS->tar_data->text_files_info[ATTR_FILE].extracted_name); + ua_dataSS->tar_data->text_files_info[ATTR_FILE].size = 0; return result; } @@ -1134,8 +1088,7 @@ int SS_FSUpdateFile(int ubFileType, ua_dataSS_t * ua_dataSS, int ulPatchCount, f FileInfo source_file; FileInfo target_file; uint8_t target_sha1[SHA_DIGEST_SIZE] = { 0, }; - char new_compressed_path[MAX_FILE_PATH], patchfile_source_path[MAX_FILE_PATH]; - snprintf(new_compressed_path, MAX_FILE_PATH, "%s/%s", ua_dataSS->update_data->ua_delta_folder, SS_NEW_COMPRESSED_FILE); + char patchfile_source_path[MAX_FILE_PATH]; snprintf(patchfile_source_path, MAX_FILE_PATH, "%s/%s", ua_dataSS->update_data->ua_delta_folder, SS_PATCHFILE_SOURCE); if (!patch_path) { @@ -1146,51 +1099,51 @@ int SS_FSUpdateFile(int ubFileType, ua_dataSS_t * ua_dataSS, int ulPatchCount, f case DIFFS: { LOGL(LOG_SSENGINE, "DIFFS mode start\n"); - tar_open(ua_dataSS->update_data->ua_delta_path); - while (pFsNode) { + diff_iterator diff_iter; + if (tar_init_diff_iterations(ua_dataSS->tar_data, &diff_iter, pFsNode) < 0) { + ulResult = E_SS_FAILURE; + SS_SetUpgradeState(E_SS_FSUPDATEFAILED); + LOGE("Couldn't begin updating diffs!\n"); + break; + } + for (;;) + { //LOGL(LOG_SSENGINE, "DIFFS update Index: [%d] \n", ulFileIndex++); snprintf(ubPatch, SS_MAX_FILE_PATH, "%s%s", patch_path, pFsNode->patch_name); //LOGL(LOG_SSENGINE, "DIFF list --- [File Name %s]\n [Patch Name %s]",pFsNode->file_path, ubPatch); - if (pFsNode->data_size > 0) { - ulReadCnt = - fast_tar_extract_file(ua_dataSS->update_data->ua_delta_path, ubPatch, patchfile_source_path, - pFsNode->data_size, pFsNode->data_offset); - if (ulReadCnt < 0) { - ulResult = E_SS_FAILURE; - tar_close(); - SS_SetUpgradeState(E_SS_FSUPDATEFAILED); - LOGE("Delta Read Failed\n"); - break; - } - //LOGL(LOG_SSENGINE,"Updating [Item - %s]and size is[%d] Read Count[%d]\n",ubPatch, pFsNode->data_size, ulReadCnt); - - if (ulReadCnt > 0) - ulResult = - SS_UpdateDeltaFS(pFsNode->file_old_path, pFsNode->file_new_path, pFsNode->sha1src, - pFsNode->sha1trg, pFsNode->data_size, ua_dataSS->update_data->ua_delta_folder); + int broken = 0; + fs_params *temp_param; + switch(tar_diff_iter_next_extract(ua_dataSS->tar_data, &diff_iter, patchfile_source_path, &temp_param)) + { + case -1: + broken = 1; + ulResult = E_SS_FAILURE; + SS_SetUpgradeState(E_SS_FSUPDATEFAILED); + LOGE("Delta Read Failed\n"); + break; + case 1: + broken = 1; + ulResult = S_SS_SUCCESS; + break; + case 0: + ulResult = + SS_UpdateDeltaFS(temp_param->file_old_path, temp_param->file_new_path, temp_param->sha1src, + temp_param->sha1trg, temp_param->data_size, ua_dataSS->update_data->ua_delta_folder); if (ulResult != S_SS_SUCCESS) { LOGE("FS update Failed Result : [%d], [Item - %s]and size is[%d] Read Count[%d], index = [%d]\n", ulResult, - ubPatch, pFsNode->data_size, ulReadCnt, ulFileIndex); - tar_close(); + ubPatch, temp_param->data_size, ulReadCnt, ulFileIndex); SS_SetUpgradeState(E_SS_FSUPDATEFAILED); break; } - SS_UpdateUIProgress(ua_dataSS, ulPatchCount, 0); - pFsNode = pFsNode->nextnode; } - else { - ulResult = E_SS_FAILURE; - tar_close(); - LOGE("size is invalid, index = [%d]\n", - ulFileIndex); - SS_SetUpgradeState(E_SS_FSUPDATEFAILED); + if (broken == 1) break; - } + + SS_UpdateUIProgress(ua_dataSS, ulPatchCount, 0); ulFileIndex++; } LOGL(LOG_SSENGINE, "DIFFS : Total index = [%d]\n", ulFileIndex - 1); - tar_close(); LOGL(LOG_SSENGINE, "DIFFS mode end\n"); } break; @@ -1335,14 +1288,19 @@ int SS_FSUpdateFile(int ubFileType, ua_dataSS_t * ua_dataSS, int ulPatchCount, f { LOGL(LOG_SSENGINE, "NEWFILES mode start\n"); LOGL(LOG_SSENGINE, "Starting New file upgrade for [%s]\n", patch_path); - if (tar_extract_file(ua_dataSS->update_data->ua_delta_path, (char *)patch_path, new_compressed_path) >= 0) { - if (_7zdecompress(new_compressed_path) == 0) + if (ua_dataSS->tar_data->new_files_info.offset > 0) { + if (tar_extract_7z_file(ua_dataSS->tar_data) < 0) { + LOGE("newfiles extraction error!\n"); + ulResult = E_SS_FAILURE; + break; + } + if (_7zdecompress(ua_dataSS->tar_data->new_files_info.extracted_name) == 0) LOGL(LOG_SSENGINE, "7zip extracted successfully %s\n", ua_dataSS->parti_info->ua_parti_name); else LOGL(LOG_SSENGINE, "7zip extraction error for %s\n", ua_dataSS->parti_info->ua_parti_name); - SS_DeleteFile(new_compressed_path); + SS_DeleteFile(ua_dataSS->tar_data->new_files_info.extracted_name); } else { - LOGL(LOG_SSENGINE, "No %s in %s, becouse there are no new files\n", SS_COMPRESSED_FILE, ua_dataSS->parti_info->ua_parti_name); + LOGL(LOG_SSENGINE, "No %s in %s, because there are no new files\n", SS_COMPRESSED_FILE, ua_dataSS->parti_info->ua_parti_name); } LOGL(LOG_SSENGINE, "NEWFILES mode end\n"); } @@ -1503,14 +1461,6 @@ int SS_FSUpdatemain(ua_dataSS_t * ua_dataSS) return E_SS_BAD_PARAMS; // Set error ?? head_ptr_node = headptr_list; - if (!head_ptr_node) { //in case of power failure, try rebilding nodes again - SS_FSVerifyPartition(ua_dataSS); - head_ptr_node = headptr_list; - } - - if (!head_ptr_node) - return E_SS_FSBADNODES; - SS_GetPartition_LocDetails(ua_dataSS); LOGL(LOG_SSENGINE, "FS Update Entry\n"); diff --git a/src/upgrade-apply-deltafs/engine/SS_UPI.h b/src/upgrade-apply-deltafs/engine/SS_UPI.h index 5968ab9..0005a79 100755 --- a/src/upgrade-apply-deltafs/engine/SS_UPI.h +++ b/src/upgrade-apply-deltafs/engine/SS_UPI.h @@ -18,8 +18,8 @@ #ifndef _SS_UPI_H_ #define _SS_UPI_H_ -#include #include "fota_common.h" +#include "SS_Common.h" #define DISPLAYRESOLUTION_SIZE 50 @@ -70,19 +70,10 @@ extern int SS_FSVerifyPartition(ua_dataSS_t * ua_dataSS); //extra functions extern void *SS_Malloc(unsigned int size); -extern int tar_get_item_size_from_struct(tar_Data_t **, const char *, int *, int *); extern void SS_Free(void *pMemBlock); -extern int tar_get_item_size(char *tar, char *item); -extern int tar_get_cfg_data(char *tar, char *item, char *buf, int buflen); -extern tar_Data_t *tar_build_cfg_table(char *tar); -extern int tar_open(char *tar); -extern int fast_tar_extract_file(char *tar, char *item, char *pathname, int size, int offset); -extern int tar_close(); extern int SS_UpdateDeltaFS(const char *source_filename, const char *target_filename, const char *source_sha1_str, const char *target_sha1_str, int patch_data_size, char *delta_folder); -extern int tar_extract_file(char *tar, char *item, char *pathname); extern int _7zdecompress(char *path); -extern void tar_free_cfg_table(tar_Data_t ** delta_tar); extern long SS_GetFileType(char *pLinkName, enumFileType * fileType); #endif //_SS_UPI_H_ diff --git a/src/upgrade-apply-deltafs/engine/fota_common.h b/src/upgrade-apply-deltafs/engine/fota_common.h index cc3869f..c5310d2 100755 --- a/src/upgrade-apply-deltafs/engine/fota_common.h +++ b/src/upgrade-apply-deltafs/engine/fota_common.h @@ -45,6 +45,9 @@ typedef u32 size_t; #define SS_PATCHLISTFORMAT ".txt" #define SS_PATCH_ATTR_FORMAT "_attr.txt" +#define SS_GENERIC_FILE "file" +#define SS_GENERIC_PATCHLIST SS_GENERIC_FILE SS_PATCHLISTFORMAT +#define SS_GENERIC_ATTR SS_GENERIC_FILE SS_PATCH_ATTR_FORMAT #define SS_FSCOUNT_MAGIC_KEY "PaTcHCoUnT:" #define SS_FSCOUNT_MAGIG_KEYLEN (11) //length of SS_FSCOUNT_MAGIC_KEY @@ -69,8 +72,6 @@ typedef u32 size_t; #define SS_STRING_ZIP "ZIP" #define SS_STRING_END "END" -#define SS_COMMON_WORKSPACE "/run/upgrade-sysroot/opt/usr/data/fota" - struct tar_Data { int itemSize; int itemOffset; diff --git a/src/upgrade-apply-deltafs/engine/fota_tar.c b/src/upgrade-apply-deltafs/engine/fota_tar.c index ff7233a..2f8fef9 100755 --- a/src/upgrade-apply-deltafs/engine/fota_tar.c +++ b/src/upgrade-apply-deltafs/engine/fota_tar.c @@ -1,7 +1,7 @@ /* * upgrade-apply-deltafs * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. @@ -24,820 +24,360 @@ #include #include #include +#include "fota_log.h" #include "SS_Engine_Errors.h" #include "SS_FSUpdate.h" #include "fota_common.h" #include "fota_tar.h" -#include "ua_types.h" - -/* tar Header Block, from POSIX 1003.1-1990. for reference */ -#if 0 - /* POSIX header. */ - -struct posix_header { /* byte offset */ - char name[100]; /* 0 */ - char mode[8]; /* 100 */ - char uid[8]; /* 108 */ - char gid[8]; /* 116 */ - char size[12]; /* 124 */ - char mtime[12]; /* 136 */ - char chksum[8]; /* 148 */ - char typeflag; /* 156 */ - char linkname[100]; /* 157 */ - char magic[6]; /* 257 */ - char version[2]; /* 263 */ - char uname[32]; /* 265 */ - char gname[32]; /* 297 */ - char devmajor[8]; /* 329 */ - char devminor[8]; /* 337 */ - char prefix[155]; /* 345 */ - /* 500 */ -}; -#endif - -#define MAX_ITEM_SIZE 0x7FFFFFFF -#define TAR_ITEM_SIZE_POSITION 124 -#define TAR_SIZE_OF_ITEM_SIZE 8 -#define TAR_SIZE_OF_HEADER 12 -#define TAR_BLOCK_SIZE 512 -#define TAR_ITEM_NAME_SIZE 100 -#define TAR_LONG_NAME_SIZE 256 -#define TAR_ITEM_TYPE_FLAG_POS 156 -/*** The byte that indicates whether the prefix is present or not */ -#define PREFIX_INDICATOR_BYTE 345 -#define PREFIX_LEN 155 - -/** the rest heavily based on (ie mostly) untgz.c from zlib **/ - -/* Values used in typeflag field. */ - -#define REGTYPE '0' /* regular file */ -#define AREGTYPE '\0' /* regular file */ -#define LNKTYPE '1' /* link */ -#define SYMTYPE '2' /* reserved */ -#define CHRTYPE '3' /* character special */ -#define BLKTYPE '4' /* block special */ -#define DIRTYPE '5' /* directory */ -#define FIFOTYPE '6' /* FIFO special */ -#define CONTTYPE '7' /* reserved, for compatibility with gnu tar, - treat as regular file, where it represents - a regular file, but saved contiguously on disk */ - -/* GNU tar extensions */ - -#define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */ -#define GNUTYPE_LONGLINK 'K' /* long link name */ -#define GNUTYPE_LONGNAME 'L' /* long file name */ -#define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */ -#define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */ -#define GNUTYPE_SPARSE 'S' /* sparse file */ -#define GNUTYPE_VOLHDR 'V' /* tape/volume header */ - -extern void *SS_Malloc(SS_UINT32 size); - -int gTarFd = -1; // Currenlty this logic supports only one tar file - -void create_dir(char *pathname, int mode) + +#define VISITED_STRING "VISITED" +#define DIFF_PREFIX "/diff" +#define GENERIC_FILENAME "file.txt" + +// for the sake of simplicity this stays global +static gzFile gz_tar = NULL; + +// the following 6 functions are copied from this same repo, upgrade-apply/main.c +void fd_cleanup(int *fd) { - char *p; - int r; - - /* Strip trailing '/' */ - if (pathname[strlen(pathname) - 1] == '/') - pathname[strlen(pathname) - 1] = '\0'; - - /* Try creating the directory. */ - r = mkdir(pathname, mode); - - if (r != 0) { - /* On failure, try creating parent directory. */ - p = strrchr(pathname, '/'); - if (p != NULL) { - *p = '\0'; - create_dir(pathname, 0755); - *p = '/'; - r = mkdir(pathname, mode); - } - } - if (r != 0) { - if (r != EEXIST && r != -1) - LOG("Could not create directory [%s] Error[%d]\n", pathname, r); - } + if (!fd || *fd < 0) + return; + close(*fd); } -/*----------------------------------------------------------------------------- - tar_get_item_offset - ----------------------------------------------------------------------------*/ -int tar_get_item_offset(char *tar, char *item) +int gzip_open(const char *pathname, int oflags, ...) { - int ret = -1; - int fd = -1; - char header[TAR_BLOCK_SIZE] = { 0, }; - char uExtendedName[MAX_FILE_PATH + 1] = { 0, }; - char size_oct[TAR_SIZE_OF_HEADER] = { 0, }; - unsigned long size_dec = 0; - int blknum = 0; - off_t pos = 0; - off_t tar_len = 0; - ssize_t rdcnt = 0; - - if (!item || !tar){ - LOG("Invalid params\n"); + if (gz_tar != NULL) { + errno = EALREADY; return -1; - }; - //check if gTarFd was opened by tar_open during SS_FSUpdateFile then use it - if (gTarFd >= 0) - fd = gTarFd; - else { - fd = open(tar, O_RDONLY); - if (fd < 0) { - LOGE("can't open file(%s).\n", tar); - return -1; - } } - tar_len = lseek(fd, 0, SEEK_END); - if (tar_len < 0) { - LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar); - goto Cleanup; - } - pos = lseek(fd, 0, SEEK_SET); - if (pos < 0) { - LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar); - goto Cleanup; + // We assume oflags == O_RDONLY, since that's what we actually use. + // Also we don't care about the mode since we are lazy. + if (oflags != O_RDONLY) { + errno = ENOTSUP; + return -1; } - while (pos < tar_len) { - /* read file header */ - rdcnt = read(fd, header, sizeof(header)); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - break; - } - - /* get file name and file size */ - if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) { - //rdcnt = read(fd, header, sizeof(header)); - memset(uExtendedName, 0, sizeof(uExtendedName)); - rdcnt = read(fd, uExtendedName, sizeof(uExtendedName) - 1); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - break; - } - rdcnt = read(fd, header, sizeof(header)); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - break; - } - } else { - memset(uExtendedName, 0, sizeof(uExtendedName)); - memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE); - } - memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct)); - size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE); - if (size_dec > MAX_ITEM_SIZE) { - LOG("ITEM : [%s]\n", item); - LOG("size too big. (size_dec=0x%08X)\n", size_dec); - break; - } - - /* check if the file is what we are looking for */ - if (strncmp(uExtendedName, item, sizeof(uExtendedName) - 1) == 0) { - ret = (int)lseek(fd, 0, SEEK_CUR); - break; - } - /* move file pointer to next file header */ - blknum = size_dec / TAR_BLOCK_SIZE; - if (size_dec % TAR_BLOCK_SIZE) - blknum++; - - pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR); - if (pos < 0) { - LOGE("can't read next block (%s).\n", tar); - close(fd); - return -1; - } - } + __attribute__((cleanup(fd_cleanup))) int inner_fd = open(pathname, O_RDONLY); + if (inner_fd == -1) + return -1; - Cleanup: - if (gTarFd < 0) - close(fd); + gz_tar = gzopen(pathname, "r"); + if (gz_tar == NULL) + return -1; + inner_fd = -1; - return ret; + return 1; } -/*----------------------------------------------------------------------------- - tar_get_item_size - ----------------------------------------------------------------------------*/ -int tar_get_item_size(char *tar, char *item) +int gzip_close(__attribute__((unused)) int useless_fd) { - int ret = -1; - int fd = -1; - char header[TAR_BLOCK_SIZE] = { 0, }; - char uExtendedName[MAX_FILE_PATH + 1] = { 0, }; - char size_oct[TAR_SIZE_OF_HEADER] = { 0, }; - unsigned long size_dec = 0; - int blknum = 0; - off_t pos = 0; - off_t tar_len = 0; - ssize_t rdcnt = 0; - - if (!item || !tar){ - LOG("Invalid params\n"); + if (gz_tar == NULL) { + errno = EINVAL; return -1; } - LOGL(LOG_SSENGINE, "Tar file Looking for (%s)\n", item); - fd = open(tar, O_RDONLY); - if (fd < 0) { - LOG("can't open file(%s).\n", tar); - return -1; - } - - tar_len = lseek(fd, 0, SEEK_END); - if (tar_len < 0) { - LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar); - goto Cleanup; - } - pos = lseek(fd, 0, SEEK_SET); - if (pos < 0) { - LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar); - goto Cleanup; - } - - while (pos < tar_len) { - /* read file header */ - rdcnt = read(fd, header, sizeof(header)); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - break; - } - - /* get file name and file size */ - if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) { - //rdcnt = read(fd, header, sizeof(header)); - memset(uExtendedName, 0, sizeof(uExtendedName)); - rdcnt = read(fd, uExtendedName, sizeof(uExtendedName) - 1); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - break; - } - rdcnt = read(fd, header, sizeof(header)); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - break; - } - } else { - memset(uExtendedName, 0, sizeof(uExtendedName)); - memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE); - } - memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct)); - size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE); - if (size_dec > MAX_ITEM_SIZE) { - LOG("ITEM : [%s]\n", item); - LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec); - break; - } - - /* check if the file is what we are looking for */ - if (strncmp(uExtendedName, item, sizeof(uExtendedName) - 1) == 0) { - ret = (int)size_dec; - if ((ret == 0) && (header[TAR_ITEM_TYPE_FLAG_POS] == DIRTYPE)) - ret = tar_get_folder_size(tar, item); - break; - } - /* move file pointer to next file header */ - //LOGL(LOG_SSENGINE,"Item in Tar (%s)\n", uExtendedName); - blknum = size_dec / TAR_BLOCK_SIZE; - if (size_dec % TAR_BLOCK_SIZE) - blknum++; - - pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR); - if (pos < 0) { - LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar); - close(fd); - return -1; - } - } - - Cleanup: - close(fd); - return ret; + return gzclose(gz_tar); } -/*----------------------------------------------------------------------------- - tar_get_cfg_data - ----------------------------------------------------------------------------*/ -int tar_get_cfg_data(char *tar, char *item, char *buf, int buflen) +ssize_t gzip_read(__attribute__((unused)) int useless_fd, void *buf, size_t len) { - int fd = -1; - int data_size = -1; - int data_offset = -1; - off_t pos = 0; - ssize_t rdcnt = 0; - - if (!buf){ - LOG("Invalid params\n"); + if (gz_tar == NULL) { + errno = EINVAL; return -1; } - data_size = tar_get_item_size(tar, item); - if (data_size <= 0) - return -1; - if (data_size > buflen) - data_size = buflen; + return gzread(gz_tar, buf, len); +} - data_offset = tar_get_item_offset(tar, item); - if (data_offset < 0) - return -1; +ssize_t gzip_write(__attribute__((unused)) int useless_fd, __attribute__((unused)) const void *buf, __attribute__((unused)) size_t len) +{ + // Again, we do not use this. + errno = ENOTSUP; + return -1; +} - fd = open(tar, O_RDONLY); - if (fd < 0) { - LOG("can't open file(%s).\n", tar); - return -1; - } +int tar_get_tartype(char *tar_path, tartype_t **type) +{ + static tartype_t gzip_type = {gzip_open, gzip_close, gzip_read, gzip_write}; - pos = lseek(fd, data_offset, SEEK_SET); - if (pos < 0) { - LOG("lseek fail (%s offset %d).\n", tar, data_offset); - close(fd); + if ((strlen(tar_path) > strlen(".tar")) && (strcmp(tar_path + strlen(tar_path) - strlen(".tar"), ".tar") == 0)) { + *type = NULL; + } + else if ((strlen(tar_path) > strlen(".tar.gz")) && (strcmp(tar_path + strlen(tar_path) - strlen(".tar.gz"), ".tar.gz") == 0)) { + *type = &gzip_type; + } + else if ((strlen(tar_path) > strlen(".tgz")) && (strcmp(tar_path + strlen(tar_path) - strlen(".tgz"), ".tgz") == 0)) { + *type = &gzip_type; + } + else { + LOGE("Unknown/unsupported file extension for delta!!!\n"); return -1; } + return 0; +} - rdcnt = read(fd, buf, data_size); - if (rdcnt != (ssize_t) data_size) { - LOG("read fail(%s from %s).\n", item, tar); - close(fd); +int tar_init_with_type(TAR **tar, char *tar_path, tartype_t *type) +{ + if (tar_open(tar, tar_path, type, O_RDONLY, 0, 0) < 0) { + *tar = NULL; + LOGE("tar_open() fail!\n"); return -1; } - - close(fd); - - return rdcnt; + return 0; } -tar_Data_t *tar_build_cfg_table(char *tar) +static off_t tar_seek(TAR *tar, off_t offset, int whence) { + if(!gz_tar) + return lseek(tar_fd(tar), offset, whence); + return gzseek(gz_tar, offset, whence); +} - int fd = -1; - int ret = 0; - char header[TAR_BLOCK_SIZE] = { 0, }; - char uExtendedName[MAX_FILE_PATH + 1] = { 0, }; - char size_oct[TAR_SIZE_OF_HEADER] = { 0, }; - unsigned long size_dec = 0; - int blknum = 0; - off_t pos = 0; - off_t tar_len = 0; - ssize_t rdcnt = 0; - - int itemSize; - int itemOffset; - tar_Data_t *headparam = NULL, *tailparam = NULL, *newnode = NULL; - tar_Data_t *local_temp = NULL; - tar_Data_t *local_next = NULL; - if (!tar) { - LOGE("Bad param tar\n"); - return NULL; - } - //check if gTarFd was opened by tar_open during SS_FSUpdateFile then use it - if (gTarFd >= 0) - fd = gTarFd; - else { - fd = open(tar, O_RDONLY); - if (fd < 0) { - LOG("can't open file(%s).\n", tar); - return NULL; +static int tar_reset_to_subject(TAR *tar, char *subject_name, off_t *offset) +{ + if (*offset > 0) { + if (tar_seek(tar, *offset, SEEK_SET) < 0) { + LOGE("seeking error!\n"); + return -1; } + if (th_read(tar) < 0) { + LOGE("unexpected th_read() return value!\n"); + return -1; + } + return 0; } - tar_len = lseek(fd, 0, SEEK_END); - if (tar_len < 0) { - LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar); - goto Cleanup; - } - pos = lseek(fd, 0, SEEK_SET); - if (pos < 0) { - LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar); - goto Cleanup; + off_t local_offset = 0; + if (tar_seek(tar, 0, SEEK_SET) < 0) { + LOGE("seeking error!\n"); + return -1; } - while (pos < tar_len) { - /* read file header */ - rdcnt = read(fd, header, sizeof(header)); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - ret = -1; - break; - } - /* get file name and file size */ - if (header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGNAME || header[TAR_ITEM_TYPE_FLAG_POS] == GNUTYPE_LONGLINK) { - //rdcnt = read(fd, header, sizeof(header)); - memset(uExtendedName, 0, sizeof(uExtendedName)); - rdcnt = read(fd, uExtendedName, sizeof(uExtendedName) - 1); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - ret = -1; - break; - } - rdcnt = read(fd, header, sizeof(header)); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - ret = -1; - break; - } - } else { - memset(uExtendedName, 0, sizeof(uExtendedName)); - memcpy(uExtendedName, header, TAR_ITEM_NAME_SIZE); - } - memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct)); - size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE); - if (size_dec > MAX_ITEM_SIZE) { - LOG("uExtendedName is : [%s]\n", uExtendedName); - LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec); - ret = -1; + + for (;;) + { + // if 1 is returned we should fail as well + switch (th_read(tar)) + { + case -1: + LOGE("th_read() fail!\n"); + return -1; + case 1: + LOGE("EOF reached -> delta error!\n"); + return -1; + case 0: break; } - //fix WGID : 51254 , size_dec comparison is not required - if ((strstr(uExtendedName, "/diff") != NULL)) { //add only delta files from rootfs and csc, hardcoding shd b removed.. - - /* check if the file is what we are looking for */ - //strncpy(itemName, name,100); - itemSize = (int)size_dec; - itemOffset = (int)lseek(fd, 0, SEEK_CUR); - newnode = (tar_Data_t *) SS_Malloc(sizeof(tar_Data_t)); - if (!newnode) { - ret = -1; - break; - } - memset(newnode->itemName, 0, sizeof(newnode->itemName)); - strncpy((char *)newnode->itemName, uExtendedName, sizeof(newnode->itemName) - 1); - newnode->itemOffset = itemOffset; - newnode->itemSize = itemSize; - newnode->nextnode = NULL; - if (headparam == NULL) { - headparam = newnode; - tailparam = newnode; - } else { - (tailparam)->nextnode = newnode; - (tailparam) = (tailparam)->nextnode; - } - } - /* move file pointer to next file header */ - blknum = size_dec / TAR_BLOCK_SIZE; - if (size_dec % TAR_BLOCK_SIZE) - blknum++; - - pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR); - if (pos < 0) { - LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar); - ret = -1; + char *pathname = th_get_pathname(tar); + if (strcmp(pathname, subject_name) == 0) { + *offset = local_offset; break; } - } - Cleanup: - //if gTarFd was opened by tar_open during SS_FSUpdateFile we do not close it - if (gTarFd < 0) - close(fd); - if (ret != -1) - return headparam; - else { - if (headparam != newnode && newnode) - SS_Free(newnode); - if (headparam) { - local_temp = headparam; - while (local_temp) { - local_next = local_temp->nextnode; - SS_Free(local_temp); - local_temp = local_next; - } + + if (TH_ISREG(tar) && (tar_skip_regfile(tar) < 0)) { + LOGE("tar_skip_regfile() error!\n"); + return -1; } - return NULL; - } -} -void tar_free_cfg_table(tar_Data_t ** delta_tar) -{ - tar_Data_t *local_temp = NULL; - tar_Data_t *local_next = NULL; - LOGL(LOG_SSENGINE, "Free TAR CFG TABLE\n"); - if (*delta_tar) { - local_temp = *delta_tar; - while (local_temp) { - local_next = local_temp->nextnode; - //LOGL(LOG_SSENGINE,"freeing [%s]\n",local_temp->itemName); - SS_Free(local_temp); - local_temp = local_next; + if ((local_offset = tar_seek(tar, 0, SEEK_CUR)) < 0) { + LOGE("seeking error!\n"); + return -1; } } + return 0; } -void deleteNode(tar_Data_t * head, tar_Data_t * n) +static int tar_verify_and_extract_text(tar_info *tar_data, char *pathname, off_t last_seek) { - tar_Data_t *prev = head; - if (head == n) { - if (head->nextnode == NULL) { - LOG("There is only one node. The list can't be made empty\n"); - return; + if (strcmp(tar_data->new_files_info.item_name, pathname) == 0) { + if (tar_data->new_files_info.offset > 0) { + LOGE("Dupicate file found in delta!\n"); + return -1; } - strncpy((char *)head->itemName, (const char *)head->nextnode->itemName, TAR_ITEM_NAME_SIZE); //head->itemName = head->nextnode->itemName; - head->itemSize = head->nextnode->itemSize; - head->itemOffset = head->nextnode->itemOffset; - n = head->nextnode; - head->nextnode = head->nextnode->nextnode; - SS_Free(n); - return; + tar_data->new_files_info.offset = last_seek; + LOGL(LOG_SSENGINE, "%s found in archive\n", tar_data->new_files_info.item_name); + return 0; } - while (prev->nextnode != NULL && prev->nextnode != n) - prev = prev->nextnode; - if (prev->nextnode == NULL) { - LOG("Given node is not present in Linked List\n"); - return; - } - prev->nextnode = prev->nextnode->nextnode; - SS_Free(n); - return; -} -int tar_get_item_size_from_struct(tar_Data_t ** delta_tar, const char *patchname, int *data_size, int *data_offset) -{ - tar_Data_t *head = *delta_tar; - tar_Data_t *base = *delta_tar; - if (head == NULL) - return 1; - else { - //LOG("fast_tar_get_item_size- looking for [%s] [%s]\n",patchname,head->itemName); - while (1) { - if (strstr((const char *)head->itemName, patchname) != 0) { - //LOG("fast_tar_get_item_size found [%s] in [%s]\n",patchname, head->itemName); - *data_size = head->itemSize; - *data_offset = head->itemOffset; - deleteNode(base, head); - return 0; - - } else if (head->nextnode != NULL) { - head = head->nextnode; - //LOG("fast_tar_get_item_size current node [%s] \n",head->itemName); - } else { - LOGE("fast_tar_get_item_size FAILED TO GET [%s] in [%s]\n", patchname, (char *)head->itemName); - break; + for(int i = 0; i < NO_OF_TEXT_FILES; i++) + { + if (strcmp(tar_data->text_files_info[i].item_name, pathname) == 0) { + if (tar_data->text_files_info[i].size > 0) { + LOGE("Dupicate file found in delta!\n"); + return -1; + } + tar_data->text_files_info[i].size = th_get_size(tar_data->tar); + if (tar_data->text_files_info[i].size == 0) { + LOGE("Needed file has size 0!"); + return -1; + } + if (tar_extract_file(tar_data->tar, tar_data->text_files_info[i].extracted_name) != 0) { + tar_data->text_files_info[i].size = 0; + LOGE("tar extraction error!"); + return -1; } + LOGL(LOG_SSENGINE, "%s found in archive\n", tar_data->text_files_info[i].item_name); + return 1; } - return 1; - } -} - -int tar_open(char *tar) -{ - if (gTarFd >= 0) - close(gTarFd); - gTarFd = open(tar, O_RDONLY); - if (gTarFd < 0) { - LOG("can't open TAR file(%s).\n", tar); - return -1; } return 0; } -int tar_close() +int tar_get_cfg_data(tar_info *tar_data) { - if (gTarFd >= 0) - close(gTarFd); - gTarFd = -1; - return 0; -} - -int tar_get_folder_size(char *tar, char *item) -{ - int ret = -1; - int fd = -1; - char header[TAR_BLOCK_SIZE] = { 0, }; - char name[TAR_LONG_NAME_SIZE + 1] = { 0, }; - char *lastfolder = NULL; - int folderpathlen = 0; - char size_oct[TAR_SIZE_OF_HEADER] = { 0, }; - unsigned long size_dec = 0; - int blknum = 0; - off_t pos = 0; - off_t tar_len = 0; - ssize_t rdcnt = 0; - - if (!item || !tar){ - LOG("Invalid params\n"); - return -1; - } - LOG("Tar folder Looking for (%s)\n", item); - fd = open(tar, O_RDONLY); - if (fd < 0) { - LOG("can't open file(%s).\n", tar); + if (tar_reset_to_subject(tar_data->tar ,tar_data->subject_name, &(tar_data->subject_offset)) < 0) { + LOGE("tar_reset_to_subject() error!\n"); return -1; } - tar_len = lseek(fd, 0, SEEK_END); - if (tar_len < 0) { - LOGL(LOG_SSENGINE, "can't read tar_len (%s).\n", tar); - goto Cleanup; - } - pos = lseek(fd, 0, SEEK_SET); - if (pos < 0) { - LOGL(LOG_SSENGINE, "can't read pos (%s).\n", tar); - goto Cleanup; - } + off_t last_seek = 0; + int ret; - while (pos < tar_len) { - /* read file header */ - rdcnt = read(fd, header, sizeof(header)); - if (rdcnt <= 0) { - LOG("read failed. (rdcnt=%d)\n", rdcnt); - ret = -1; + for(;;) + { + switch(th_read(tar_data->tar)) + { + case -1: + LOGE("th_read() fail!\n"); + return -1; + case 1: + LOGL(LOG_SSENGINE, "EOF reached -> end of tar configuration\n"); + return 0; + case 0: break; } - /* get file name and file size */ - memcpy(name, header, sizeof(name) - 1); - memcpy(size_oct, header + TAR_ITEM_SIZE_POSITION, sizeof(size_oct)); - errno = 0; - size_dec = strtoul(size_oct, NULL, TAR_SIZE_OF_ITEM_SIZE); - if (errno != 0) { - LOG("strtoul failed. (errno=%d)\n", errno); - ret = -1; - break; - } else if (size_dec > MAX_ITEM_SIZE) { - LOG("size too big. (size_dec=0x%08X)\n", (unsigned int)size_dec); - ret = -1; - break; + char *curr_pathname = th_get_pathname(tar_data->tar); + char *pos = strchr(curr_pathname, '/'); + if ((!pos) || (strncmp(tar_data->subject_name, curr_pathname, (pos - curr_pathname) + 1) != 0)) { + return 0; } + tar_data->uncompressed_folder_size += th_get_size(tar_data->tar); - /* check if the file is what we are looking for */ - //Get until folder name - - lastfolder = strrchr(name, '/'); - if (lastfolder) - folderpathlen = strlen(name) - strlen(lastfolder); - - if (strncmp(name, item, folderpathlen) == 0) { - ret += (int)size_dec; - //LOG("Tar Files under folder [%s]\n", name); - //break; + if ((ret = tar_verify_and_extract_text(tar_data, curr_pathname, last_seek)) < 0) { + LOGE("Delta config error!\n"); + return -1; } - /* move file pointer to next file header */ - blknum = size_dec / TAR_BLOCK_SIZE; - if (size_dec % TAR_BLOCK_SIZE) - blknum++; + if ((ret == 0) && TH_ISREG(tar_data->tar) && (tar_skip_regfile(tar_data->tar) < 0)) { + LOGE("tar_skip_regfile() error!\n"); + return -1; + } - pos = lseek(fd, (off_t) (blknum * TAR_BLOCK_SIZE), SEEK_CUR); - if (pos < 0) { - LOGL(LOG_SSENGINE, "can't read next block (%s).\n", tar); - close(fd); + if ((last_seek = tar_seek(tar_data->tar, 0, SEEK_CUR)) < 0) { + LOGE("seeking error!\n"); return -1; } } - - Cleanup: - close(fd); - LOG("ret=%d\n", ret); - - return ret; //Should return +1?? or Ignore?? + return 0; } -int fast_tar_extract_file(char *tar, char *item, char *pathname, int size, int offset) +int tar_extract_7z_file(tar_info *tar_data) { - int fd = -1; - int data_size = size; - int data_offset = offset; - off_t pos = 0; - ssize_t rdcnt = 0; - ssize_t writeCount = 0; - char *buf = NULL; - char err_buf[256]; - int fd2; - - if (!item || !tar || !pathname){ - LOG("Invalid params\n"); + if (tar_seek(tar_data->tar, tar_data->new_files_info.offset, SEEK_SET) < 0) { + LOGE("seeking error!\n"); return -1; } - if (gTarFd >= 0) - fd = gTarFd; - else { - fd = open(tar, O_RDONLY); - if (fd < 0) { - LOG("can't open file(%s).\n", tar); - return -1; - } - } - pos = lseek(fd, data_offset, SEEK_SET); - if (pos < 0) { - LOG("lseek fail (%s offset %d).\n", tar, data_offset); - close(fd); - return -1; - } - buf = SS_Malloc(data_size + 1); - if (buf == NULL) { - close(fd); - LOGE("Failed to Allocate Memory\n"); + if (th_read(tar_data->tar) != 0) { + LOGE("unexpected return value from th_read()!\n"); return -1; } - rdcnt = read(fd, buf, data_size); - if (rdcnt != (ssize_t) data_size) { - LOG(" rdcnt read fail(%s from %s).\n", item, tar); - SS_Free(buf); - close(fd); + + LOGL(LOG_SSENGINE, "extracting %s\n", th_get_pathname(tar_data->tar)); + + if (tar_extract_file(tar_data->tar, tar_data->new_files_info.extracted_name) < 0) { + LOGE("tar extraction error!\n"); return -1; } - fd2 = open(pathname, O_CREAT | O_WRONLY, S_IRWXU); // Directory where file is required should be created already. - if (fd2 < 0) { - LOG("can't open file(%s).\n", pathname); - SS_Free(buf); - close(fd); + + return 0; +} + +int tar_init_diff_iterations(tar_info *tar_data, diff_iterator *diff_iter, fs_params *head) +{ + if (tar_reset_to_subject(tar_data->tar, tar_data->subject_name, &(tar_data->subject_offset)) < 0) { + LOGE("tar_reset_to_subject() fail!\n"); return -1; } - writeCount = write(fd2, buf, rdcnt); - if (writeCount != rdcnt) { - LOG("writeCount write fail(%s from %s).\n", item, tar); - strerror_r(errno, err_buf, sizeof(err_buf)); - LOG("Oh dear, something went wrong with read()! %s\n", err_buf); - close(fd); - close(fd2); - SS_Free(buf); - return -1; + diff_iter->head = head; + diff_iter->sum = 0; + int patch_count = 0; + fs_params *tmp = head; + while(tmp) + { + patch_count++; + tmp = tmp->nextnode; } - SS_Free(buf); - if (gTarFd < 0) - close(fd); - fsync(fd2); - close(fd2); - return rdcnt; // or jus return success? + diff_iter->sum_max = patch_count; + + return 0; } -int tar_extract_file(char *tar, char *item, char *pathname) +static int tar_check_diff_sum(diff_iterator *diff_iter) { - int fd = -1; - int data_size = -1; - int data_offset = -1; - off_t pos = 0; - ssize_t rdcnt = 0; - ssize_t writeCount = 0; - char *buf = NULL; - char err_buf[256]; - int fd2; - - if (!item || !tar || !pathname){ - LOG("Invalid params\n"); - return -1; - } - data_size = tar_get_item_size(tar, item); - data_offset = tar_get_item_offset(tar, item); + return (diff_iter->sum == diff_iter->sum_max) ? 1 : -1; +} - if (data_size <= 0 || data_offset < 0) { - LOGE("Error Not a file , size is [%d], offset [%d] for item [%s]\n", data_size, data_offset, item); - return -1; - } else - LOGL(LOG_SSENGINE, "extracting file [%s] size [%d]\n", item, data_size); - fd = open(tar, O_RDONLY); - if (fd < 0) { - LOG("can't open file(%s).\n", tar); - return -1; - } - pos = lseek(fd, data_offset, SEEK_SET); - if (pos < 0) { - LOG("lseek fail (%s offset %d).\n", tar, data_offset); - close(fd); - return -1; - } - buf = SS_Malloc(data_size + 1); - if (buf == NULL) { - close(fd); - LOGE("Failed to Allocate Memory\n"); - return -1; - } - rdcnt = read(fd, buf, data_size); - if (rdcnt != (ssize_t) data_size) { - LOG(" rdcnt read fail(%s from %s).\n", item, tar); - SS_Free(buf); - close(fd); - return -1; - } - fd2 = open(pathname, O_CREAT | O_WRONLY, S_IRWXU); // Directory where file is required should be created already. - if (fd2 < 0) { - LOG("can't open file(%s).\n", pathname); - SS_Free(buf); - close(fd); - return -1; - } - writeCount = write(fd2, buf, rdcnt); - if (writeCount != rdcnt) { - LOG("writeCount write fail(%s from %s).\n", item, tar); - strerror_r(errno, err_buf, sizeof(err_buf)); - LOG("Oh dear, something went wrong with read()! %s\n", err_buf); - close(fd); - close(fd2); - SS_Free(buf); - return -1; +static fs_params* tar_check_diff_iter_list(diff_iterator *diff_iter, char *pathname) +{ + fs_params *tmp = diff_iter->head; + while (tmp) { + if ((strcmp(tmp->patch_name, VISITED_STRING) !=0) && (strcmp(tmp->patch_name, pathname) == 0)) { + (diff_iter->sum)++; + // to signify that it has been visited + strcpy(tmp->patch_name, VISITED_STRING); + return tmp; + } + tmp = tmp->nextnode; } - SS_Free(buf); - close(fd); - fsync(fd2); - close(fd2); - return rdcnt; // or jus return success? + return tmp; } + +int tar_diff_iter_next_extract(tar_info *tar_data, diff_iterator *diff_iter, char *target, fs_params **params) +{ + for (;;) + { + switch(th_read(tar_data->tar)) + { + case -1: + LOGE("th_read() fail!\n"); + return -1; + case 1: + LOGL(LOG_SSENGINE, "EOF reached -> end of tar configuration\n"); + return tar_check_diff_sum(diff_iter); + case 0: + break; + } + + char *curr_pathname = th_get_pathname(tar_data->tar); + char *pos = strchr(curr_pathname, '/'); + if (!pos) { + return tar_check_diff_sum(diff_iter); + } + if (strncmp(tar_data->subject_name, curr_pathname, (pos - curr_pathname) + 1) != 0) + { + return tar_check_diff_sum(diff_iter); + } + if (strstr(curr_pathname, DIFF_PREFIX)) { + fs_params *tmp; + if (!(tmp = tar_check_diff_iter_list(diff_iter, pos + 1))) { + LOGE("Config file differs form delta!"); + return -1; + } + *params = tmp; + (*params)->data_size = th_get_size(tar_data->tar); + if (tar_extract_file(tar_data->tar, target) < 0) { + LOGE("File extraction error!\n"); + return -1; + } + return 0; + } + if (TH_ISREG(tar_data->tar) && (tar_skip_regfile(tar_data->tar) < 0)) { + LOGE("tar_skip_regfile() error!\n"); + return -1; + } + } +} \ No newline at end of file diff --git a/src/upgrade-apply-deltafs/engine/fota_tar.h b/src/upgrade-apply-deltafs/engine/fota_tar.h index a774836..debbfe9 100755 --- a/src/upgrade-apply-deltafs/engine/fota_tar.h +++ b/src/upgrade-apply-deltafs/engine/fota_tar.h @@ -1,7 +1,7 @@ /* * upgrade-apply-deltafs * - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 - 2022 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. @@ -19,12 +19,23 @@ #ifndef _FOTA_TAR_H_ #define _FOTA_TAR_H_ -int tar_get_item_offset(char *tar, char *item); +#include +#include +#include "ua_types.h" +#include "SS_UPI.h" +typedef struct _diff_iterator { + int sum; + fs_params *head; + char *subject_name; + int sum_max; +} diff_iterator; -int tar_get_item_size(char *tar, char *item); +int tar_get_tartype(char *tar_path, tartype_t **type); +int tar_init_with_type(TAR **tar, char *tar_path, tartype_t *type); +int tar_get_cfg_data(tar_info *tar_data); +int tar_extract_7z_file(tar_info *tar_data); +int tar_init_diff_iterations(tar_info *tar_data, diff_iterator *diff_iter, fs_params *head); +int tar_diff_iter_next_extract(tar_info *tar_data, diff_iterator *diff_iter, char *target, fs_params **params); -int tar_get_cfg_data(char *tar, char *item, char *buf, int buflen); - -int tar_get_folder_size(char *tar, char *item); #endif /* _FOTA_TAR_H_ */ diff --git a/src/upgrade-apply-deltafs/engine/ua_types.h b/src/upgrade-apply-deltafs/engine/ua_types.h index 9d00a9d..14d8773 100755 --- a/src/upgrade-apply-deltafs/engine/ua_types.h +++ b/src/upgrade-apply-deltafs/engine/ua_types.h @@ -20,8 +20,21 @@ #define __UA_TYPES_H__ #include +#include #define MAX_FILE_PATH 512 +// every delta should have a patchlist text file, and can have +// an attribute file additionally +#define NO_OF_TEXT_FILES 2 + +// the following macros define the meaning of indexes in tar_info.text_files_info array + +// this file has a list of diff files and the number of all operations (DIFFS, NEWS, MOVES etc.) +// this file is required to be present in a delta +#define PATCHLIST_FILE 0 + +// this files lists files whose attributes changed and their new values +#define ATTR_FILE 1 /* * FOTA Adaptaion header @@ -70,11 +83,34 @@ typedef struct _ua_delta_info_t { char ua_attrib_path[MAX_FILE_PATH]; } ua_delta_info_t; +typedef struct _file_text_info { + int size; + char item_name[MAX_FILE_PATH]; + char extracted_name[MAX_FILE_PATH]; +} text_file_info; + +typedef struct _file_7z_info { + off_t offset; + char item_name[MAX_FILE_PATH]; + char extracted_name[MAX_FILE_PATH]; +} file_7z_info; + +typedef struct _tar_info { + TAR *tar; + char *subject_name; + int uncompressed_folder_size; + off_t subject_offset; + file_7z_info new_files_info; + // id = 0 -> config file, id = 1 -> attribute file + text_file_info text_files_info[NO_OF_TEXT_FILES]; +} tar_info; + typedef struct _ua_dataSS_t { // partition operations ua_part_info_t *parti_info; ua_update_cfg_t *update_cfg; ua_update_data_t *update_data; ua_delta_info_t *update_delta; + tar_info *tar_data; unsigned long ua_operation; void (*ui_progress)(void *, unsigned long); int (*write_data_to_blkdev)(char *, int, int, char *); diff --git a/src/upgrade-apply-deltafs/ua.c b/src/upgrade-apply-deltafs/ua.c index 6f49a43..c140923 100755 --- a/src/upgrade-apply-deltafs/ua.c +++ b/src/upgrade-apply-deltafs/ua.c @@ -53,7 +53,6 @@ int dm_verity_status = DM_VERITY_DISABLED; // TODO: Consider changing all to PATH_MAX static char fota_result[MAX_FILE_PATH]; static char fota_cause[MAX_FILE_PATH]; -static char fota_status_path[MAX_FILE_PATH]; static char delta_folder[MAX_FOLDER_PATH]; static char delta_path[MAX_FILE_PATH]; static char log_folder[MAX_FOLDER_PATH]; @@ -68,6 +67,12 @@ static ua_update_cfg_t s_update_cfg; static ua_update_data_t s_update_data; +static tar_info s_tar_data; + +static text_file_info s_text_files_info[NO_OF_TEXT_FILES]; + +static file_7z_info s_new_files_info; + typedef struct temp_opt{ char * archive; char * archive_file; @@ -94,8 +99,8 @@ void print_usage(const char *msg) if (msg) { printf("%s\n", msg); } - printf("print_usage: upgrade-apply-deltafs --archive delta_dir --dest directory --archive-file label.img\n" - "delta_dir: directory path where delta.tar file is located\n" + printf("print_usage: upgrade-apply-deltafs --archive delta_path --dest directory --archive-file label.img\n" + "delta_path: filepath of delta (allowed file extensions: .tar, .tar.gz, .tgz)\n" "directory: directory where partition to be upgraded is mounted\n" "label.img: name of the directory inside of delta that is to be used during upgrade\n" ); @@ -262,11 +267,13 @@ int verify_Delta_FS() ua_update_cfg_t *ua_update_cfg = &s_update_cfg; ua_update_data_t *ua_update_data = &s_update_data; ua_delta_info_t *ua_delta_info = &s_delta_info; + tar_info *ua_tar_data = &s_tar_data; ua_dataSS.parti_info = ua_part_info; ua_dataSS.update_cfg = ua_update_cfg; ua_dataSS.update_data = ua_update_data; ua_dataSS.update_delta = ua_delta_info; ua_dataSS.ua_operation = UI_OP_SCOUT; + ua_dataSS.tar_data = ua_tar_data; ua_dataSS.ui_progress = fota_gui_progress; if (ua_update_data->ua_delta_path != NULL) { @@ -288,11 +295,13 @@ int update_Delta_FS(unsigned long ui32Operation) ua_update_cfg_t *ua_update_cfg = &s_update_cfg; ua_update_data_t *ua_update_data = &s_update_data; ua_delta_info_t *ua_delta_info = &s_delta_info; + tar_info *ua_tar_data = &s_tar_data; ua_dataSS.parti_info = ua_part_info; ua_dataSS.update_cfg = ua_update_cfg; ua_dataSS.update_data = ua_update_data; ua_dataSS.update_delta = ua_delta_info; ua_dataSS.ua_operation = ui32Operation; + ua_dataSS.tar_data = ua_tar_data; ua_dataSS.ui_progress = fota_gui_progress; if (ua_update_data->ua_delta_path != NULL) @@ -340,13 +349,28 @@ static void get_time_stamp(void) snprintf(ts, sizeof(ts), "%06d.%03d", sec % 100000, msec); } +/*----------------------------------------------------------------------------- + remove_cfg_file_files + ----------------------------------------------------------------------------*/ +void remove_extracted_files(void) +{ + for (int i = 0; i < NO_OF_TEXT_FILES; i++) + { + if (s_tar_data.text_files_info[i].size > 0) { + if (unlink(s_tar_data.text_files_info[i].extracted_name) < 0) { + LOGE("unlink error!\n"); + } + } + } +} + /*----------------------------------------------------------------------------- update_all ----------------------------------------------------------------------------*/ int update_all() { int ret = OK; - int cause = 0, item_size = 0; + int cause = 0; unsigned long ui32Operation = UI_OP_SCOUT; char * org_dir = getcwd(NULL, 0); @@ -354,13 +378,18 @@ int update_all() cause = ret; goto CleanUp; } + if (tar_get_cfg_data(&s_tar_data) < 0) { + LOGE("Delta read error!\n"); + ret = UPI_DELTACOUNT_ERROR; + goto CleanUp; + } + if (s_tar_data.text_files_info[PATCHLIST_FILE].size <= 0) { + LOGE("Patchlist file not present in delta -> aborting!\n"); + ret = UPI_DELTACOUNT_ERROR; + goto CleanUp; + } - item_size = tar_get_item_size(s_update_data.ua_delta_path, s_part_info.ua_subject_name); - if (item_size > 0) - s_update_data.data_size = (unsigned int)item_size; - else - s_update_data.data_size = 0; - + s_update_data.data_size = s_tar_data.uncompressed_folder_size; LOGL(LOG_DEBUG, "s_update_data.data_size=%lu, ua_delta_path=%s, " "ua_subject_name=%s\n", (long unsigned int)s_update_data.data_size, @@ -373,6 +402,7 @@ int update_all() goto CleanUp; } + LOG(" set weight to draw progressive bar.....\n"); set_data_weight(s_update_data.data_size); set_data_weight_offset(); @@ -430,8 +460,9 @@ int update_all() CleanUp: if (ret != OK) save_cause(cause); - free(org_dir); + remove_extracted_files(); + free(org_dir); return ret; } @@ -581,47 +612,6 @@ void save_result(int result) return; } -/*----------------------------------------------------------------------------- - fota_path_init - ----------------------------------------------------------------------------*/ -int fota_path_init(void) -{ - if (strlen(delta_folder) > MAX_FILE_PATH - 15) { - LOG("FOTA path is too long\n"); - return FAIL; - } - - - s_update_data.ua_delta_path = malloc(MAX_FILE_PATH); - if (s_update_data.ua_delta_path == NULL) { - LOG("Memory allocation fail\n"); - return FAIL; - } - snprintf(s_update_data.ua_delta_path, MAX_FILE_PATH, "%s/%s", delta_folder, DEFAULT_DELTA_NAME); - snprintf(fota_cause, sizeof(fota_cause), "%s/%s", result_folder, "cause"); - - LOG("s_part_info[UA_%s].ua_delta_path=%s\n", - s_part_info.ua_parti_name, - s_update_data.ua_delta_path); - - return SUCCESS; -} - -/*----------------------------------------------------------------------------- - fota_path_deinit - ----------------------------------------------------------------------------*/ -void fota_path_deinit(void) -{ - if (s_update_data.ua_delta_path) { - free(s_update_data.ua_delta_path); - s_update_data.ua_delta_path = NULL; - } - if (s_update_data.ua_temp_path) { - free(s_update_data.ua_temp_path); - s_update_data.ua_temp_path = NULL; - } -} - /*----------------------------------------------------------------------------- check_dm_verity_status ----------------------------------------------------------------------------*/ @@ -647,39 +637,45 @@ int check_dm_verity_status(void) } /*----------------------------------------------------------------------------- - remove_temp_files + set_delta_folder ----------------------------------------------------------------------------*/ -void remove_temp_files(void) +int set_delta_folder(void) { - int ret = 0; - char *ua_temp_path; - struct stat sbuf; + char *pos = strrchr(delta_path, '/'); + if ((pos == NULL) || ((pos - delta_path + 1) == strlen(delta_path))) { + print_usage("Invalid delta path"); + return -1; + } + snprintf(delta_folder, (pos - delta_path) + 1, "%s", delta_path); + return 0; +} +/*----------------------------------------------------------------------------- + set_tar_info + ----------------------------------------------------------------------------*/ +void set_tar_info(TAR *tar) +{ + s_tar_data.subject_name = strdup(s_part_info.ua_subject_name); + s_tar_data.tar = tar; + s_tar_data.subject_offset = 0; + s_tar_data.uncompressed_folder_size = 0; + s_new_files_info.offset = 0; + snprintf(s_new_files_info.item_name, MAX_FILE_PATH, "%s%s", s_tar_data.subject_name, SS_NEW_COMPRESSED_FILE); + snprintf(s_new_files_info.extracted_name, MAX_FILE_PATH, "%s/%s", s_update_data.ua_delta_folder, SS_NEW_COMPRESSED_FILE); - ua_temp_path = s_update_data.ua_temp_path; - if (NULL == ua_temp_path) - return; + s_text_files_info[PATCHLIST_FILE].size = 0; + s_text_files_info[ATTR_FILE].size = 0; - ret = lstat(ua_temp_path, &sbuf); - if (ret < 0) { - ret = stat(ua_temp_path, &sbuf); - if (ret < 0) { - LOG("stat failed with return value: %d errno: %d\n", ret, errno); - return; - } - } + snprintf(s_text_files_info[PATCHLIST_FILE].item_name, MAX_FILE_PATH, "%s%s%s", s_tar_data.subject_name, s_part_info.ua_parti_name, SS_PATCHLISTFORMAT); + snprintf(s_text_files_info[PATCHLIST_FILE].extracted_name, MAX_FILE_PATH, "%s/%s%s", s_update_data.ua_delta_folder, s_part_info.ua_parti_name, SS_PATCHLISTFORMAT); - if (S_ISDIR(sbuf.st_mode)) { - ret = rmdir(ua_temp_path); - if (ret < 0) - LOG("rmdir(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno); - } else { - ret = unlink(ua_temp_path); - if (ret < 0) - LOG("unlink(%s) failed with return value: %d errno: %d\n", ua_temp_path, ret, errno); - } -} + snprintf(s_text_files_info[ATTR_FILE].item_name, MAX_FILE_PATH, "%s%s%s", s_tar_data.subject_name, s_part_info.ua_parti_name, SS_PATCH_ATTR_FORMAT); + snprintf(s_text_files_info[ATTR_FILE].extracted_name, MAX_FILE_PATH, "%s/%s%s", s_update_data.ua_delta_folder, s_part_info.ua_parti_name, SS_PATCH_ATTR_FORMAT); + s_tar_data.text_files_info[PATCHLIST_FILE] = s_text_files_info[PATCHLIST_FILE]; + s_tar_data.text_files_info[ATTR_FILE] = s_text_files_info[ATTR_FILE]; + s_tar_data.new_files_info = s_new_files_info; +} /*----------------------------------------------------------------------------- arg_parse ----------------------------------------------------------------------------*/ @@ -689,9 +685,9 @@ int arg_parse(int argc, char ** argv, temp_opt *my_opt) print_usage("Invalid parameter count"); return -1; } - const char * archive = NULL; - const char * archive_file = NULL; - const char * dest = NULL; + char * archive = NULL; + char * archive_file = NULL; + char * dest = NULL; const struct option long_options[] = { {"archive", required_argument, NULL, 0 }, {"dest", required_argument, NULL, 1 }, @@ -750,8 +746,10 @@ int main(int argc, char **argv) char *dot_pos; int len; temp_opt my_opt; + tartype_t *type; + TAR *tar; log_init(); - if(arg_parse(argc, argv, &my_opt) < 0) { + if (arg_parse(argc, argv, &my_opt) < 0) { ret = UPI_INVALID_PARAM_ERROR; goto Results; } @@ -760,10 +758,13 @@ int main(int argc, char **argv) SS_set_feature_support_capability(1); #endif - snprintf(delta_folder, sizeof(delta_folder)-1, "%s", my_opt.archive); - snprintf(delta_path, sizeof(delta_path)-1, "%s/%s", delta_folder, DEFAULT_DELTA_NAME); + snprintf(delta_path, sizeof(delta_folder)-1, "%s", my_opt.archive); + if (set_delta_folder() < 0) { + ret = UPI_INVALID_PARAM_ERROR; + goto Results; + } s_update_data.ua_delta_folder = strdup(delta_folder); - + s_update_data.ua_delta_path = strdup(delta_path); snprintf(mnt_point, sizeof(mnt_point)-1, "%s", my_opt.dest); snprintf(temp_folder, sizeof(temp_folder)-1, "%s", TEMP_FOLDER); snprintf(log_folder, sizeof(log_folder)-1, "%s", SYSTEM_LOG_DIR); @@ -783,15 +784,22 @@ int main(int argc, char **argv) s_part_info.ua_parti_name[len] = '\0'; s_part_info.ua_subject_name = my_opt.archive_file; - s_update_cfg.source_img_size = 0; // TODO lets see if 0 will work + s_update_cfg.source_img_size = 0; // TODO lets see if 0 works - /* load block device number at run-time */ + if (tar_get_tartype(s_update_data.ua_delta_path, &type) < 0) { + ret = UPI_CONFIG_ERROR; + goto Results; + } - ret = fota_path_init(); - if (ret == FAIL) { - ret = UPI_DELTA_PATH_LENGTH_ERROR; + if (tar_init_with_type(&tar, s_update_data.ua_delta_path, type) < 0) { + ret = UPI_CONFIG_ERROR; goto Results; } + + set_tar_info(tar); + + + LOG("<<<<<<<<<<< log_init >>>>>>>>>>>>\n"); /* UPI version check */ @@ -809,10 +817,8 @@ int main(int argc, char **argv) Results: LOG("Result=%d\n", ret); save_result(ret); - //remove_temp_files(); // TOTA if (ret != SUCCESS) print_error_code(ret); - switch (ret) { /* Before initialize fota path */ case UPI_INVALID_PARAM_ERROR: @@ -828,14 +834,16 @@ int main(int argc, char **argv) case UPI_DELTACOUNT_ERROR: case UPI_VERIFY_ERROR: case UPI_UPDATE_ERROR: - fota_path_deinit(); log_deinit(); + if(s_tar_data.tar) + tar_close(s_tar_data.tar); _exit_stdio(); return -1; case SUCCESS: - fota_path_deinit(); log_deinit(); /* Preserve log file for debugging */ + if(s_tar_data.tar) + tar_close(s_tar_data.tar); _exit_stdio(); return 0; default: diff --git a/src/upgrade-apply-deltafs/ua.h b/src/upgrade-apply-deltafs/ua.h index 635129e..4be40fd 100755 --- a/src/upgrade-apply-deltafs/ua.h +++ b/src/upgrade-apply-deltafs/ua.h @@ -64,8 +64,6 @@ #define UPI_DELTACOUNT_ERROR UPI_ERROR(EC) #define UPI_PARTINFO_ERROR UPI_ERROR(ED) -#define DEFAULT_DELTA_NAME "delta.tar" - enum { UA_OP_MODE_FG = 0, UA_OP_MODE_BG