From: Antoni Adaszkiewicz Date: Mon, 19 Dec 2022 12:18:33 +0000 (+0100) Subject: update-manager: Drop untaring deltas with system() function X-Git-Tag: accepted/tizen/unified/20230116.060914^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F52%2F285752%2F10;p=platform%2Fcore%2Fsystem%2Fupdate-control.git update-manager: Drop untaring deltas with system() function Untaring deltas with system() function can be very slow, especially for larger deltas. This can result in timouts while verifying delta-device compatability. Change-Id: I5ee01e9d8af6d88eb69aff0b8856ab396ea92f64 --- diff --git a/packaging/update-control.spec b/packaging/update-control.spec index 3030476..4abcc82 100644 --- a/packaging/update-control.spec +++ b/packaging/update-control.spec @@ -32,6 +32,7 @@ BuildRequires: pkgconfig(key-manager) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(storage) BuildRequires: pkgconfig(vconf) +BuildRequires: libtar-devel %description An Update Control library in Tizen C API diff --git a/update-manager/CMakeLists.txt b/update-manager/CMakeLists.txt index 00475c4..a76e12e 100644 --- a/update-manager/CMakeLists.txt +++ b/update-manager/CMakeLists.txt @@ -18,6 +18,7 @@ SET(PKG_MODULES pkgmgr-info storage vconf + zlib ) INCLUDE(FindPkgConfig) pkg_check_modules(${PKG_NAME} REQUIRED ${PKG_MODULES}) @@ -40,4 +41,5 @@ FILE(GLOB SOURCE_FILES ) ADD_EXECUTABLE(${PKG_NAME} ${SOURCE_FILES}) TARGET_LINK_LIBRARIES(${PKG_NAME} ${${PKG_NAME}_LDFLAGS} "-ldl") +TARGET_LINK_LIBRARIES(${PKG_NAME} libtar.a) INSTALL(TARGETS ${PKG_NAME} DESTINATION bin) diff --git a/update-manager/common/common-tar.c b/update-manager/common/common-tar.c new file mode 100644 index 0000000..c7de444 --- /dev/null +++ b/update-manager/common/common-tar.c @@ -0,0 +1,180 @@ +#include "common.h" + +#include +#include +#include +#include +#include + +// for the sake of simplicity this stays global +static gzFile gz_tar = NULL; + +int gzip_open(const char *pathname, int oflags, ...) +{ + if (gz_tar != NULL) { + errno = EALREADY; + return -1; + } + + // 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; + } + + gz_tar = gzopen(pathname, "r"); + if (gz_tar == NULL) { + _CLOGE("gzopen() failed with errno: %d\n", errno); + return -1; + } + + return 1; +} + +int gzip_close(__attribute__((unused)) int useless_fd) +{ + if (gz_tar == NULL) { + errno = EINVAL; + return -1; + } + + int ret = gzclose(gz_tar); + if (ret != Z_OK) + _CLOGE("gzclose() failed with errno: %d\n", errno); + + return ret; +} + +ssize_t gzip_read(__attribute__((unused)) int useless_fd, void *buf, size_t len) +{ + if (gz_tar == NULL) { + errno = EINVAL; + return -1; + } + + int ret = gzread(gz_tar, buf, len); + if (ret <= 0) { + if (gzeof(gz_tar)) + _CLOGE("gzread() failed - EOF reached\n"); + else + _CLOGE("gzread() failed with error: %s\n", gzerror(gz_tar, NULL)); + } + + return ret; +} + +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; +} + +static int str_ends_with(const char *str, const char *suffix) +{ + size_t str_length = strlen(str); + size_t suffix_length = strlen(suffix); + + return ((str_length > suffix_length) && (memcmp(str + str_length - suffix_length, suffix, suffix_length + 1) == 0)); +} + +static int tar_get_tartype(const char *tar_path, tartype_t **type) +{ + static tartype_t gzip_type = {gzip_open, gzip_close, gzip_read, gzip_write}; + + if (str_ends_with(tar_path, ".tar")) { + *type = NULL; + } + else if (str_ends_with(tar_path, ".tar.gz")) { + *type = &gzip_type; + } + else if (str_ends_with(tar_path, ".tgz")) { + *type = &gzip_type; + } + else { + _CLOGE("Unknown/unsupported file extension for delta - %s\n", tar_path); + return -1; + } + + return 0; +} + +static int tar_init_with_type(TAR **tar, const char *tar_path, tartype_t *type) +{ + if (tar_open(tar, tar_path, type, O_RDONLY, 0, 0) < 0) { + *tar = NULL; + _CLOGE("tar_open() fail!\n"); + return -1; + } + + return 0; +} + +int util_file_untar(const char *tar_path, const char *dest_path, const char *extract_file_name) +{ + TAR *tar; + tartype_t *type; + DIR *dir; + + if (tar_get_tartype(tar_path, &type)) { + _CLOGE("tar_get_tartype() error!\n"); + return -1; + } + + dir = opendir(dest_path); + if (dir == NULL) { + _CLOGE("Directory %s could not be opened, errno: %d\n", dest_path, errno); + return -1; + } + closedir(dir); + + if (tar_init_with_type(&tar, tar_path, type)) { + _CLOGE("tar_init_with_type() error!\n"); + return -1; + } + + int ret = 0; + char extracted_file_path[MAX_BUFFER_SIZE]; + snprintf(extracted_file_path, MAX_BUFFER_SIZE, "%s/%s", dest_path, extract_file_name); + + for (;;) + { + switch (th_read(tar)) + { + case -1: + _CLOGE("th_read() fail!\n"); + ret = -1; + goto cleanup; + case 1: + _CLOGE("EOF reached - incorrect delta!\n"); + ret = -1; + goto cleanup; + case 0: + break; + } + + char *current_pathname = th_get_pathname(tar); + + if (strcmp(current_pathname, extract_file_name) == 0) { + if (tar_extract_file(tar, extracted_file_path) < 0) { + _CLOGE("tar_extract_file() fail!\n"); + ret = -1; + goto cleanup; + } + _CLOGI("%s successfully extracted from %s\n", extract_file_name, tar_path); + goto cleanup; + } + + if (TH_ISREG(tar) && (tar_skip_regfile(tar) < 0)) { + _CLOGE("tar_skip_regfile() fail!\n"); + ret = -1; + goto cleanup; + } + } + +cleanup: + tar_close(tar); + gz_tar = NULL; + return ret; +} \ No newline at end of file diff --git a/update-manager/common/common-util.c b/update-manager/common/common-util.c index 43a0a3f..f584398 100644 --- a/update-manager/common/common-util.c +++ b/update-manager/common/common-util.c @@ -101,27 +101,6 @@ int util_file_write_line(const char *path, const char *msg) return status; } -int util_file_untar(const char *tar_path, const char *dest_path, const char *extract_file_name) -{ - int ret = 0, status = 0; - char *command = NULL; - - command = g_strjoin(" ", - "tar", "xvfp", tar_path, "-C", dest_path, extract_file_name, NULL); - - ret = system(command); - if (ret < 0) { - _CLOGE("Failed to execute untar command %s : %m", command); - status = -1; - } else if (ret > 0) { - _CLOGE("Failed to untar : %d", ret); - status = -1; - } - free(command); - - return status; -} - static int read_checksum_for(const char *checksum_path, const char *file_name, char *sha1_hex, size_t sha1_hex_len) { int result = -1;