From bd9950152509c232e27307a76959287b4d0a4f2b Mon Sep 17 00:00:00 2001 From: konect-V <66421869+konect-V@users.noreply.github.com> Date: Sat, 15 Jun 2024 14:27:52 +0200 Subject: [PATCH] Working store --- bootstrap/sys-libs.yml | 27 +++ sources/core/apps/store/source/deps/deps.c | 4 +- .../apps/store/source/download/download.c | 70 ++++--- .../core/apps/store/source/install/install.c | 3 + sources/core/apps/store/source/untar/untar.c | 174 ++++++++++++++++++ sources/core/apps/store/source/untar/untar.h | 8 + 6 files changed, 254 insertions(+), 32 deletions(-) create mode 100644 sources/core/apps/store/source/untar/untar.c create mode 100644 sources/core/apps/store/source/untar/untar.h diff --git a/bootstrap/sys-libs.yml b/bootstrap/sys-libs.yml index 5afa34de5..c634c8836 100644 --- a/bootstrap/sys-libs.yml +++ b/bootstrap/sys-libs.yml @@ -168,3 +168,30 @@ packages: build: - args: ['make', '-j@PARALLELISM@'] - args: ['make', 'DESTDIR=@THIS_COLLECT_DIR@', 'install'] + + - name: libarchive + source: + subdir: 'bundled' + git: 'https://github.com/libarchive/libarchive' + tag: 'v3.7.4' + version: '3.7.4' + tools_required: + - host-gcc + pkgs_required: + - mlibc + revision: 4 + configure: + - args: + - 'cmake' + - '@THIS_SOURCE_DIR@' + - '-DCMAKE_INSTALL_PREFIX=/usr' + - '-DBUILD_SHARED_LIBS=Off' + environ: + CC: "@OPTION:cc@" + CXX: "@OPTION:cxx@" + LD: "@OPTION:ld@" + ASMC: "@OPTION:asmc@" + + build: + - args: ['make', '-j@PARALLELISM@'] + - args: ['make', 'DESTDIR=@THIS_COLLECT_DIR@', 'install'] \ No newline at end of file diff --git a/sources/core/apps/store/source/deps/deps.c b/sources/core/apps/store/source/deps/deps.c index 013a2c77f..7c7d57439 100644 --- a/sources/core/apps/store/source/deps/deps.c +++ b/sources/core/apps/store/source/deps/deps.c @@ -8,8 +8,8 @@ #include "deps.h" static bool is_file_exists(char* path){ - struct stat sb; - return (stat(path, &sb) == 0); + struct stat sb; + return (stat(path, &sb) == 0); } int check_dependencies(char* app_info_json_path, char** installation_file_url){ diff --git a/sources/core/apps/store/source/download/download.c b/sources/core/apps/store/source/download/download.c index f41493f84..884a951b3 100644 --- a/sources/core/apps/store/source/download/download.c +++ b/sources/core/apps/store/source/download/download.c @@ -1,12 +1,18 @@ -#include #include -#include +#include #include +#include +#include +#include #include +static bool is_file_exists(char* path){ + struct stat sb; + return (stat(path, &sb) == 0); +} + static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp){ size_t real_size = size * nmemb; - printf("%d\n", real_size); fwrite(contents, size, nmemb, (FILE*)userp); return real_size; } @@ -28,35 +34,39 @@ static int progress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow int download_file(CURL* curl, char* url, char* path){ - printf("Initiating download of `%s` to `%s`\n", url, path); - int r = -1; - FILE* fp = fopen(path, "wb"); + if(!is_file_exists(path)){ + printf("Initiating download of `%s` to `%s`\n", url, path); + int r = -1; + FILE* fp = fopen(path, "wb"); - if(fp == NULL){ - printf("Failed to open file `%s` for writing. Error: %s\n", path, strerror(errno)); - }else{ - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); - curl_easy_setopt(curl, CURLOPT_CAINFO, "/usr/etc/ssl/cert.pem"); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); - - double time_begin = time(NULL); - curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &time_begin); - curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); - - printf("N/A\n"); - CURLcode res = curl_easy_perform(curl); - if(res == CURLE_OK){ - r = 0; - printf("Completed successfully.\n"); - } else { - printf("Failed. Error: %s\n", curl_easy_strerror(res)); + if(fp == NULL){ + printf("Failed to open file `%s` for writing. Error: %s\n", path, strerror(errno)); + }else{ + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + curl_easy_setopt(curl, CURLOPT_CAINFO, "/usr/etc/ssl/cert.pem"); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); + + double time_begin = time(NULL); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &time_begin); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); + + printf("N/A\n"); + CURLcode res = curl_easy_perform(curl); + if(res == CURLE_OK){ + r = 0; + printf("Completed successfully.\n"); + } else { + printf("Failed. Error: %s\n", curl_easy_strerror(res)); + } + + fclose(fp); } - fclose(fp); + return r; + }else{ + return 0; } - - return r; } \ No newline at end of file diff --git a/sources/core/apps/store/source/install/install.c b/sources/core/apps/store/source/install/install.c index db8275fe6..3e979ed6d 100644 --- a/sources/core/apps/store/source/install/install.c +++ b/sources/core/apps/store/source/install/install.c @@ -6,6 +6,7 @@ #include "install.h" #include "../deps/deps.h" +#include "../untar/untar.h" #include "../download/download.h" static bool is_dir_exist(char* path){ @@ -93,6 +94,8 @@ int install_app(CURL* curl, char* url, char* name){ free(path_store_app); return -1; } + + untar(path_store_installation_file, path_store_app); } } diff --git a/sources/core/apps/store/source/untar/untar.c b/sources/core/apps/store/source/untar/untar.c new file mode 100644 index 000000000..460210d8a --- /dev/null +++ b/sources/core/apps/store/source/untar/untar.c @@ -0,0 +1,174 @@ +/* + * Written by Tim Kientzle, March 2009. + * + * Released into the public domain. + */ + +#include + +static int parseoct(const char *p, size_t n){ + int i = 0; + + while (*p < '0' || *p > '7') { + ++p; + --n; + } + while (*p >= '0' && *p <= '7' && n > 0) { + i *= 8; + i += *p - '0'; + ++p; + --n; + } + return (i); +} + +/* Returns true if this is 512 zero bytes. */ +static int is_end_of_archive(const char *p){ + int n; + for (n = 511; n >= 0; --n) + if (p[n] != '\0') + return (0); + return (1); +} + +/* Create a directory, including parent directories as necessary. */ +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) + fprintf(stderr, "Could not create directory %s\n", pathname); +} + +/* Create a file, including parent directory as necessary. */ +static FILE* create_file(char *pathname, int mode){ + FILE *f; + f = fopen(pathname, "w+"); + if (f == NULL) { + /* Try creating parent dir and then creating file. */ + char *p = strrchr(pathname, '/'); + if (p != NULL) { + *p = '\0'; + create_dir(pathname, 0755); + *p = '/'; + f = fopen(pathname, "w+"); + } + } + return (f); +} + +/* Verify the tar checksum. */ +static int verify_checksum(const char *p){ + int n, u = 0; + for (n = 0; n < 512; ++n) { + if (n < 148 || n > 155) + /* Standard tar checksum adds unsigned bytes. */ + u += ((unsigned char *)p)[n]; + else + u += 0x20; + + } + return (u == parseoct(p + 148, 8)); +} + +/* Extract a tar archive. */ +int untar(const char* tar_path, const char* dst_path){ + char buffer[512]; + FILE* file_tmp = NULL; + FILE* tar_file = fopen(tar_path, "r");; + size_t bytes_read; + int file_size; + int dst_path_len = strlen(dst_path); + + printf("Extracting from %s\n", tar_path); + for (;;) { + bytes_read = fread(buffer, 1, 512, tar_file); + if (bytes_read < 512) { + fprintf(stderr, "Short read on %s: expected 512, got %d\n", tar_path, bytes_read); + return -1; + } + if (is_end_of_archive(buffer)) { + printf("End of %s\n", tar_path); + return -1; + } + if (!verify_checksum(buffer)) { + fprintf(stderr, "Checksum failure\n"); + return -1; + } + file_size = parseoct(buffer + 124, 12); + switch (buffer[156]) { + case '1': + printf(" Ignoring hardlink %s\n", buffer); + break; + case '2': + printf(" Ignoring symlink %s\n", buffer); + break; + case '3': + printf(" Ignoring character device %s\n", buffer); + break; + case '4': + printf(" Ignoring block device %s\n", buffer); + break; + case '5': + char* path_dir = malloc(dst_path_len + strlen(buffer) + 1); + strcpy(path_dir, dst_path); + strcat(path_dir, buffer); + printf(" Extracting dir %s to %s\n", buffer, path_dir); + create_dir(path_dir, parseoct(buffer + 100, 8)); + file_size = 0; + break; + case '6': + printf(" Ignoring FIFO %s\n", buffer); + break; + default: + char* path_file = malloc(dst_path_len + strlen(buffer) + 1); + strcpy(path_file, dst_path); + strcat(path_file, buffer); + printf(" Extracting file %s to %s\n", buffer, path_file); + file_tmp = create_file(path_file, parseoct(buffer + 100, 8)); + break; + } + while (file_size > 0) { + bytes_read = fread(buffer, 1, 512, tar_file); + if (bytes_read < 512) { + fprintf(stderr, "Short read on %s: Expected 512, got %d\n", dst_path, bytes_read); + return -1; + } + if (file_size < 512) + bytes_read = file_size; + if(file_tmp != NULL){ + if (fwrite(buffer, 1, bytes_read, file_tmp) != bytes_read){ + fprintf(stderr, "Failed write\n"); + fclose(file_tmp); + file_tmp = NULL; + } + } + file_size -= bytes_read; + } + if(file_tmp != NULL){ + fclose(file_tmp); + file_tmp = NULL; + } + } + + fclose(tar_file); + + return 0; +} \ No newline at end of file diff --git a/sources/core/apps/store/source/untar/untar.h b/sources/core/apps/store/source/untar/untar.h new file mode 100644 index 000000000..abbc4e1ad --- /dev/null +++ b/sources/core/apps/store/source/untar/untar.h @@ -0,0 +1,8 @@ +#ifndef UNTAR_H +#define UNTAR_H + +#include + +int untar(const char* tar_path, const char* dst_path); + +#endif // UNTAR_H \ No newline at end of file