aboutsummaryrefslogtreecommitdiff
path: root/snag/src
diff options
context:
space:
mode:
authorJack Jamison <jackqjamison@gmail.com>2026-07-23 12:23:40 -0400
committerJack Jamison <jackqjamison@gmail.com>2026-07-23 12:23:40 -0400
commitfa4344e5dedff14af2bce55d29a272495dd6bbb5 (patch)
treeb90719263489365885a704bb4eab155c40c11d71 /snag/src
parente207f7382cf23dcf88700dead255a41c817a0863 (diff)
cache downloads and cleaning
Diffstat (limited to 'snag/src')
-rw-r--r--snag/src/build_db.c53
-rw-r--r--snag/src/build_db.h8
-rw-r--r--snag/src/download_db.c37
-rw-r--r--snag/src/download_db.h6
-rw-r--r--snag/src/main.c11
-rw-r--r--snag/src/package.h28
-rw-r--r--snag/src/package_db.c43
-rw-r--r--snag/src/package_db.h1
8 files changed, 115 insertions, 72 deletions
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