1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/librazor/razor-root.c Mon Jun 16 17:54:29 2008 -0400
1.3 @@ -0,0 +1,168 @@
1.4 +#include <stdlib.h>
1.5 +#include <stdint.h>
1.6 +#include <stdio.h>
1.7 +#include <sys/stat.h>
1.8 +#include <dirent.h>
1.9 +#include <unistd.h>
1.10 +#include <fcntl.h>
1.11 +#include "razor.h"
1.12 +#include "razor-internal.h"
1.13 +
1.14 +static const char system_repo_filename[] = "system.repo";
1.15 +static const char next_repo_filename[] = "system-next.repo";
1.16 +static const char razor_root_path[] = "/var/lib/razor";
1.17 +
1.18 +struct razor_root {
1.19 + struct razor_set *system;
1.20 + struct razor_set *next;
1.21 + int fd;
1.22 + char path[PATH_MAX];
1.23 + char new_path[PATH_MAX];
1.24 +};
1.25 +
1.26 +int
1.27 +razor_root_create(const char *root)
1.28 +{
1.29 + struct stat buf;
1.30 + struct razor_set *set;
1.31 + char path[PATH_MAX];
1.32 +
1.33 + if (stat(root, &buf) < 0) {
1.34 + if (mkdir(root, 0777) < 0) {
1.35 + fprintf(stderr,
1.36 + "could not create install root \"%s\"\n",
1.37 + root);
1.38 + return -1;
1.39 + }
1.40 + fprintf(stderr, "created install root \"%s\"\n", root);
1.41 + } else if (!S_ISDIR(buf.st_mode)) {
1.42 + fprintf(stderr,
1.43 + "install root \"%s\" exists, but is not a directory\n",
1.44 + root);
1.45 + return -1;
1.46 + }
1.47 +
1.48 + snprintf(path, sizeof path, "%s/%s",
1.49 + razor_root_path, system_repo_filename);
1.50 + if (razor_create_dir(root, path) < 0) {
1.51 + fprintf(stderr, "could not create %s%s\n",
1.52 + root, razor_root_path);
1.53 + return -1;
1.54 + }
1.55 +
1.56 + set = razor_set_create();
1.57 + snprintf(path, sizeof path, "%s%s/%s",
1.58 + root, razor_root_path, system_repo_filename);
1.59 + if (stat(path, &buf) == 0) {
1.60 + fprintf(stderr,
1.61 + "a razor install root is already initialized\n");
1.62 + return -1;
1.63 + }
1.64 + if (razor_set_write(set, path) < 0) {
1.65 + fprintf(stderr, "could not write initial package set\n");
1.66 + return -1;
1.67 + }
1.68 + razor_set_destroy(set);
1.69 +
1.70 + return 0;
1.71 +}
1.72 +
1.73 +struct razor_root *
1.74 +razor_root_open(const char *root, int flags)
1.75 +{
1.76 + struct razor_root *image;
1.77 +
1.78 + image = malloc(sizeof *image);
1.79 + if (image == NULL)
1.80 + return NULL;
1.81 +
1.82 + /* Create the new next repo file up front to ensure exclusive
1.83 + * access. */
1.84 + snprintf(image->new_path, sizeof image->new_path,
1.85 + "%s%s/%s", root, root, next_repo_filename);
1.86 + image->fd = open(image->new_path,
1.87 + O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
1.88 + if (image->fd < 0) {
1.89 + fprintf(stderr, "failed to get lock file, "
1.90 + "maybe previous operation crashed?\n");
1.91 +
1.92 + /* FIXME: Use fcntl advisory locking on the system
1.93 + * package set file to figure out whether previous
1.94 + * operation crashed or is still in progress. */
1.95 +
1.96 + free(image);
1.97 + return NULL;
1.98 + }
1.99 +
1.100 + snprintf(image->path, sizeof image->path,
1.101 + "%s%s/%s", root, razor_root_path, system_repo_filename);
1.102 + image->system = razor_set_open(image->path);
1.103 + if (image->system == NULL) {
1.104 + unlink(image->new_path);
1.105 + close(image->fd);
1.106 + free(image);
1.107 + return NULL;
1.108 + }
1.109 +
1.110 + return image;
1.111 +}
1.112 +
1.113 +struct razor_set *
1.114 +razor_root_open_read_only(const char *root)
1.115 +{
1.116 + char path[PATH_MAX];
1.117 +
1.118 + snprintf(path, sizeof path, "%s%s/%s",
1.119 + root, razor_root_path, system_repo_filename);
1.120 +
1.121 + return razor_set_open(path);
1.122 +}
1.123 +
1.124 +struct razor_transaction *
1.125 +razor_root_create_transaction(struct razor_root *image,
1.126 + struct razor_set *upstream)
1.127 +{
1.128 + /* FIXME: This should take a number of upstream repos. */
1.129 + return razor_transaction_create(image->system, upstream);
1.130 +}
1.131 +
1.132 +int
1.133 +razor_root_close(struct razor_root *image)
1.134 +{
1.135 + unlink(image->new_path);
1.136 + close(image->fd);
1.137 + free(image);
1.138 +
1.139 + return 0;
1.140 +}
1.141 +
1.142 +void
1.143 +razor_root_update(struct razor_root *root, struct razor_set *next)
1.144 +{
1.145 + razor_set_write_to_fd(next, root->fd);
1.146 + root->next = next;
1.147 +
1.148 + /* Sync the new repo file so the new package set is on disk
1.149 + * before we start upgrading. */
1.150 + fsync(root->fd);
1.151 + printf("wrote %s\n", root->new_path);
1.152 +}
1.153 +
1.154 +int
1.155 +razor_root_commit(struct razor_root *image)
1.156 +{
1.157 + /* Make it so. */
1.158 + rename(image->new_path, image->path);
1.159 + printf("renamed %s to %s\n", image->new_path, image->path);
1.160 + close(image->fd);
1.161 + free(image);
1.162 +
1.163 + return 0;
1.164 +}
1.165 +
1.166 +void
1.167 +razor_root_diff(struct razor_root *root,
1.168 + razor_package_callback_t callback, void *data)
1.169 +{
1.170 + return razor_set_diff(root->system, root->next, callback, data);
1.171 +}