upgrade-apply-deltafs: Rewrite code responsible for reading archive files (deltas... 94/281294/6
authorAntoni Adaszkiewicz <a.adaszkiewi@samsung.com>
Thu, 8 Sep 2022 09:45:04 +0000 (11:45 +0200)
committerAntoni Adaszkiewicz <a.adaszkiewi@samsung.com>
Mon, 7 Nov 2022 10:02:48 +0000 (11:02 +0100)
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

src/upgrade-apply-deltafs/CMakeLists.txt
src/upgrade-apply-deltafs/engine/SS_PatchDelta.c
src/upgrade-apply-deltafs/engine/SS_PatchDelta.h
src/upgrade-apply-deltafs/engine/SS_UPI.c
src/upgrade-apply-deltafs/engine/SS_UPI.h
src/upgrade-apply-deltafs/engine/fota_common.h
src/upgrade-apply-deltafs/engine/fota_tar.c
src/upgrade-apply-deltafs/engine/fota_tar.h
src/upgrade-apply-deltafs/engine/ua_types.h
src/upgrade-apply-deltafs/ua.c
src/upgrade-apply-deltafs/ua.h

index a7e335e..b53d7f8 100644 (file)
@@ -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})
index 299f126..414e1a0 100755 (executable)
@@ -26,7 +26,7 @@
 #include <sys/types.h>
 #include <fcntl.h>
 #include <unistd.h>
-#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);
index 09e5b9d..ba43685 100755 (executable)
@@ -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
index 87cccc0..bfc3a6e 100755 (executable)
@@ -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");
index 5968ab9..0005a79 100755 (executable)
@@ -18,8 +18,8 @@
 
 #ifndef _SS_UPI_H_
 #define _SS_UPI_H_
-#include <stdbool.h>
 #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_
index cc3869f..c5310d2 100755 (executable)
@@ -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;
index ff7233a..2f8fef9 100755 (executable)
@@ -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.
 #include <string.h>
 #include <errno.h>
 #include <limits.h>
+#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
index a774836..debbfe9 100755 (executable)
@@ -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.
 #ifndef _FOTA_TAR_H_
 #define _FOTA_TAR_H_
 
-int tar_get_item_offset(char *tar, char *item);
+#include <zlib.h>
+#include <libtar.h>
+#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_ */
index 9d00a9d..14d8773 100755 (executable)
 #define __UA_TYPES_H__
 
 #include <stdio.h>
+#include <libtar.h>
 
 #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 *);
index 6f49a43..c140923 100755 (executable)
@@ -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)
@@ -341,12 +350,27 @@ static void get_time_stamp(void)
 }
 
 /*-----------------------------------------------------------------------------
+  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;
 }
 
@@ -582,47 +613,6 @@ void save_result(int result)
 }
 
 /*-----------------------------------------------------------------------------
-  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
  ----------------------------------------------------------------------------*/
 int check_dm_verity_status(void)
@@ -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:
index 635129e..4be40fd 100755 (executable)
@@ -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