aboutsummaryrefslogtreecommitdiff
path: root/snag/src
diff options
context:
space:
mode:
authorRiley Beckett <rbeckettvt@gmail.com>2026-10-15 17:23:35 -0400
committerRiley Beckett <rbeckettvt@gmail.com>2026-10-15 17:23:35 -0400
commit65cfd95021b585fa92b455e89f2e0a645e48bb45 (patch)
treee720ba963ff92d0a2e5a5a5b204949615e34cbbf /snag/src
parent5f755d9d6c4ce77c4c8eb3a61cc59e1a01be0cfa (diff)
some work on checking flist/installing files
Diffstat (limited to 'snag/src')
-rw-r--r--snag/src/build_db.c132
-rw-r--r--snag/src/build_db.h3
-rw-r--r--snag/src/main.c4
-rw-r--r--snag/src/util.h2
4 files changed, 132 insertions, 9 deletions
diff --git a/snag/src/build_db.c b/snag/src/build_db.c
index ff163ba..6b22bcc 100644
--- a/snag/src/build_db.c
+++ b/snag/src/build_db.c
@@ -17,7 +17,8 @@
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
-
+#include <dirent.h>
+#include <linux/limits.h>
#include "sandboxing.h"
@@ -27,6 +28,8 @@
extern char** environment;
+const char slash[] = "/";
+
bool set_child_sandbox(const package_build_t* build) {
struct landlock_ruleset_attr ruleset_attr = {
.handled_access_fs =
@@ -325,13 +328,128 @@ void build_run(const package_build_t* build) {
if (WEXITSTATUS(wstatus) != 0) die("the child failed to execute install script");
}
-int nftw_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
- const char* path = strstr(fpath, "fakeroot") + strlen("fakeroot");
- if (!path[0]) return 0;
- print("%s\n", path);
+int do_dir_traversal(char* path, const char* absolute_path, const char** flist) {
+ size_t path_len = strlen(path);
+ if (path_len >= PATH_MAX) {
+ return -1;
+ }
+ struct stat st;
+ if (lstat(path, &st) < 0) {
+ fprintf(stderr, "Failed to stat path '%s': %s", path, strerror(errno));
+ return -1;
+ }
+ bool copy_allowed = true;
+ bool exists = false;
+ struct stat absolute_st;
+ if (lstat(absolute_path, &absolute_st) < 0) {
+ if (errno != ENOENT) {
+ print("lstat %s failed: %s", absolute_path, strerror(errno));
+ return -1;
+ }
+ }
+ else {
+ //fprintf(stderr, "%s exists\n", absolute_path);
+ exists = true;
+ copy_allowed = false;
+ if (S_ISDIR(st.st_mode)) {
+ copy_allowed = true;
+ }
+ else if (flist != NULL) {
+ for (int i = 0; flist[i]; i++) {
+ if (!strcmp(flist[i], absolute_path)) {
+ copy_allowed = true;
+ break;
+ }
+ }
+ }
+ }
+ if (exists && !copy_allowed) {
+ print("Path %s exists and is not in flist: stopping\n", absolute_path);
+ return -1;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ if (exists && copy_allowed) {
+ print("Directory %s exists doing nothing\n", absolute_path);
+ }
+ else {
+ fprintf(stderr, "Creating directory %s -> %s\n", path, absolute_path);
+ }
+ DIR* d = opendir(path);
+ if (!d) return -1;
+ struct dirent* de = NULL;
+ while((de = readdir(d))) {
+ if (de->d_name[0] == '.'
+ && (!de->d_name[1]
+ || (de->d_name[1]=='.' && !de->d_name[2]))) continue;
+ if (path_len + strlen(de->d_name) >= PATH_MAX) return -1;
+ path[path_len] = '/';
+ if (absolute_path == slash) absolute_path = strstr(path, "fakeroot") + strlen("fakeroot");
+ strcpy(path + path_len + 1, de->d_name);
+ if (do_dir_traversal(path, absolute_path, flist)) {
+ closedir(d);
+ return -1;
+ }
+ }
+ closedir(d);
+ }
+ else if (S_ISLNK(st.st_mode)) {
+ if (exists && copy_allowed) {
+ fprintf(stderr, "Overwriting symlink %s\n", absolute_path);
+ }
+ else {
+ fprintf(stderr, "Creating symlink %s -> %s\n", path, absolute_path);
+ }
+ }
+ else {
+ if (exists && copy_allowed) {
+ fprintf(stderr, "Overwriting file %s\n", absolute_path);
+ }
+ else {
+ fprintf(stderr, "Copying file %s -> %s\n", path, absolute_path);
+ }
+ }
return 0;
}
-void list_fakeroot(const package_build_t* build) {
- nftw(build->fakeroot, nftw_callback, 100, FTW_PHYS);
+void list_fakeroot(const package_build_t* build, const char** flist) {
+ char path[PATH_MAX] = {0};
+ strcpy(path, build->fakeroot);
+ const char* absolute_path = slash;
+ do_dir_traversal(path, absolute_path, flist);
+}
+
+void read_flist(const package_info_t* info, const char*** flist) {
+ char* flist_file = vastrcat(cfg.install_db, "/", info->attrs.id, "/flist");
+ if (!flist_file) {
+ die("flist path allocation failed: %s", strerror(errno));
+ }
+ FILE* f = fopen(flist_file, "r");
+ if (!f) {
+ print("There is no flist file for: %s\n", info->attrs.id);
+ free(flist_file);
+ *flist = NULL;
+ return;
+ }
+ fseek(f, 0, SEEK_END);
+ long file_size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ char* flist_buffer = emalloc(file_size + 1, "flist buffer");
+ if (fread(flist_buffer, 1, file_size, f) < file_size) {
+ die("Failed to read entire flist");
+ }
+ flist_buffer[file_size] = 0;
+ size_t lines = 0;
+ for (int i = 0; i < file_size; i++) {
+ if (flist_buffer[i] == '\n') lines++;
+ }
+ if (flist_buffer[file_size - 1] != '\n') lines++;
+ const char** flist_array = emalloc((lines + 1) * sizeof(char*), "flist array");
+ flist_array[0] = strtok(flist_buffer, "\n");
+ for (int i = 1; i < lines; i++) {
+ flist_array[i] = strtok(NULL, "\n");
+ }
+ flist_array[lines] = NULL;
+ *flist = flist_array;
+ fclose(f);
+ free(flist_file);
}
diff --git a/snag/src/build_db.h b/snag/src/build_db.h
index 4b735a7..413295f 100644
--- a/snag/src/build_db.h
+++ b/snag/src/build_db.h
@@ -12,6 +12,7 @@ typedef struct {
bool package_setup_build(const package_info_t* info, package_build_t* build);
void build_run(const package_build_t* info);
-void list_fakeroot(const package_build_t* info);
+void list_fakeroot(const package_build_t* info, const char** flist);
+void read_flist(const package_info_t* info, const char*** flist);
#endif
diff --git a/snag/src/main.c b/snag/src/main.c
index 5893ed7..37feb58 100644
--- a/snag/src/main.c
+++ b/snag/src/main.c
@@ -62,7 +62,9 @@ int cmd_install(char* cmd_name, ArgParser* parser) {
package_build_t build;
package_setup_build(&info, &build);
build_run(&build);
- list_fakeroot(&build);
+ const char** flist = NULL;
+ read_flist(&info, &flist);
+ list_fakeroot(&build, flist);
}
}
diff --git a/snag/src/util.h b/snag/src/util.h
index 0c684a4..299bd22 100644
--- a/snag/src/util.h
+++ b/snag/src/util.h
@@ -34,4 +34,6 @@ char* vastrcat_(int dummy, ...);
#define join_path(...) join_path_(0, __VA_ARGS__, NULL)
char* join_path_(int dummy, ...);
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+
#endif