/* * pkg - Package locker * https://rawnix.org * * Copyright (c) 2025 zorz@gmx.com * SPDX-License-Identifier: BSD-2-Clause */ #include "locker.h" #include "paths.h" #include #include struct locker { char *path; strarray_t pkgs; }; locker_t *locker_open(const char *root) { locker_t *l; FILE *fp; char line[256]; l = xmalloc(sizeof(locker_t)); strarray_init(&l->pkgs); l->path = build_root_path(root, LOCK_FILE); fp = fopen(l->path, "r"); if (!fp) return l; while (fgets(line, sizeof(line), fp)) { line[strcspn(line, "\n")] = '\0'; if (line[0] && line[0] != '#') strarray_add(&l->pkgs, line); } fclose(fp); return l; } void locker_close(locker_t *l) { if (!l) return; strarray_free(&l->pkgs); free(l->path); free(l); } static int locker_save(locker_t *l) { char tmp[4096]; int fd; FILE *fp; size_t i; ensure_parent_dir(l->path); snprintf(tmp, sizeof(tmp), "%s.tmp", l->path); fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) return -1; fp = fdopen(fd, "w"); if (!fp) { close(fd); unlink(tmp); return -1; } fprintf(fp, "# Locked packages (excluded from sysup)\n"); for (i = 0; i < l->pkgs.size; i++) fprintf(fp, "%s\n", l->pkgs.data[i]); if (file_close_checked(fp) != 0) { unlink(tmp); return -1; } if (rename(tmp, l->path) != 0) { unlink(tmp); return -1; } return 0; } bool locker_is_locked(locker_t *l, const char *pkg) { return strarray_contains(&l->pkgs, pkg); } bool locker_lock(locker_t *l, const char *pkg) { if (locker_is_locked(l, pkg)) return true; strarray_add(&l->pkgs, pkg); return locker_save(l) == 0; } bool locker_unlock(locker_t *l, const char *pkg) { size_t i; for (i = 0; i < l->pkgs.size; i++) { if (strcmp(l->pkgs.data[i], pkg) == 0) { free(l->pkgs.data[i]); l->pkgs.data[i] = l->pkgs.data[--l->pkgs.size]; return locker_save(l) == 0; } } return false; } strarray_t *locker_list(locker_t *l) { strarray_t *arr; size_t i; arr = xmalloc(sizeof(strarray_t)); strarray_init(arr); for (i = 0; i < l->pkgs.size; i++) strarray_add(arr, l->pkgs.data[i]); return arr; }