diff options
Diffstat (limited to 'snag/src')
| -rw-r--r-- | snag/src/build_db.c | 132 | ||||
| -rw-r--r-- | snag/src/build_db.h | 3 | ||||
| -rw-r--r-- | snag/src/main.c | 4 | ||||
| -rw-r--r-- | snag/src/util.h | 2 |
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 |
