rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include rhughes@241: #include "razor.h" rhughes@241: #include "razor-internal.h" rhughes@241: rhughes@241: static const char system_repo_filename[] = "system.repo"; rhughes@241: static const char next_repo_filename[] = "system-next.repo"; rhughes@241: static const char razor_root_path[] = "/var/lib/razor"; rhughes@241: rhughes@241: struct razor_root { rhughes@241: struct razor_set *system; rhughes@241: struct razor_set *next; rhughes@241: int fd; rhughes@241: char path[PATH_MAX]; rhughes@241: char new_path[PATH_MAX]; rhughes@241: }; rhughes@241: rhughes@241: int rhughes@241: razor_root_create(const char *root) rhughes@241: { rhughes@241: struct stat buf; rhughes@241: struct razor_set *set; rhughes@241: char path[PATH_MAX]; rhughes@241: rhughes@241: if (stat(root, &buf) < 0) { rhughes@241: if (mkdir(root, 0777) < 0) { rhughes@241: fprintf(stderr, rhughes@241: "could not create install root \"%s\"\n", rhughes@241: root); rhughes@241: return -1; rhughes@241: } rhughes@241: fprintf(stderr, "created install root \"%s\"\n", root); rhughes@241: } else if (!S_ISDIR(buf.st_mode)) { rhughes@241: fprintf(stderr, rhughes@241: "install root \"%s\" exists, but is not a directory\n", rhughes@241: root); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: snprintf(path, sizeof path, "%s/%s", rhughes@241: razor_root_path, system_repo_filename); rhughes@241: if (razor_create_dir(root, path) < 0) { rhughes@241: fprintf(stderr, "could not create %s%s\n", rhughes@241: root, razor_root_path); rhughes@241: return -1; rhughes@241: } rhughes@241: rhughes@241: set = razor_set_create(); rhughes@241: snprintf(path, sizeof path, "%s%s/%s", rhughes@241: root, razor_root_path, system_repo_filename); rhughes@241: if (stat(path, &buf) == 0) { rhughes@241: fprintf(stderr, rhughes@241: "a razor install root is already initialized\n"); rhughes@241: return -1; rhughes@241: } rhughes@241: if (razor_set_write(set, path) < 0) { rhughes@241: fprintf(stderr, "could not write initial package set\n"); rhughes@241: return -1; rhughes@241: } rhughes@241: razor_set_destroy(set); rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: struct razor_root * rhughes@241: razor_root_open(const char *root, int flags) rhughes@241: { rhughes@241: struct razor_root *image; rhughes@241: rhughes@241: image = malloc(sizeof *image); rhughes@241: if (image == NULL) rhughes@241: return NULL; rhughes@241: rhughes@241: /* Create the new next repo file up front to ensure exclusive rhughes@241: * access. */ rhughes@241: snprintf(image->new_path, sizeof image->new_path, krh@243: "%s%s/%s", root, razor_root_path, next_repo_filename); rhughes@241: image->fd = open(image->new_path, rhughes@241: O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666); rhughes@241: if (image->fd < 0) { rhughes@241: fprintf(stderr, "failed to get lock file, " rhughes@241: "maybe previous operation crashed?\n"); rhughes@241: rhughes@241: /* FIXME: Use fcntl advisory locking on the system rhughes@241: * package set file to figure out whether previous rhughes@241: * operation crashed or is still in progress. */ rhughes@241: rhughes@241: free(image); rhughes@241: return NULL; rhughes@241: } rhughes@241: rhughes@241: snprintf(image->path, sizeof image->path, rhughes@241: "%s%s/%s", root, razor_root_path, system_repo_filename); rhughes@241: image->system = razor_set_open(image->path); rhughes@241: if (image->system == NULL) { rhughes@241: unlink(image->new_path); rhughes@241: close(image->fd); rhughes@241: free(image); rhughes@241: return NULL; rhughes@241: } rhughes@241: rhughes@241: return image; rhughes@241: } rhughes@241: rhughes@241: struct razor_set * rhughes@241: razor_root_open_read_only(const char *root) rhughes@241: { rhughes@241: char path[PATH_MAX]; rhughes@241: rhughes@241: snprintf(path, sizeof path, "%s%s/%s", rhughes@241: root, razor_root_path, system_repo_filename); rhughes@241: rhughes@241: return razor_set_open(path); rhughes@241: } rhughes@241: rhughes@241: struct razor_transaction * rhughes@241: razor_root_create_transaction(struct razor_root *image, rhughes@241: struct razor_set *upstream) rhughes@241: { rhughes@241: /* FIXME: This should take a number of upstream repos. */ rhughes@241: return razor_transaction_create(image->system, upstream); rhughes@241: } rhughes@241: rhughes@241: int rhughes@241: razor_root_close(struct razor_root *image) rhughes@241: { rhughes@241: unlink(image->new_path); rhughes@241: close(image->fd); rhughes@241: free(image); rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: void rhughes@241: razor_root_update(struct razor_root *root, struct razor_set *next) rhughes@241: { rhughes@241: razor_set_write_to_fd(next, root->fd); rhughes@241: root->next = next; rhughes@241: rhughes@241: /* Sync the new repo file so the new package set is on disk rhughes@241: * before we start upgrading. */ rhughes@241: fsync(root->fd); rhughes@241: printf("wrote %s\n", root->new_path); rhughes@241: } rhughes@241: rhughes@241: int rhughes@241: razor_root_commit(struct razor_root *image) rhughes@241: { rhughes@241: /* Make it so. */ rhughes@241: rename(image->new_path, image->path); rhughes@241: printf("renamed %s to %s\n", image->new_path, image->path); rhughes@241: close(image->fd); rhughes@241: free(image); rhughes@241: rhughes@241: return 0; rhughes@241: } rhughes@241: rhughes@241: void rhughes@241: razor_root_diff(struct razor_root *root, rhughes@241: razor_package_callback_t callback, void *data) rhughes@241: { rhughes@241: return razor_set_diff(root->system, root->next, callback, data); rhughes@241: }