From c43227493617e335451787792d3618368412bc18 Mon Sep 17 00:00:00 2001 From: Liam Waldron Date: Fri, 18 Sep 2026 11:20:59 -0400 Subject: [PATCH] Refuse base-repo installs under GL_SCOPE_USR at the library level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gl_install_pkg now returns GL_INSTALL_ERR_SCOPE for scope == GL_SCOPE_USR && repo == "base", checked immediately after manifest parse and before any store path construction or filesystem mutation. Per SECURITY_DESIGN.txt section 8: enforced in the library rather than a CLI, since the split-.so architecture lets third-party tools call gl_install_pkg directly. Also drops src/istoreutils.c.rej, .c.back, .h.back — stale leftovers from the uid -> gl_context_t migration patch; that migration is fully present in the current tree, so these were dead weight. Co-Authored-By: Claude Sonnet 5 --- src/istoreutils.c | 21 + src/istoreutils.c.back | 1365 ---------------------------------------- src/istoreutils.c.rej | 302 --------- src/istoreutils.h | 1 + src/istoreutils.h.back | 101 --- 5 files changed, 22 insertions(+), 1768 deletions(-) delete mode 100644 src/istoreutils.c.back delete mode 100644 src/istoreutils.c.rej delete mode 100644 src/istoreutils.h.back diff --git a/src/istoreutils.c b/src/istoreutils.c index 3cb2409..a545771 100644 --- a/src/istoreutils.c +++ b/src/istoreutils.c @@ -1188,6 +1188,27 @@ gl_install_pkg(gl_context_t *ctx, const char *gpkg_path) if (!manifest_found) { return GL_INSTALL_ERR_MANIFEST; } + + /* + * Base-repo packages can NEVER be installed under per-user scope. + * Enforced here, at the library level, rather than in any CLI: the + * split-.so architecture means a third-party tool can call + * gl_install_pkg directly without going through gpkg/syspkg, and a + * rule only one CLI respects is not a real guarantee. See + * SECURITY_DESIGN.txt section 8. + * + * This is the earliest possible point — pkg.pkg_repo only exists + * once the manifest is parsed — and deliberately sits before any + * store path construction or filesystem mutation below. + */ + if (ctx->scope == GL_SCOPE_USR && + strcmp(pkg.pkg_repo, GL_BASE_REPO) == 0) { + lg_printf(2, + "Refusing to install base-repo package '%s' under user scope.", + pkg.pkg_name); + gl_free_pkg(&pkg); + return GL_INSTALL_ERR_SCOPE; + } char pkg_store_base[PATH_MAX]; char pkg_store_final[PATH_MAX]; diff --git a/src/istoreutils.c.back b/src/istoreutils.c.back deleted file mode 100644 index 5d52e76..0000000 --- a/src/istoreutils.c.back +++ /dev/null @@ -1,1365 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "istoreutils.h" -#include "log.h" -#include "pkg.h" -#include "transaction.h" - -static const dir_t usr_index = { "/glacier/usr/index", 0700 }; -static const dir_t sys_index = { "/glacier/sys/index", 0700 }; - -static const dir_t usr_store = { "/glacier/usr/store", 0700 }; -static const dir_t sys_store = { "/glacier/sys/store", 0700 }; - -static const dir_t usr_links = { "/glacier/usr/links", 0700 }; -static const dir_t sys_links = { "/glacier/sys/links", 0700 }; - -bool -gl_usr_istore_exists(index_store_t index_or_store, int uid) -{ - char path[PATH_MAX]; - struct stat st; - - switch (index_or_store) { - case INDEX: - snprintf(path, sizeof(path), "%s/%d", usr_index.path, uid); - break; - case STORE: - snprintf(path, sizeof(path), "%s/%d", usr_store.path, uid); - break; - default: - printf("libglacier: argument index_or_store of function gl_usr_istore_exists must be INDEX or STORE\n"); - return false; - } - - if (stat(path, &st) != 0) { - return false; - } - - return S_ISDIR(st.st_mode); -} - -bool -gl_sys_istore_exists(index_store_t index_or_store) -{ - char path[PATH_MAX]; - struct stat st; - - switch (index_or_store) { - case INDEX: - snprintf(path, sizeof(path), "%s", sys_index.path); - break; - case STORE: - snprintf(path, sizeof(path), "%s", sys_store.path); - break; - default: - printf("libglacier: argument index_or_store of function gl_sys_istore_exists must be INDEX or STORE\n"); - return false; - } - - if (stat(path, &st) != 0) { - return false; - } - - return S_ISDIR(st.st_mode); -} - -static void -make_index_name(char *buffer, size_t buffersz) -{ - time_t now = time(NULL); - struct tm *tm = localtime(&now); - strftime(buffer, buffersz, "index-%m_%d_%Y@%H:%M", tm); -} - -static int -create_index(const char *ind_path, uid_t uid) -{ - char fname[64]; - make_index_name(fname, sizeof(fname)); - - char full_path[PATH_MAX]; - snprintf(full_path, sizeof(full_path), "%s/%s", ind_path, fname); - - FILE *f = fopen(full_path, "w"); - if (!f) { return -1; } - fprintf(f, "uid = %d\n", uid); - fprintf(f, "listed = 0\n\n"); - fclose(f); - - if (chown(full_path, uid, (gid_t)-1) != 0) { return -1; } - - char link_path[PATH_MAX]; - snprintf(link_path, sizeof(link_path), "%s/current", ind_path); - unlink(link_path); - - if (symlink(fname, link_path) != 0) { return -1; } - if (lchown(link_path, uid, (gid_t)-1) != 0) { return -1; } - - return 0; -} - -static bool -is_dir(const char *d) -{ - struct stat st; - return stat(d, &st) == 0 && S_ISDIR(st.st_mode); -} - - -int -gl_init_user(uid_t uid, bool isVerbose) -{ - if (isVerbose) { lg_printf(0, "Checking if UID is within acceptable bounds..."); } - if (uid < 1000) { - if (isVerbose) { - lg_printf(2, "Attempted to create index and store for UID < 1000. Quitting..."); - } - return 2; - } - - if (isVerbose) { lg_printf(0, "Constructing paths for index and store..."); } - - char ind_path[PATH_MAX]; - char sto_path[PATH_MAX]; - char lnk_path[PATH_MAX]; - - snprintf(ind_path, sizeof(ind_path), "%s/%d", usr_index.path, uid); - snprintf(sto_path, sizeof(sto_path), "%s/%d", usr_store.path, uid); - snprintf(lnk_path, sizeof(lnk_path), "%s/%d", usr_links.path, uid); - - if (isVerbose) { lg_printf(0, "Paths constructed:\n%s\n%s", ind_path, sto_path); } - - if (isVerbose) { lg_printf(0, "Attempting to create index directory at %s", ind_path); } - if (mkdir(ind_path, 0700) == -1) { - switch (errno) { - case EACCES: - lg_printf(2, "Cannot create index: permission denied"); - return 1; - break; - case EEXIST: - lg_printf(2, "Cannot create index: directory already exists"); - return 1; - break; - case ENOENT: - /* should never happen, but here for completeness */ - lg_printf(2, "Cannot create index: parent directory does not exist"); - return 1; - break; - case ENOSPC: - lg_printf(2, "Cannot create index: no space left on device"); - return 1; - break; - case EROFS: - lg_printf(2, "Cannot create index: read only filesystem"); - return 1; - break; - default: - printf("libglacier: mkdir error in function gl_init_user\n"); - return -1; - break; - } - } - - if (isVerbose) { lg_printf(0, "Attempting to create store directory at %s", sto_path); } - if (mkdir(sto_path, 0700) == -1) { - switch (errno) { - case EACCES: - lg_printf(2, "Cannot create store: permission denied"); - return 1; - break; - case EEXIST: - lg_printf(2, "Cannot create store: directory already exists"); - return 1; - break; - case ENOENT: - /* should never happen, but here for completeness */ - lg_printf(2, "Cannot create store: parent directory does not exist"); - return 1; - break; - case ENOSPC: - lg_printf(2, "Cannot create store: no space left on device"); - return 1; - break; - case EROFS: - lg_printf(2, "Cannot create store: read only filesystem"); - return 1; - break; - default: - printf("libglacier: mkdir error in function gl_init_user\n"); - return -1; - break; - } - } - - if (isVerbose) { lg_printf(0, "Attempting to create links directory at %s", lnk_path); } - if (mkdir(lnk_path, 0700) == -1) { - switch (errno) { - case EACCES: - lg_printf(2, "Cannot create store: permission denied"); - return 1; - break; - case EEXIST: - lg_printf(2, "Cannot create store: directory already exists"); - return 1; - break; - case ENOENT: - /* should never happen, but here for completeness */ - lg_printf(2, "Cannot create store: parent directory does not exist"); - return 1; - break; - case ENOSPC: - lg_printf(2, "Cannot create store: no space left on device"); - return 1; - break; - case EROFS: - lg_printf(2, "Cannot create store: read only filesystem"); - return 1; - break; - default: - printf("libglacier: mkdir error in function gl_init_user\n"); - return -1; - break; - } - } - - if (isVerbose) { lg_printf(0, "Changing ownership of index and store to UID %i", uid); } - - if (chown(sto_path, uid, (gid_t)-1) != 0) { - return 1; - } - - if (chown(ind_path, uid, (gid_t)-1) != 0) { - return 1; - } - - if (chown(lnk_path, uid, (gid_t)-1) != 0) { - return 1; - } - - if (create_index(ind_path, uid) != 0) { - /* No switch for errno. chown() shouldn't fail if mkdir() didn't */ - lg_printf(2, "Cannot create initial index file"); - return 1; - } - return 0; -} - -int -gl_init_sys(bool isVerbose) -{ - const char *paths[] = { - sys_index.path, - sys_store.path, - sys_links.path, - }; - mode_t modes[] = { - sys_index.mode, - sys_store.mode, - sys_links.mode, - }; - - for (int i = 0; i < 3; i++) { - if (isVerbose) { lg_printf(0, "Creating %s", paths[i]); } - - if (mkdir(paths[i], modes[i]) == -1) { - switch (errno) { - case EEXIST: - break; - case EACCES: - lg_printf(2, "Cannot create %s: permission denied", paths[i]); - return 1; - case ENOSPC: - lg_printf(2, "Cannot create %s: no space left on device", paths[i]); - return 1; - case EROFS: - lg_printf(2, "Cannot create %s: read-only filesystem", paths[i]); - return 1; - default: - lg_printf(2, "Cannot create %s: mkdir failed", paths[i]); - return -1; - } - } - } - - return 0; -} - -static void -trim(char *s) -{ - char *p = s; - while (*p && isspace((unsigned char)*p)) { - p++; - } - - if (p != s) { - memmove(s, p, strlen(p) + 1); - } - - size_t len = strlen(s); - while (len && isspace((unsigned char)s[len - 1])) { - s[--len] = 0; - } -} - -static char -*dupstr(const char *s) -{ - size_t n = strlen(s); - char *p = malloc(n + 1); - if (!p) { - return NULL; - } - - memcpy(p, s, n + 1); - return p; -} - -int -gl_parse_index(struct gindex *idx, FILE *f) -{ - idx->uid = -1; - idx->listed = -1; - idx->entries = NULL; - idx->count = 0; - - char line[512]; - - while (fgets(line, sizeof(line), f)) { - trim(line); - if (!line[0] || line[0] == '#') { continue; } - - char *eq = strchr(line, '='); - if (eq) { - *eq = 0; - char *key = line; - char *val = eq + 1; - trim(key); - trim(val); - - if (strcmp(key, "uid") == 0) { idx->uid = atoi(val); } - else if (strcmp(key, "listed") == 0) { idx->listed=atoi(val); } - continue; - } - - char *first = strstr(line, "::"); - if (!first) { continue; } - - *first = 0; - char *repo = line; - char *pkg = first + 2; - trim(repo); - trim(pkg); - - struct gpkg_entry ent; - ent.repo = dupstr(repo); - ent.pkg = dupstr(pkg); - if (!ent.repo || !ent.pkg) { return -1; } - - struct gpkg_entry *tmp = - realloc(idx->entries, sizeof(*idx->entries) * (idx->count + 1)); - if (!tmp) { return -1; } - idx->entries = tmp; - idx->entries[idx->count++] = ent; - } - - return 0; -} - -void -gl_free_index(struct gindex *idx) -{ - for (size_t i = 0; i < idx->count; i++) { - free(idx->entries[i].repo); - free(idx->entries[i].pkg); - } - - free(idx->entries); - idx->entries = NULL; - idx->count = 0; -} -/* -int -gl_rebuild_index(uid_t uid, const char *out_dir) -{ - char store_path[PATH_MAX]; - snprintf(store_path, sizeof(store_path), "%s/%d", usr_store.path, uid); - - DIR *store_dir = opendir(store_path); - if (!store_dir) return -1; - - FILE *out = fopen(out_dir, "w"); - if (!out) return -1; - - size_t listed = 0; - - struct dirent *repo_ent; - while ((repo_ent = readdir(store_dir))) { - if (repo_ent->d_name[0] == '.') { continue; } - - char repo_path[PATH_MAX]; - snprintf(repo_path, sizeof(repo_path), "%s/%s", - store_path, repo_ent->d_name); - - struct stat rst; - if (stat(repo_path, &rst) != 0 || !S_ISDIR(rst.st_mode)) { - continue; - } - - DIR *repo_dir = opendir(repo_path); - if (!repo_dir) continue; - - struct dirent *pkg_ent; - while ((pkg_ent = readdir(repo_dir))) { - if (pkg_ent->d_name[0] == '.') { continue; } - - char pkg_path[PATH_MAX]; - snprintf(pkg_path, sizeof(pkg_path), "%s/%s", - repo_path, pkg_ent->d_name); - - struct stat pst; - if (stat(pkg_path, &pst) != 0 || !S_ISDIR(pst.st_mode)) { - continue; - } - - fprintf(out, "%s::%s\n", - repo_ent->d_name, - pkg_ent->d_name); - listed++; - } - closedir(repo_dir); - } - - rewind(out); - fprintf(out, "uid = %d\n", uid); - - closedir(store_dir); - fclose(out); - return 0; -} -*/ - -int -gl_rebuild_index(gl_context_t *ctx) -{ - if (!ctx) { return -1; } - - DIR *store_dir = opendir(ctx->store_path); - if (!store_dir) return -1; - - /* Write to a new timestamped index file */ - char fname[64]; - make_index_name(fname, sizeof(fname)); - - char new_index_path[PATH_MAX]; - snprintf(new_index_path, sizeof(new_index_path), "%s/%s", - ctx->index_path, fname); - - FILE *out = fopen(new_index_path, "w"); - if (!out) { - closedir(store_dir); - return -1; - } - - size_t listed = 0; - - struct dirent *repo_ent; - while ((repo_ent = readdir(store_dir))) { - if (repo_ent->d_name[0] == '.') { continue; } - - char repo_path[PATH_MAX]; - snprintf(repo_path, sizeof(repo_path), "%s/%s", - ctx->store_path, repo_ent->d_name); - - struct stat rst; - if (stat(repo_path, &rst) != 0 || !S_ISDIR(rst.st_mode)) { - continue; - } - - DIR *repo_dir = opendir(repo_path); - if (!repo_dir) continue; - - struct dirent *pkg_ent; - while ((pkg_ent = readdir(repo_dir))) { - if (pkg_ent->d_name[0] == '.') { continue; } - - char pkg_path[PATH_MAX]; - snprintf(pkg_path, sizeof(pkg_path), "%s/%s", - repo_path, pkg_ent->d_name); - - struct stat pst; - if (stat(pkg_path, &pst) != 0 || !S_ISDIR(pst.st_mode)) { - continue; - } - - fprintf(out, "%s::%s\n", - repo_ent->d_name, - pkg_ent->d_name); - listed++; - } - closedir(repo_dir); - } - closedir(store_dir); - fclose(out); - - /* Prepend header by copying through a temp file then renaming over */ - FILE *tmp_in = fopen(new_index_path, "r"); - if (!tmp_in) return -1; - - char tmp_path[PATH_MAX]; - snprintf(tmp_path, sizeof(tmp_path), "%s/.index_tmp_XXXXXX", - ctx->index_path); - int tmp_fd = mkstemp(tmp_path); - if (tmp_fd < 0) { fclose(tmp_in); return -1; } - - FILE *tmp_out = fdopen(tmp_fd, "w"); - if (!tmp_out) { close(tmp_fd); fclose(tmp_in); return -1; } - - fprintf(tmp_out, "uid = %d\n", ctx->uid); - fprintf(tmp_out, "listed = %zu\n\n", listed); - - char line[512]; - while (fgets(line, sizeof(line), tmp_in)) { - fputs(line, tmp_out); - } - fclose(tmp_in); - fclose(tmp_out); - - rename(tmp_path, new_index_path); - chown(new_index_path, ctx->uid, (gid_t)-1); - - /* Update the "current" symlink to point at the new index */ - char link_path[PATH_MAX]; - snprintf(link_path, sizeof(link_path), "%s/current", ctx->index_path); - unlink(link_path); - - if (symlink(fname, link_path) != 0) { return -1; } - lchown(link_path, ctx->uid, (gid_t)-1); - - return 0; -} - -static int -add_to_archive(struct archive *a, const char *real_path, const char *archive_path) -{ - struct stat st; - - if (lstat(real_path, &st) != 0) { - return -1; - } - - if (S_ISDIR(st.st_mode)) { - struct archive_entry *entry = archive_entry_new(); - archive_entry_set_pathname(entry, archive_path); - archive_entry_set_filetype(entry, AE_IFDIR); - archive_entry_set_perm(entry, st.st_mode & 0777); - - if (archive_write_header(a, entry) != ARCHIVE_OK) { - archive_entry_free(entry); - return -1; - } - - archive_entry_free(entry); - - DIR *dir = opendir(real_path); /* NEW */ - if (!dir) { - return -1; - } - - struct dirent *ent; - while ((ent = readdir(dir))) { /* NEW */ - if (strcmp(ent->d_name, ".") == 0 || - strcmp(ent->d_name, "..") == 0) { - continue; - } - - char child_real[PATH_MAX]; /* NEW */ - char child_arch[PATH_MAX]; /* NEW */ - - snprintf(child_real, sizeof(child_real), - "%s/%s", real_path, ent->d_name); - - snprintf(child_arch, sizeof(child_arch), - "%s/%s", archive_path, ent->d_name); - - if (add_to_archive(a, child_real, child_arch) != 0) { - closedir(dir); - return -1; - } - } - - closedir(dir); - return 0; - } - - /* existing file handling logic continues below */ - - if (S_ISREG(st.st_mode)) { - - int fd = open(real_path, O_RDONLY); - if (fd < 0) { - return -1; - } - - struct archive_entry *entry = archive_entry_new(); - archive_entry_set_pathname(entry, archive_path); - archive_entry_set_size(entry, st.st_size); - archive_entry_set_filetype(entry, AE_IFREG); - archive_entry_set_perm(entry, st.st_mode & 0777); - - if (archive_write_header(a, entry) != ARCHIVE_OK) { - archive_entry_free(entry); - close(fd); - return -1; - } - - char buf[8192]; - ssize_t n; - - while ((n = read(fd, buf, sizeof(buf))) > 0) { - if (archive_write_data(a, buf, (size_t)n) < 0) { - archive_entry_free(entry); - close(fd); - return -1; - } - } - - archive_entry_free(entry); - close(fd); - - if (n < 0) { - return -1; - } - - return 0; - } - - return 0; /* NEW: ignore other file types */ -} - -gl_backup_status_t -gl_backup_istore(const char *tar_path, - const char *glacier_root, - const char *uid) -{ - struct archive *a = archive_write_new(); - if (!a) { return GL_BACKUP_ERR_ALLOC; } - - if (archive_write_add_filter_gzip(a) != ARCHIVE_OK) { - archive_write_free(a); - return GL_BACKUP_ERR_OPEN; - } - - if (archive_write_set_format_pax_restricted(a) != ARCHIVE_OK) { - archive_write_free(a); - return GL_BACKUP_ERR_OPEN; - } - - if (archive_write_open_filename(a, tar_path) != ARCHIVE_OK) { - archive_write_free(a); - return GL_BACKUP_ERR_OPEN; - } - - char index_path[1024]; - char store_path[1024]; - char links_path[1024]; - - char arch_index[512]; - char arch_store[512]; - char arch_links[512]; - - snprintf(index_path, sizeof(index_path), "%s/index/%s", glacier_root, uid); - snprintf(store_path, sizeof(store_path), "%s/store/%s", glacier_root, uid); - snprintf(links_path, sizeof(links_path), "%s/links/%s", glacier_root, uid); - - snprintf(arch_index, sizeof(arch_index), "%s/index", uid); - snprintf(arch_store, sizeof(arch_store), "%s/store", uid); - snprintf(arch_links, sizeof(arch_links), "%s/links", uid); - - if (add_to_archive(a, index_path, arch_index) != 0) { - archive_write_close(a); - archive_write_free(a); - return GL_BACKUP_ERR_ADD_INDEX; - } - - if (add_to_archive(a, store_path, arch_store) != 0) { - archive_write_close(a); - archive_write_free(a); - return GL_BACKUP_ERR_ADD_STORE; - } - - if (add_to_archive(a, links_path, arch_links) != 0) { - archive_write_close(a); - archive_write_free(a); - return GL_BACKUP_ERR_ADD_LINKS; - } - - if (archive_write_close(a) != ARCHIVE_OK) { - archive_write_free(a); - return GL_BACKUP_ERR_CLOSE; - } - - archive_write_free(a); - return GL_BACKUP_OK; -} - -static int -gl_unlink_pkg(gl_context_t *ctx, const char *pkg_store_final) -{ - char links_base[PATH_MAX]; - strncpy(links_base, ctx->links_path, PATH_MAX - 1); - - size_t strip_len = strlen(pkg_store_final); - - char *stack[4096]; - int top = 0; - stack[top++] = strdup(pkg_store_final); - - while (top > 0) { - char * current = stack[--top]; - - DIR *dir = opendir(current); - if (!dir) { - free(current); - continue; - } - - struct dirent *ent; - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') { continue; } - - char full_path[PATH_MAX]; - snprintf(full_path, sizeof(full_path), "%s/%s", - current, ent->d_name); - - struct stat st; - if (lstat(full_path, &st) != 0) { continue; } - const char *rel = full_path + strip_len; - if (rel[0] == '/') { rel++; } - - if (strncmp(rel, "usr/", 4) == 0) { rel += 4; } - - char link_path[PATH_MAX]; - snprintf(link_path, sizeof(link_path), "%s/%s", - links_base, rel); - - if (S_ISDIR(st.st_mode)) { - if (top < 4096) { - stack[top++] = strdup(full_path); - } - } - else if (S_ISREG(st.st_mode)) { - unlink(link_path); - } - } - - closedir(dir); - free(current); - } - - return 0; -} - -gl_remove_status_t -gl_remove_pkg(gl_context_t *ctx, const char *pkg_name, const char *pkg_repo) -{ - if (!ctx) { return GL_REMOVE_ERR_NOT_FOUND; } - - /* find the package base directory in the store */ - char pkg_store_base[PATH_MAX]; - snprintf(pkg_store_base, sizeof(pkg_store_base), - "%s/%s/%s", ctx->store_path, pkg_repo, pkg_name); - - struct stat st; - if (stat(pkg_store_base, &st) != 0 || !S_ISDIR(st.st_mode)) { - return GL_REMOVE_ERR_NOT_FOUND; - } - - /* find the versioned subdirectory */ - DIR *dir = opendir(pkg_store_base); - if (!dir) { return GL_REMOVE_ERR_NOT_FOUND; } - - char pkg_store_final[PATH_MAX] = {0}; - struct dirent *ent; - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') { continue; } - snprintf(pkg_store_final, sizeof(pkg_store_final), - "%s/%s", pkg_store_base, ent->d_name); - break; - } - closedir(dir); - - if (pkg_store_final[0] == '\0') { - return GL_REMOVE_ERR_NOT_FOUND; - } - - /* remove symlinks from links tree. GL_CTX_STAGE: skip — the - * stage links tree isn't seeded (links are fully derived from - * the store post-commit by relink_store), so there's nothing - * there to unlink. */ - if (ctx->mode == GL_CTX_LIVE) { - if (gl_unlink_pkg(ctx, pkg_store_final) != 0) { - return GL_REMOVE_ERR_UNLINK; - } - } - - /* remove package from store */ - if (gl_rmdir_recursive(pkg_store_base) != 0) { - return GL_REMOVE_ERR_UNLINK; - } - - /* rebuild index */ - if (gl_rebuild_index(ctx) != 0) { - return GL_REMOVE_ERR_INDEX; - } - - return GL_REMOVE_OK; -} - -static int -gl_link_pkg(gl_context_t *ctx, const char *pkg_store_final) -{ - char links_base[PATH_MAX]; - strncpy(links_base, ctx->links_path, PATH_MAX - 1); - - size_t strip_len = strlen(pkg_store_final); - - /* use a stack-based queue to walk the tree without recursion */ - char *stack[4096]; - int top = 0; - - stack[top++] = strdup(pkg_store_final); - - while (top > 0) { - char *current = stack[--top]; - - DIR *dir = opendir(current); - if (!dir) { - free(current); - continue; - } - - struct dirent *ent; - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') { continue; } - - char full_path[PATH_MAX]; - snprintf(full_path, sizeof(full_path), "%s/%s", - current, ent->d_name); - - struct stat st; - if (lstat(full_path, &st) != 0) { continue; } - - /* relative path inside the package, e.g. usr/bin/kilo */ - const char *rel = full_path + strip_len; - if (rel[0] == '/') { rel++; } - - /* strip leading usr/ so bin/kilo lands at links/1000/bin/kilo */ - if (strncmp(rel, "usr/", 4) == 0) { rel += 4; } - - char link_path[PATH_MAX]; - snprintf(link_path, sizeof(link_path), "%s/%s", - links_base, rel); - - if (S_ISDIR(st.st_mode)) { - /* create the directory in the links tree */ - gl_mkdirp(link_path, 0700); - - /* push onto stack to recurse into */ - if (top < 4096) { - stack[top++] = strdup(full_path); - } - } else if (S_ISREG(st.st_mode)) { - /* create parent dirs in links tree */ - char parent[PATH_MAX]; - strncpy(parent, link_path, sizeof(parent)); - char *slash = strrchr(parent, '/'); - if (slash) { - *slash = '\0'; - gl_mkdirp(parent, 0700); - } - - /* remove existing symlink if present */ - unlink(link_path); - - /* symlink store path -> links tree */ - if (symlink(full_path, link_path) != 0) { - closedir(dir); - free(current); - while (top > 0) { free(stack[--top]); } - return -1; - } - - lchown(link_path, ctx->uid, (gid_t)-1); - } - } - - closedir(dir); - free(current); - } - - return 0; -} - -int -gl_delete_user(uid_t uid, bool isVerbose) -{ - char ind_path[PATH_MAX]; - char sto_path[PATH_MAX]; - char lnk_path[PATH_MAX]; - - snprintf(ind_path, sizeof(ind_path), "%s/%d", usr_index.path, uid); - snprintf(sto_path, sizeof(sto_path), "%s/%d", usr_store.path, uid); - snprintf(lnk_path, sizeof(lnk_path), "%s/%d", usr_links.path, uid); - - if (isVerbose) { lg_printf(0, "Removing Glacier directories for UID %d...", uid); } - - if (gl_rmdir_recursive(ind_path) != 0) { - lg_printf(2, "Failed to remove index for UID %d", uid); - return 1; - } - - if (gl_rmdir_recursive(sto_path) != 0) { - lg_printf(2, "Failed to remove store for UID %d", uid); - return 1; - } - - if (gl_rmdir_recursive(lnk_path) != 0) { - lg_printf(2, "Failed to remove links for UID %d", uid); - return 1; - } - - lg_printf(3, "Successfully removed Glacier directories for UID %d.", uid); - return 0; -} - -char -*gl_find_pkg_repo(gl_context_t *ctx, const char *pkg_name) -{ - char store_path[PATH_MAX]; - strncpy(store_path, ctx->store_path, PATH_MAX - 1); - - DIR *uid_dir = opendir(store_path); - if (!uid_dir) { return NULL; } - - struct dirent *repo_entry; - while ((repo_entry = readdir(uid_dir)) != NULL) { - if (repo_entry->d_name[0] == '.') { continue; } - - char pkg_path[PATH_MAX]; - snprintf(pkg_path, sizeof(pkg_path), "%s/%s/%s", store_path, repo_entry->d_name, pkg_name); - - struct stat st; - if (stat(pkg_path, &st) == 0 && S_ISDIR(st.st_mode)) { - char *repo = strdup(repo_entry->d_name); - closedir(uid_dir); - return repo; - } - } - - closedir(uid_dir); - return NULL; -} - -gl_repo_list_t -gl_find_pkg_repos(gl_context_t *ctx, const char *pkg_name) -{ - gl_repo_list_t result = { NULL, 0 }; - - char store_path[PATH_MAX]; - strncpy(store_path, ctx->store_path, PATH_MAX - 1); - - DIR *uid_dir = opendir(store_path); - if (!uid_dir) { return result; } - - struct dirent *repo_entry; - while ((repo_entry = readdir(uid_dir)) != NULL) { - if (repo_entry->d_name[0] == '.') { continue; } - - char pkg_path[PATH_MAX]; - snprintf(pkg_path, sizeof(pkg_path), - "%s/%s/%s", store_path, repo_entry->d_name, pkg_name); - - struct stat st; - if (stat(pkg_path, &st) == 0 && S_ISDIR(st.st_mode)) { - char **tmp = realloc(result.repos, - (result.count + 1) * sizeof(char *)); - if (!tmp) { break; } - result.repos = tmp; - result.repos[result.count] = strdup(repo_entry->d_name); - result.count++; - } - } - - closedir(uid_dir); - return result; -} - -void -gl_free_repo_list(gl_repo_list_t *list) -{ - if (!list) { return; } - for (size_t i = 0; i < list->count; i++) { free(list->repos[i]); } - free(list->repos); - list->repos = NULL; - list->count = 0; -} - -gl_restore_status_t -gl_restore_istore(const char *tar_path, const char *glacier_root, const char *uid) -{ - struct archive *a = archive_read_new(); - archive_read_support_filter_gzip(a); - archive_read_support_format_tar(a); - - if (archive_read_open_filename(a, tar_path, 10240) != ARCHIVE_OK) { - archive_read_free(a); - return GL_RESTORE_ERR_OPEN; - } - - struct archive_entry *entry; - while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { - const char *rel = archive_entry_pathname(entry); - - char dest[PATH_MAX]; - snprintf(dest, sizeof(dest), "%s/%s/%s", - glacier_root, uid, rel); - - archive_entry_set_pathname(entry, dest); - - if (archive_entry_filetype(entry) == AE_IFDIR) { - gl_mkdirp(dest, archive_entry_perm(entry)); - archive_read_data_skip(a); - continue; - } - - /* create parent dirs */ - char parent[PATH_MAX]; - strncpy(parent, dest, sizeof(parent)); - char *slash = strrchr(parent, '/'); - if (slash) { - *slash = '\0'; - gl_mkdirp(parent, 0700); - } - - int fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, - archive_entry_perm(entry)); - if (fd < 0) { - archive_read_free(a); - return GL_RESTORE_ERR_EXTRACT; - } - - char buf[8192]; - ssize_t n; - while ((n = archive_read_data(a, buf, sizeof(buf))) > 0) { - ssize_t written = write(fd, buf, (size_t)n); - if (written < 0 || written != n) { - close(fd); - archive_read_free(a); - return GL_RESTORE_ERR_EXTRACT; - } - } - close(fd); - } - - archive_read_free(a); - return GL_RESTORE_OK; -} - -gl_install_status_t -gl_install_pkg(gl_context_t *ctx, const char *gpkg_path) -{ - if (!ctx) { return GL_INSTALL_ERR_OPEN; } - char original_cwd[PATH_MAX]; - if (getcwd(original_cwd, sizeof(original_cwd)) == NULL) { - return GL_INSTALL_ERR_OPEN; - } - - /* The archive is opened and the manifest is parsed here */ - struct archive *a = archive_read_new(); - archive_read_support_filter_gzip(a); - archive_read_support_format_tar(a); - - if (archive_read_open_filename(a, gpkg_path, 10240) != ARCHIVE_OK) { - archive_read_free(a); - return GL_INSTALL_ERR_OPEN; - } - - struct archive_entry *entry; - gl_pkg_t pkg = {0}; - bool manifest_found = false; - - while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { - const char *path = archive_entry_pathname(entry); - - if (strstr(path, "manifest.gpm.cfg")) { - char tmp_manifest[PATH_MAX]; - strncpy(tmp_manifest, "/tmp/gpkg_manifest_XXXXXX", - sizeof(tmp_manifest)); - - int fd = mkstemp(tmp_manifest); - if (fd < 0) { - archive_read_free(a); - return GL_INSTALL_ERR_MANIFEST; - } - - char buffer[8192]; - ssize_t n; - - while ((n = archive_read_data(a, buffer, sizeof(buffer))) > 0) { - ssize_t written = write(fd, buffer, (size_t)n); - if (written < 0 || written != n) { - close(fd); - unlink(tmp_manifest); - archive_read_free(a); - return GL_INSTALL_ERR_MANIFEST; - } - } - - close(fd); - - if (gl_gpm2gpkg(tmp_manifest, &pkg) != 0) { - unlink(tmp_manifest); - archive_read_free(a); - return GL_INSTALL_ERR_MANIFEST; - } - - unlink(tmp_manifest); - manifest_found = true; - break; - } - - archive_read_data_skip(a); - } - - archive_read_free(a); - - if (!manifest_found) { - return GL_INSTALL_ERR_MANIFEST; - } - - char pkg_store_base[PATH_MAX]; - char pkg_store_final[PATH_MAX]; - - /* construct the directory for the package in the store */ - snprintf(pkg_store_base, sizeof(pkg_store_base), - "%s/%s/%s", ctx->store_path, pkg.pkg_repo, pkg.pkg_name); - - snprintf(pkg_store_final, sizeof(pkg_store_final), - "%s/%s-%d.%d.%d", pkg_store_base, pkg.pkg_name, - pkg.pkg_ver.maj, pkg.pkg_ver.min, pkg.pkg_ver.pat); - - if (gl_mkdirp(pkg_store_base, 0700) == -1) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } - - if (mkdir(pkg_store_final, 0700) == -1) { - if (errno == EEXIST) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_ALREADY_INSTALLED; - } - - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } - - /* now the archive must be reopened in order to extract package files */ - struct archive *a2 = archive_read_new(); - archive_read_support_filter_gzip(a2); - archive_read_support_format_tar(a2); - - if (archive_read_open_filename(a2, gpkg_path, 10240) != ARCHIVE_OK) { - archive_read_free(a2); - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } - - char strip_prefix[PATH_MAX]; - snprintf(strip_prefix, sizeof(strip_prefix), - "%s-%d.%d.%d/files/", pkg.pkg_name, - pkg.pkg_ver.maj, pkg.pkg_ver.min, pkg.pkg_ver.pat); - - while (archive_read_next_header(a2, &entry) == ARCHIVE_OK) { - const char *entry_path = archive_entry_pathname(entry); - - if (strncmp(entry_path, strip_prefix, strlen(strip_prefix)) != 0) { - archive_read_data_skip(a2); - continue; - } - - const char *rel_path = entry_path + strlen(strip_prefix); - if (rel_path[0] == '\0') { - archive_read_data_skip(a2); - continue; - } - - char dest_path[PATH_MAX]; - snprintf(dest_path, sizeof(dest_path), "%s/%s", - pkg_store_final, rel_path); - - if (archive_entry_filetype(entry) == AE_IFDIR) { - if (mkdir(dest_path, archive_entry_perm(entry)) == -1 - && errno != EEXIST) { - archive_read_free(a2); - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } - } - else if (archive_entry_filetype(entry) == AE_IFREG) { - char parent[PATH_MAX]; - strncpy(parent, dest_path, sizeof(parent)); - char *slash = strrchr(parent, '/'); - if (slash) { - *slash = '\0'; - gl_mkdirp(parent, 0700); - } - - int fd = open(dest_path, O_WRONLY | O_CREAT | O_TRUNC, - archive_entry_perm(entry)); - - if (fd < 0) { - archive_read_free(a2); - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } - - char buffer[8192]; - ssize_t n; - while ((n = archive_read_data(a2, buffer, sizeof(buffer))) > 0) { - ssize_t written = write(fd, buffer, (size_t)n); - if (written < 0 || written != n) { - close(fd); - archive_read_free(a2); - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } - } - - close(fd); - } - } - - archive_read_free(a2); - - /* now the index will be updated */ - /* Resolve "current" symlink to find the actual index file to append to */ - char current_link[PATH_MAX]; - snprintf(current_link, sizeof(current_link), "%s/current", ctx->index_path); - - char current_target[PATH_MAX]; - ssize_t len = readlink(current_link, current_target, sizeof(current_target) - 1); - if (len < 0) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_INDEX; - } - current_target[len] = '\0'; - - char index_path[PATH_MAX]; - snprintf(index_path, sizeof(index_path), "%s/%s", - ctx->index_path, current_target); - - FILE *idx = fopen(index_path, "a"); - if (!idx) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_INDEX; - } - - fprintf(idx, "%s::%s\n", pkg.pkg_repo, pkg.pkg_name); - fclose(idx); - - if (gl_rebuild_index(ctx) != 0) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_INDEX; - } - - if (ctx->mode == GL_CTX_LIVE) { - if (gl_link_pkg(ctx, pkg_store_final) != 0) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } - } - /* GL_CTX_STAGE: skip. A symlink written here would target - * ctx->store_path, which is the stage path — it goes stale the - * moment gl_commit_transaction renames the store into its live - * location. The links tree is fully derived from the store, so - * it's regenerated wholesale post-commit instead of tracked - * incrementally here (see relink_store in transaction.c). */ - - gl_free_pkg(&pkg); - chdir(original_cwd); - return GL_INSTALL_OK; -} - -int -gl_relink_store(gl_context_t *ctx) -{ - DIR *repo_dir = opendir(ctx->store_path); - if (!repo_dir) return (errno == ENOENT) ? 0 : -1; - - struct dirent *repo_ent; - while ((repo_ent = readdir(repo_dir))) { - if (repo_ent->d_name[0] == '.') continue; - - char repo_path[PATH_MAX]; - snprintf(repo_path, sizeof(repo_path), "%s/%s", - ctx->store_path, repo_ent->d_name); - if (!is_dir(repo_path)) continue; - - DIR *name_dir = opendir(repo_path); - if (!name_dir) continue; - - struct dirent *name_ent; - while ((name_ent = readdir(name_dir))) { - if (name_ent->d_name[0] == '.') continue; - - char name_path[PATH_MAX]; - snprintf(name_path, sizeof(name_path), "%s/%s", - repo_path, name_ent->d_name); - if (!is_dir(name_path)) continue; - - /* one version dir per package name today */ - DIR *ver_dir = opendir(name_path); - if (!ver_dir) continue; - - struct dirent *ver_ent; - while ((ver_ent = readdir(ver_dir))) { - if (ver_ent->d_name[0] == '.') continue; - - char ver_path[PATH_MAX]; - snprintf(ver_path, sizeof(ver_path), "%s/%s", - name_path, ver_ent->d_name); - if (!is_dir(ver_path)) continue; - - if (gl_link_pkg(ctx, ver_path) != 0) { - closedir(ver_dir); closedir(name_dir); - closedir(repo_dir); - return -1; - } - } - closedir(ver_dir); - } - closedir(name_dir); - } - closedir(repo_dir); - return 0; -} \ No newline at end of file diff --git a/src/istoreutils.c.rej b/src/istoreutils.c.rej deleted file mode 100644 index 617ab7f..0000000 --- a/src/istoreutils.c.rej +++ /dev/null @@ -1,302 +0,0 @@ ---- istoreutils.c.orig 2026-06-01 19:43:00.493773073 +0000 -+++ istoreutils.c.new 2026-06-01 19:43:00.573469330 +0000 -@@ -21,6 +21,7 @@ - #include "istoreutils.h" - #include "log.h" - #include "pkg.h" -+#include "transaction.h" - - static const dir_t usr_index = { "/glacier/usr/index", 0700 }; - static const dir_t sys_index = { "/glacier/sys/index", 0700 }; -@@ -29,6 +30,7 @@ - static const dir_t sys_store = { "/glacier/sys/store", 0700 }; - - static const dir_t usr_links = { "/glacier/usr/links", 0700 }; -+static const dir_t sys_links = { "/glacier/sys/links", 0700 }; - - bool - gl_usr_istore_exists(index_store_t index_or_store, int uid) -@@ -253,6 +255,46 @@ - return 0; - } - -+int -+gl_init_sys(bool isVerbose) -+{ -+ const char *paths[] = { -+ sys_index.path, -+ sys_store.path, -+ sys_links.path, -+ }; -+ mode_t modes[] = { -+ sys_index.mode, -+ sys_store.mode, -+ sys_links.mode, -+ }; -+ -+ for (int i = 0; i < 3; i++) { -+ if (isVerbose) { lg_printf(0, "Creating %s", paths[i]); } -+ -+ if (mkdir(paths[i], modes[i]) == -1) { -+ switch (errno) { -+ case EEXIST: -+ break; -+ case EACCES: -+ lg_printf(2, "Cannot create %s: permission denied", paths[i]); -+ return 1; -+ case ENOSPC: -+ lg_printf(2, "Cannot create %s: no space left on device", paths[i]); -+ return 1; -+ case EROFS: -+ lg_printf(2, "Cannot create %s: read-only filesystem", paths[i]); -+ return 1; -+ default: -+ lg_printf(2, "Cannot create %s: mkdir failed", paths[i]); -+ return -1; -+ } -+ } -+ } -+ -+ return 0; -+} -+ - static void - trim(char *s) - { -@@ -409,12 +451,11 @@ - */ - - int --gl_rebuild_index(uid_t uid, const char *out_dir) -+gl_rebuild_index(gl_context_t *ctx) - { -- char store_path[PATH_MAX]; -- snprintf(store_path, sizeof(store_path), "%s/%d", usr_store.path, uid); -+ if (!ctx) { return -1; } - -- DIR *store_dir = opendir(store_path); -+ DIR *store_dir = opendir(ctx->store_path); - if (!store_dir) return -1; - - /* Write to a new timestamped index file */ -@@ -422,7 +463,8 @@ - make_index_name(fname, sizeof(fname)); - - char new_index_path[PATH_MAX]; -- snprintf(new_index_path, sizeof(new_index_path), "%s/%s", out_dir, fname); -+ snprintf(new_index_path, sizeof(new_index_path), "%s/%s", -+ ctx->index_path, fname); - - FILE *out = fopen(new_index_path, "w"); - if (!out) { -@@ -438,7 +480,7 @@ - - char repo_path[PATH_MAX]; - snprintf(repo_path, sizeof(repo_path), "%s/%s", -- store_path, repo_ent->d_name); -+ ctx->store_path, repo_ent->d_name); - - struct stat rst; - if (stat(repo_path, &rst) != 0 || !S_ISDIR(rst.st_mode)) { -@@ -476,14 +518,15 @@ - if (!tmp_in) return -1; - - char tmp_path[PATH_MAX]; -- snprintf(tmp_path, sizeof(tmp_path), "%s/.index_tmp_XXXXXX", out_dir); -+ snprintf(tmp_path, sizeof(tmp_path), "%s/.index_tmp_XXXXXX", -+ ctx->index_path); - int tmp_fd = mkstemp(tmp_path); - if (tmp_fd < 0) { fclose(tmp_in); return -1; } - - FILE *tmp_out = fdopen(tmp_fd, "w"); - if (!tmp_out) { close(tmp_fd); fclose(tmp_in); return -1; } - -- fprintf(tmp_out, "uid = %d\n", uid); -+ fprintf(tmp_out, "uid = %d\n", ctx->uid); - fprintf(tmp_out, "listed = %zu\n\n", listed); - - char line[512]; -@@ -494,15 +537,15 @@ - fclose(tmp_out); - - rename(tmp_path, new_index_path); -- chown(new_index_path, uid, (gid_t)-1); -+ chown(new_index_path, ctx->uid, (gid_t)-1); - - /* Update the "current" symlink to point at the new index */ - char link_path[PATH_MAX]; -- snprintf(link_path, sizeof(link_path), "%s/current", out_dir); -+ snprintf(link_path, sizeof(link_path), "%s/current", ctx->index_path); - unlink(link_path); - - if (symlink(fname, link_path) != 0) { return -1; } -- lchown(link_path, uid, (gid_t)-1); -+ lchown(link_path, ctx->uid, (gid_t)-1); - - return 0; - } -@@ -672,10 +715,10 @@ - } - - static int --gl_unlink_pkg(const char *pkg_store_final, uid_t uid) -+gl_unlink_pkg(gl_context_t *ctx, const char *pkg_store_final) - { - char links_base[PATH_MAX]; -- snprintf(links_base, sizeof(links_base), "%s/%d", usr_links.path, uid); -+ strncpy(links_base, ctx->links_path, PATH_MAX - 1); - - size_t strip_len = strlen(pkg_store_final); - -@@ -729,12 +772,14 @@ - } - - gl_remove_status_t --gl_remove_pkg(const char *pkg_name, const char *pkg_repo, uid_t uid) -+gl_remove_pkg(gl_context_t *ctx, const char *pkg_name, const char *pkg_repo) - { -+ if (!ctx) { return GL_REMOVE_ERR_NOT_FOUND; } -+ - /* find the package base directory in the store */ - char pkg_store_base[PATH_MAX]; - snprintf(pkg_store_base, sizeof(pkg_store_base), -- "%s/%d/%s/%s", usr_store.path, uid, pkg_repo, pkg_name); -+ "%s/%s/%s", ctx->store_path, pkg_repo, pkg_name); - - struct stat st; - if (stat(pkg_store_base, &st) != 0 || !S_ISDIR(st.st_mode)) { -@@ -760,7 +805,7 @@ - } - - /* remove symlinks from links tree */ -- if (gl_unlink_pkg(pkg_store_final, uid) != 0) { -+ if (gl_unlink_pkg(ctx, pkg_store_final) != 0) { - return GL_REMOVE_ERR_UNLINK; - } - -@@ -770,10 +815,7 @@ - } - - /* rebuild index */ -- char index_dir[PATH_MAX]; -- snprintf(index_dir, sizeof(index_dir), "%s/%d", usr_index.path, uid); -- -- if (gl_rebuild_index(uid, index_dir) != 0) { -+ if (gl_rebuild_index(ctx) != 0) { - return GL_REMOVE_ERR_INDEX; - } - -@@ -781,10 +823,10 @@ - } - - static int --gl_link_pkg(const char *pkg_store_final, uid_t uid) -+gl_link_pkg(gl_context_t *ctx, const char *pkg_store_final) - { - char links_base[PATH_MAX]; -- snprintf(links_base, sizeof(links_base), "%s/%d", usr_links.path, uid); -+ strncpy(links_base, ctx->links_path, PATH_MAX - 1); - - size_t strip_len = strlen(pkg_store_final); - -@@ -854,7 +896,7 @@ - return -1; - } - -- lchown(link_path, uid, (gid_t)-1); -+ lchown(link_path, ctx->uid, (gid_t)-1); - } - } - -@@ -898,11 +940,10 @@ - } - - char --*gl_find_pkg_repo(const char *pkg_name, uid_t uid) -+*gl_find_pkg_repo(gl_context_t *ctx, const char *pkg_name) - { - char store_path[PATH_MAX]; -- snprintf(store_path, sizeof(store_path), --"/glacier/usr/store/%u", uid); -+ strncpy(store_path, ctx->store_path, PATH_MAX - 1); - - DIR *uid_dir = opendir(store_path); - if (!uid_dir) { return NULL; } -@@ -927,13 +968,12 @@ - } - - gl_repo_list_t --gl_find_pkg_repos(const char *pkg_name, uid_t uid) -+gl_find_pkg_repos(gl_context_t *ctx, const char *pkg_name) - { - gl_repo_list_t result = { NULL, 0 }; - - char store_path[PATH_MAX]; -- snprintf(store_path, sizeof(store_path), -- "/glacier/usr/store/%u", uid); -+ strncpy(store_path, ctx->store_path, PATH_MAX - 1); - - DIR *uid_dir = opendir(store_path); - if (!uid_dir) { return result; } -@@ -1033,8 +1073,9 @@ - } - - gl_install_status_t --gl_install_pkg(const char *gpkg_path, uid_t uid) -+gl_install_pkg(gl_context_t *ctx, const char *gpkg_path) - { -+ if (!ctx) { return GL_INSTALL_ERR_OPEN; } - char original_cwd[PATH_MAX]; - if (getcwd(original_cwd, sizeof(original_cwd)) == NULL) { - return GL_INSTALL_ERR_OPEN; -@@ -1108,7 +1149,7 @@ - - /* construct the directory for the package in the store */ - snprintf(pkg_store_base, sizeof(pkg_store_base), -- "%s/%d/%s/%s", usr_store.path, uid, pkg.pkg_repo, pkg.pkg_name); -+ "%s/%s/%s", ctx->store_path, pkg.pkg_repo, pkg.pkg_name); - - snprintf(pkg_store_final, sizeof(pkg_store_final), - "%s/%s-%d.%d.%d", pkg_store_base, pkg.pkg_name, -@@ -1208,15 +1249,9 @@ - archive_read_free(a2); - - /* now the index will be updated */ -- -- /* now the index will be updated */ -- char index_dir[PATH_MAX]; -- snprintf(index_dir, sizeof(index_dir), -- "%s/%d", usr_index.path, uid); -- - /* Resolve "current" symlink to find the actual index file to append to */ - char current_link[PATH_MAX]; -- snprintf(current_link, sizeof(current_link), "%s/current", index_dir); -+ snprintf(current_link, sizeof(current_link), "%s/current", ctx->index_path); - - char current_target[PATH_MAX]; - ssize_t len = readlink(current_link, current_target, sizeof(current_target) - 1); -@@ -1227,7 +1262,8 @@ - current_target[len] = '\0'; - - char index_path[PATH_MAX]; -- snprintf(index_path, sizeof(index_path), "%s/%s", index_dir, current_target); -+ snprintf(index_path, sizeof(index_path), "%s/%s", -+ ctx->index_path, current_target); - - FILE *idx = fopen(index_path, "a"); - if (!idx) { -@@ -1238,12 +1274,12 @@ - fprintf(idx, "%s::%s\n", pkg.pkg_repo, pkg.pkg_name); - fclose(idx); - -- if (gl_rebuild_index(uid, index_dir) != 0) { -+ if (gl_rebuild_index(ctx) != 0) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_INDEX; - } - -- if (gl_link_pkg(pkg_store_final, uid) != 0) { -+ if (gl_link_pkg(ctx, pkg_store_final) != 0) { - gl_free_pkg(&pkg); - return GL_INSTALL_ERR_EXTRACT; - } diff --git a/src/istoreutils.h b/src/istoreutils.h index db50d4a..58564da 100644 --- a/src/istoreutils.h +++ b/src/istoreutils.h @@ -47,6 +47,7 @@ typedef enum { GL_INSTALL_ERR_INDEX = 4, GL_INSTALL_ERR_ALREADY_INSTALLED = 5, GL_INSTALL_SKIPPED = 6, + GL_INSTALL_ERR_SCOPE = 7, } gl_install_status_t; diff --git a/src/istoreutils.h.back b/src/istoreutils.h.back deleted file mode 100644 index a3ee8e3..0000000 --- a/src/istoreutils.h.back +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef ISTOREUTILS_H_ -#define ISTOREUTILS_H_ - -#include -#include -#include - -typedef enum { - INDEX, - STORE -} -index_store_t; - -typedef enum { - GL_BACKUP_OK = 0, - GL_BACKUP_ERR_ALLOC = 1, - GL_BACKUP_ERR_OPEN = 2, - GL_BACKUP_ERR_ADD_INDEX = 3, - GL_BACKUP_ERR_ADD_STORE = 4, - GL_BACKUP_ERR_ADD_LINKS = 5, - GL_BACKUP_ERR_CLOSE = 6 -} -gl_backup_status_t; - -typedef enum { - GL_RESTORE_OK = 0, - GL_RESTORE_ERR_OPEN = 1, - GL_RESTORE_ERR_EXTRACT = 2 -} gl_restore_status_t; - -/* - * GL_INSTALL_OK: installation successful - * GL_INSTALL_ERR_OPEN: unable to open .gpkg file - * GL_INSTALL_ERR_MANIFEST: manifest is missing or unparseable - * GL_INSTALL_ERR_EXTRACT: unable to extract files - * GL_INSTALL_ERR_INDEX: unable to update index - * GL_INSTALL_ERR_ALREADY_INSTALLED: package already installed - */ - -typedef enum { - GL_INSTALL_OK = 0, - GL_INSTALL_ERR_OPEN = 1, - GL_INSTALL_ERR_MANIFEST = 2, - GL_INSTALL_ERR_EXTRACT = 3, - GL_INSTALL_ERR_INDEX = 4, - GL_INSTALL_ERR_ALREADY_INSTALLED = 5, - GL_INSTALL_SKIPPED = 6, -} -gl_install_status_t; - -typedef enum { - GL_REMOVE_OK = 0, - GL_REMOVE_ERR_NOT_FOUND = 1, - GL_REMOVE_ERR_UNLINK = 2, - GL_REMOVE_ERR_INDEX = 3, -} gl_remove_status_t; - -struct gpkg_entry { - char *repo; - char *pkg; -}; - -struct gindex { - int uid; - int listed; - struct gpkg_entry *entries; - size_t count; -}; - -bool gl_usr_istore_exists(index_store_t index_or_store, int uid); -bool gl_sys_istore_exists(index_store_t index_or_store); - -int gl_init_user(uid_t uid, bool isVerbose); -int gl_delete_user(uid_t uid, bool isVerbose); - -int gl_parse_index(struct gindex *idx, FILE *f); -void gl_free_index(struct gindex *idx); - -int gl_rebuild_index(uid_t uid, const char *out_dir); - -char *gl_find_pkg_repo(const char *pkg_name, uid_t uid); - -typedef struct { - char **repos; - size_t count; -} -gl_repo_list_t; - -gl_repo_list_t gl_find_pkg_repos(const char *pkg_name, uid_t uid); -void gl_free_repo_list(gl_repo_list_t *list); - -gl_backup_status_t gl_backup_istore(const char *tar_path, const char *glacier_root, - const char *uid); -gl_restore_status_t gl_restore_istore(const char *tar_path, const char *glacier_root, const char *uid); - -gl_install_status_t gl_install_pkg(const char *gpkg_path, uid_t uid); -gl_remove_status_t gl_remove_pkg(const char *pkg_name, const char *pkg_repo, uid_t uid); - - - -#endif