diff options
| author | Jack Jamison <jackqjamison@gmail.com> | 2026-07-23 12:23:40 -0400 |
|---|---|---|
| committer | Jack Jamison <jackqjamison@gmail.com> | 2026-07-23 12:23:40 -0400 |
| commit | fa4344e5dedff14af2bce55d29a272495dd6bbb5 (patch) | |
| tree | b90719263489365885a704bb4eab155c40c11d71 | |
| parent | e207f7382cf23dcf88700dead255a41c817a0863 (diff) | |
cache downloads and cleaning
| -rwxr-xr-x | snag/configure | 2 | ||||
| -rwxr-xr-x | snag/scripts/run_pkg_build.sh (renamed from snag/scripts/run_pkg_install.sh) | 0 | ||||
| -rw-r--r-- | snag/src/build_db.c | 53 | ||||
| -rw-r--r-- | snag/src/build_db.h | 8 | ||||
| -rw-r--r-- | snag/src/download_db.c | 37 | ||||
| -rw-r--r-- | snag/src/download_db.h | 6 | ||||
| -rw-r--r-- | snag/src/main.c | 11 | ||||
| -rw-r--r-- | snag/src/package.h | 28 | ||||
| -rw-r--r-- | snag/src/package_db.c | 43 | ||||
| -rw-r--r-- | snag/src/package_db.h | 1 | ||||
| -rw-r--r-- | todo.txt | 1 |
11 files changed, 117 insertions, 73 deletions
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_install.sh b/snag/scripts/run_pkg_build.sh index d48d831..d48d831 100755 --- a/snag/scripts/run_pkg_install.sh +++ b/snag/scripts/run_pkg_build.sh 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <errno.h> + +#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 <openssl/evp.h> #include <openssl/sha.h> #include <string.h> +#include <unistd.h> #include <errno.h> // 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 <errno.h> #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 @@ -4,6 +4,7 @@ SNAG - [x] add output and error functions for regular program output, make emalloc also have file info, also gen sh to configure - [x] download packages to download db and verify hash - [ ] cache download and actually create build environment for packages in build script +- [ ] rename "download" db to source or archive db - [ ] snag api - [ ] proper download with snag api (supports git download) - [ ] proper installation |
