diff options
Diffstat (limited to 'snag/src/build_db.c')
| -rw-r--r-- | snag/src/build_db.c | 132 |
1 files changed, 125 insertions, 7 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); } |
