From fa4344e5dedff14af2bce55d29a272495dd6bbb5 Mon Sep 17 00:00:00 2001 From: Jack Jamison Date: Thu, 23 Jul 2026 12:23:40 -0400 Subject: cache downloads and cleaning --- snag/configure | 2 +- snag/scripts/run_pkg_build.sh | 16 +++++++++++++ snag/scripts/run_pkg_install.sh | 16 ------------- snag/src/build_db.c | 53 +++++++++++++++++++++++++++++++++++++++++ snag/src/build_db.h | 8 +++++++ snag/src/download_db.c | 37 ++++++++++++++++++++-------- snag/src/download_db.h | 6 ++++- snag/src/main.c | 11 ++++++--- snag/src/package.h | 28 +++++++++++----------- snag/src/package_db.c | 43 --------------------------------- snag/src/package_db.h | 1 - 11 files changed, 132 insertions(+), 89 deletions(-) create mode 100755 snag/scripts/run_pkg_build.sh delete mode 100755 snag/scripts/run_pkg_install.sh create mode 100644 snag/src/build_db.c create mode 100644 snag/src/build_db.h (limited to 'snag') diff --git a/snag/configure b/snag/configure index 9613843..a140a28 100755 --- a/snag/configure +++ b/snag/configure @@ -2,7 +2,7 @@ # temp for testing mkdir -p ./var/snag/{downloads,installs,builds} -ln -s ../../../packages/ ./var/snag/packages +[ ! -e ./var/snag/packages ] && ln -s ../../../packages/ ./var/snag/packages bin="snag" libs="libcurl libcrypto" diff --git a/snag/scripts/run_pkg_build.sh b/snag/scripts/run_pkg_build.sh new file mode 100755 index 0000000..d48d831 --- /dev/null +++ b/snag/scripts/run_pkg_build.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# reads a package description script and runs the configure, build, and install +# steps. intended only for use by snag program +if [ -z "$1" ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +# load the description script +. $1 + +# run all install steps for package +configure +build +install diff --git a/snag/scripts/run_pkg_install.sh b/snag/scripts/run_pkg_install.sh deleted file mode 100755 index d48d831..0000000 --- a/snag/scripts/run_pkg_install.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -# reads a package description script and runs the configure, build, and install -# steps. intended only for use by snag program -if [ -z "$1" ]; then - echo "Usage: $0 " >&2 - exit 1 -fi - -# load the description script -. $1 - -# run all install steps for package -configure -build -install diff --git a/snag/src/build_db.c b/snag/src/build_db.c new file mode 100644 index 0000000..f2f4e01 --- /dev/null +++ b/snag/src/build_db.c @@ -0,0 +1,53 @@ +#include "build_db.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +#define PKG_BUILD_CMD "./scripts/run_pkg_build.sh" + +void package_run_install(const package_info_t* info) { + + // PIPE and FORK to run install script + int pipefds[2] = {0}; + if (pipe(pipefds) < 0) die("failed to pipe: %s", strerror(errno)); + pid_t pid = fork(); + if (pid < 0) die("failed to fork: %s", strerror(errno)); + + if (pid == 0) { + // child proc + // connect my stdout and stderr to the pipe + close(pipefds[0]); + dup2(pipefds[1], STDOUT_FILENO); + dup2(pipefds[1], STDERR_FILENO); + close(pipefds[1]); + // exec into install script + char* argv[] = { PKG_BUILD_CMD, info->script_path, NULL }; + char* envp[] = { NULL }; + execve(PKG_BUILD_CMD, argv, envp); + // what are you still doing here? + die("CHILD - execve to %s failed: %s", PKG_BUILD_CMD, strerror(errno)); + } else { + // parent proc, close write end of pipe + close(pipefds[1]); + } + + // read from the pipe until EOF + char buf[4096]; + ssize_t bytes_read = 0; + while ((bytes_read = read(pipefds[0], buf, sizeof(buf))) > 0) { + // print build out, can log and stuff in future + printf("%.*s", (int)bytes_read, buf); + } + if (bytes_read < 0) die("failed to read from pipe: %s", strerror(errno)); + close(pipefds[0]); + + // reap the child to finish + int wstatus; + if (waitpid(pid, &wstatus, 0) < 0) die("waitpid failed: %s", strerror(errno)); + if (WEXITSTATUS(wstatus) != 0) die("the child failed to execute install script"); +} diff --git a/snag/src/build_db.h b/snag/src/build_db.h new file mode 100644 index 0000000..ed57c43 --- /dev/null +++ b/snag/src/build_db.h @@ -0,0 +1,8 @@ +#ifndef BUILD_DB_H +#define BUILD_DB_H + +#include "package.h" + +void package_run_install(const package_info_t* info); + +#endif diff --git a/snag/src/download_db.c b/snag/src/download_db.c index c1e2e1b..c355566 100644 --- a/snag/src/download_db.c +++ b/snag/src/download_db.c @@ -6,6 +6,7 @@ #include #include #include +#include #include // note: fixed location of download database for now @@ -29,10 +30,22 @@ static size_t download_write_callback(char* ptr, size_t size, size_t nmemb, void return written; } -bool download_package(package_info_t* pkg) { +bool package_get_download(package_info_t* pkg, package_download_t* download) { + memset(download, 0, sizeof(*download)); + // construct path of download + char* download_path = vastrcat(download_db_path, "/", pkg->attrs.id, "-", pkg->attrs.version, ".tar.gz"); + + // return download if it already exists in database + if (access(download_path, F_OK) == 0) { + download->download_path = download_path; + return true; + } else { + print("Downloading %s\n", pkg->attrs.source_url); + } + + // initialize curl if it isn't already if (curl == NULL) { - // initialize curl if it isn't already CURLcode result = curl_global_init(CURL_GLOBAL_ALL); if (result != CURLE_OK) die("failed to initialize curl: %s", curl_easy_strerror(result)); curl = curl_easy_init(); // note(jqj): for now we reuse one easy curl object @@ -43,8 +56,8 @@ bool download_package(package_info_t* pkg) { /* curl_global_cleanup(); */ } + // initialize libcrypto context if it isn't already if (mdctx == NULL) { - // initialize libcrypto context if it isn't already mdctx = EVP_MD_CTX_new(); md = EVP_sha256(); @@ -59,7 +72,6 @@ bool download_package(package_info_t* pkg) { // note(jqj): extension is fixed to tar gz until the switch out download // attrs for the swenu api download command which will specify // more information - char* download_path = vastrcat(download_db_path, "/", pkg->attrs.id, "-", pkg->attrs.version, ".tar.gz"); FILE* download_file = fopen(download_path, "wb"); if (download_file == NULL) die("failed open download file for writing (%s): %s", download_path, strerror(errno)); @@ -73,7 +85,7 @@ bool download_package(package_info_t* pkg) { if(result != CURLE_OK) { // todo(jqj): handle better, maybe try again print("failed to download package with curl: %s", curl_easy_strerror(result)); - return false; + goto fail; } // get sha256 hash @@ -88,20 +100,25 @@ bool download_package(package_info_t* pkg) { } hash_hex[SHA256_DIGEST_LENGTH * 2] = '\0'; + // todo(jqj): collapse codepath and delete download if it doesn't match checksum + // confirm that hash matches checksum if (pkg->attrs.source_checksum != NULL) { if (strcmp(pkg->attrs.source_checksum, hash_hex) == 0) { - print("checksum verified for %s: %s\n", pkg->attrs.id, hash_hex); + print("checksum verified for download: %s\n", hash_hex); + download->download_path = download_path; return true; } else { - print("FAIL: bad checksum for %s: %s\n", pkg->attrs.id, hash_hex); - return false; + print("FAIL: bad checksum for download: %s\n", hash_hex); + goto fail; } } else { // todo(jqj): not sure if we will allow packages without hashes yet print("WARNING: could not verify checksum for %s download because none was provided\n", pkg->attrs.id); - return true; + goto fail; } - return true; + fail: + free(download_path); + return false; } diff --git a/snag/src/download_db.h b/snag/src/download_db.h index fbf7b03..0f6e181 100644 --- a/snag/src/download_db.h +++ b/snag/src/download_db.h @@ -5,6 +5,10 @@ #include "package.h" -bool download_package(package_info_t* pkg); +typedef struct { + char* download_path; +} package_download_t; + +bool package_get_download(package_info_t* pkg, package_download_t* download); #endif diff --git a/snag/src/main.c b/snag/src/main.c index 0813032..921c31a 100644 --- a/snag/src/main.c +++ b/snag/src/main.c @@ -2,6 +2,7 @@ #include "util.h" #include "package_db.h" +#include "build_db.h" #include "download_db.h" int cmd_install(char* cmd_name, ArgParser* parser); @@ -43,10 +44,14 @@ int cmd_install(char* cmd_name, ArgParser* parser) { char* pkgid = ap_get_arg_at_index(parser, i); package_info_t info; if (load_package_info(pkgid, &info)) { - print("Downloading '%s'\n", info.attrs.source_url); - download_package(&info); print("Installing %s - %s\n", info.attrs.name, info.attrs.desc); - run_package_install(&info); + + // download or retrieve package download + package_download_t download; + package_get_download(&info, &download); + + // run the package install + package_run_install(&info); } } diff --git a/snag/src/package.h b/snag/src/package.h index b848ce6..bdbf0cb 100644 --- a/snag/src/package.h +++ b/snag/src/package.h @@ -1,21 +1,21 @@ #ifndef PACKAGE_H #define PACKAGE_H +// this struct is the "handle" of a package to be passed into other package +// functions typedef struct { - char* id; - char* name; - char* desc; - char* webpage; - char* license; - char* version; - char* source_url; - char* source_checksum; - char buffer[4069]; -} package_attrs_t; - -typedef struct { - char* script_path; - package_attrs_t attrs; + char* script_path; + struct { + char buffer[4069]; + char* id; + char* name; + char* desc; + char* webpage; + char* license; + char* version; + char* source_url; + char* source_checksum; + } attrs; } package_info_t; #endif diff --git a/snag/src/package_db.c b/snag/src/package_db.c index 04705e4..e0d7e8a 100644 --- a/snag/src/package_db.c +++ b/snag/src/package_db.c @@ -9,7 +9,6 @@ #include #define PKG_INFO_CMD "./scripts/get_pkg_attrs.sh" -#define PKG_INST_CMD "./scripts/run_pkg_install.sh" // note: fixed location of package database for now const char pkg_db[] = "./var/snag/packages"; @@ -117,45 +116,3 @@ bool load_package_info(char* pkgid, package_info_t* info) { return true; } - -void run_package_install(const package_info_t* info) { - - // PIPE and FORK to run install script - int pipefds[2] = {0}; - if (pipe(pipefds) < 0) die("failed to pipe: %s", strerror(errno)); - pid_t pid = fork(); - if (pid < 0) die("failed to fork: %s", strerror(errno)); - - if (pid == 0) { - // child proc - // connect my stdout and stderr to the pipe - close(pipefds[0]); - dup2(pipefds[1], STDOUT_FILENO); - dup2(pipefds[1], STDERR_FILENO); - close(pipefds[1]); - // exec into install script - char* argv[] = { PKG_INST_CMD, info->script_path, NULL }; - char* envp[] = { NULL }; - execve(PKG_INST_CMD, argv, envp); - // what are you still doing here? - die("CHILD - execve to %s failed: %s", PKG_INST_CMD, strerror(errno)); - } else { - // parent proc, close write end of pipe - close(pipefds[1]); - } - - // read from the pipe until EOF - char buf[4096]; - ssize_t bytes_read = 0; - while ((bytes_read = read(pipefds[0], buf, sizeof(buf))) > 0) { - // print build out, can log and stuff in future - printf("%.*s", (int)bytes_read, buf); - } - if (bytes_read < 0) die("failed to read from pipe: %s", strerror(errno)); - close(pipefds[0]); - - // reap the child to finish - int wstatus; - if (waitpid(pid, &wstatus, 0) < 0) die("waitpid failed: %s", strerror(errno)); - if (WEXITSTATUS(wstatus) != 0) die("the child failed to execute install script"); -} diff --git a/snag/src/package_db.h b/snag/src/package_db.h index 17ff58d..52dad2b 100644 --- a/snag/src/package_db.h +++ b/snag/src/package_db.h @@ -9,6 +9,5 @@ // excessive validation, so this should be fine when loading lots of package // data bool load_package_info(char* pkgid, package_info_t* info); -void run_package_install(const package_info_t* info); #endif -- cgit v1.2.3