1.1 --- a/main.c Mon Jun 09 14:38:58 2008 -0400
1.2 +++ b/main.c Mon Jun 09 16:01:34 2008 -0400
1.3 @@ -563,6 +563,159 @@
1.4 return 0;
1.5 }
1.6
1.7 +/* The image data struct encapsulates filesystem conventions and the
1.8 + * locking protocol. FIXME: Should this be razor_root?*/
1.9 +struct razor_root {
1.10 + struct razor_set *system;
1.11 + int fd;
1.12 + char path[PATH_MAX];
1.13 + char new_path[PATH_MAX];
1.14 +};
1.15 +
1.16 +#define RAZOR_ROOT_OPEN_WRITE 0x01
1.17 +
1.18 +int
1.19 +razor_root_create(const char *root);
1.20 +struct razor_root *
1.21 +razor_root_open(const char *root, int flags);
1.22 +struct razor_transaction *
1.23 +razor_root_create_transaction(struct razor_root *image,
1.24 + struct razor_set *upstream);
1.25 +int
1.26 +razor_root_close(struct razor_root *image);
1.27 +void
1.28 +razor_root_update(struct razor_root *image, struct razor_set *next);
1.29 +int
1.30 +razor_root_commit(struct razor_root *image);
1.31 +
1.32 +int
1.33 +razor_root_create(const char *root)
1.34 +{
1.35 + struct stat buf;
1.36 + struct razor_set *set;
1.37 + char path[PATH_MAX];
1.38 +
1.39 + if (stat(root, &buf) < 0) {
1.40 + if (mkdir(root, 0777) < 0) {
1.41 + fprintf(stderr,
1.42 + "could not create install root \"%s\"\n",
1.43 + root);
1.44 + return -1;
1.45 + }
1.46 + fprintf(stderr, "created install root \"%s\"\n", root);
1.47 + } else if (!S_ISDIR(buf.st_mode)) {
1.48 + fprintf(stderr,
1.49 + "install root \"%s\" exists, but is not a directory\n",
1.50 + root);
1.51 + return -1;
1.52 + }
1.53 +
1.54 + snprintf(path, sizeof path, "%s/%s",
1.55 + razor_root_path, system_repo_filename);
1.56 + if (razor_create_dir(root, path) < 0) {
1.57 + fprintf(stderr, "could not create %s%s\n",
1.58 + root, razor_root_path);
1.59 + return -1;
1.60 + }
1.61 +
1.62 + set = razor_set_create();
1.63 + snprintf(path, sizeof path, "%s%s/%s",
1.64 + root, razor_root_path, system_repo_filename);
1.65 + if (stat(root, &buf) == 0) {
1.66 + fprintf(stderr,
1.67 + "a razor install root is already initialized\n");
1.68 + return -1;
1.69 + }
1.70 + if (razor_set_write(set, path) < 0) {
1.71 + fprintf(stderr, "could not write initial package set\n");
1.72 + return -1;
1.73 + }
1.74 + razor_set_destroy(set);
1.75 +
1.76 + return 0;
1.77 +}
1.78 +
1.79 +struct razor_root *
1.80 +razor_root_open(const char *root, int flags)
1.81 +{
1.82 + struct razor_root *image;
1.83 +
1.84 + image = malloc(sizeof *image);
1.85 + if (image == NULL)
1.86 + return NULL;
1.87 +
1.88 + /* Create the new next repo file up front to ensure exclusive
1.89 + * access. */
1.90 + snprintf(image->new_path, sizeof image->new_path,
1.91 + "%s%s/%s", root, root, next_repo_filename);
1.92 + image->fd = open(image->new_path,
1.93 + O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
1.94 + if (image->fd < 0) {
1.95 + fprintf(stderr, "failed to get lock file, "
1.96 + "maybe previous operation crashed?\n");
1.97 +
1.98 + /* FIXME: Use fcntl advisory locking on the system
1.99 + * package set file to figure out whether previous
1.100 + * operation crashed or is still in progress. */
1.101 +
1.102 + free(image);
1.103 + return NULL;
1.104 + }
1.105 +
1.106 + snprintf(image->path, sizeof image->path,
1.107 + "%s%s/%s", root, razor_root_path, system_repo_filename);
1.108 + image->system = razor_set_open(image->path);
1.109 + if (image->system == NULL) {
1.110 + unlink(image->new_path);
1.111 + close(image->fd);
1.112 + free(image);
1.113 + return NULL;
1.114 + }
1.115 +
1.116 + return image;
1.117 +}
1.118 +
1.119 +struct razor_transaction *
1.120 +razor_root_create_transaction(struct razor_root *image,
1.121 + struct razor_set *upstream)
1.122 +{
1.123 + /* FIXME: This should take a number of upstream repos. */
1.124 + return razor_transaction_create(image->system, upstream);
1.125 +}
1.126 +
1.127 +int
1.128 +razor_root_close(struct razor_root *image)
1.129 +{
1.130 + unlink(image->new_path);
1.131 + close(image->fd);
1.132 + free(image);
1.133 +
1.134 + return 0;
1.135 +}
1.136 +
1.137 +void
1.138 +razor_root_update(struct razor_root *image, struct razor_set *next)
1.139 +{
1.140 + razor_set_write_to_fd(next, image->fd);
1.141 +
1.142 + /* Sync the new repo file so the new package set is on disk
1.143 + * before we start upgrading. */
1.144 + fsync(image->fd);
1.145 + printf("wrote %s\n", image->new_path);
1.146 +}
1.147 +
1.148 +int
1.149 +razor_root_commit(struct razor_root *image)
1.150 +{
1.151 + /* Make it so. */
1.152 + rename(image->new_path, image->path);
1.153 + printf("renamed %s to %s\n", image->new_path, image->path);
1.154 + close(image->fd);
1.155 + free(image);
1.156 +
1.157 + return 0;
1.158 +}
1.159 +
1.160 static void
1.161 download_package(const char *name,
1.162 const char *old_version,
1.163 @@ -634,45 +787,24 @@
1.164 static int
1.165 command_install(int argc, const char *argv[])
1.166 {
1.167 - struct razor_set *system, *upstream, *next;
1.168 + struct razor_root *root;
1.169 + struct razor_set *upstream, *next;
1.170 struct razor_transaction *trans;
1.171 - char path[PATH_MAX], new_path[PATH_MAX];
1.172 - int i = 0, errors, fd, dependencies = 1;
1.173 + int i = 0, errors, dependencies = 1;
1.174
1.175 if (i < argc && strcmp(argv[i], "--no-dependencies") == 0) {
1.176 dependencies = 0;
1.177 i++;
1.178 }
1.179
1.180 - /* Create the new next repo file up front to ensure exclusive
1.181 - * access. */
1.182 - snprintf(new_path, sizeof new_path,
1.183 - "%s%s/%s", root, razor_root_path, next_repo_filename);
1.184 - fd = open(new_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
1.185 - if (fd < 0) {
1.186 - fprintf(stderr, "failed to get lock file, "
1.187 - "maybe previous operation crashed?\n");
1.188 + root = razor_root_open(razor_root_path, RAZOR_ROOT_OPEN_WRITE);
1.189 + upstream = razor_set_open(rawhide_repo_filename);
1.190 + trans = razor_root_create_transaction(root, upstream);
1.191
1.192 - /* FIXME: Use fcntl advisory locking to figure out
1.193 - * whether previous operation crashed or is still in
1.194 - * progress. */
1.195 -
1.196 - return -1;
1.197 - }
1.198 -
1.199 - upstream = razor_set_open(rawhide_repo_filename);
1.200 - snprintf(path, sizeof path,
1.201 - "%s%s/%s", root, razor_root_path, system_repo_filename);
1.202 - system = razor_set_open(path);
1.203 - if (system == NULL || upstream == NULL) {
1.204 - unlink(new_path);
1.205 - return 1;
1.206 - }
1.207 - trans = razor_transaction_create(system, upstream);
1.208 for (; i < argc; i++) {
1.209 if (mark_packages_for_update(trans, upstream, argv[i]) == 0) {
1.210 fprintf(stderr, "no package matched %s\n", argv[i]);
1.211 - unlink(new_path);
1.212 + razor_root_close(root);
1.213 return 1;
1.214 }
1.215 }
1.216 @@ -680,83 +812,42 @@
1.217 if (dependencies) {
1.218 errors = razor_transaction_resolve(trans);
1.219 if (errors) {
1.220 - unlink(new_path);
1.221 + razor_root_close(root);
1.222 return 1;
1.223 }
1.224 }
1.225
1.226 next = razor_transaction_finish(trans);
1.227
1.228 - razor_set_write_to_fd(next, fd);
1.229 - printf("wrote %s\n", new_path);
1.230 + razor_root_update(root, next);
1.231
1.232 if (mkdir("rpms", 0777) && errno != EEXIST) {
1.233 fprintf(stderr, "failed to create rpms directory.\n");
1.234 + razor_root_close(root);
1.235 return 1;
1.236 }
1.237
1.238 - razor_set_diff(system, next, download_package, &errors);
1.239 + razor_set_diff(root->system, next, download_package, &errors);
1.240 if (errors > 0) {
1.241 fprintf(stderr, "failed to download %d packages\n", errors);
1.242 - unlink(new_path);
1.243 + razor_root_close(root);
1.244 return 1;
1.245 }
1.246
1.247 /* FIXME: We need to figure out the right install order here,
1.248 * so the post and pre scripts can run. */
1.249 - razor_set_diff(system, next, install_package, (void *) root);
1.250 + razor_set_diff(root->system, next, install_package, (void *) root);
1.251
1.252 razor_set_destroy(next);
1.253 - razor_set_destroy(system);
1.254 razor_set_destroy(upstream);
1.255
1.256 - /* Make it so. */
1.257 - rename(new_path, path);
1.258 - printf("renamed %s to %s\n", new_path, path);
1.259 -
1.260 - return 0;
1.261 + return razor_root_commit(root);
1.262 }
1.263
1.264 static int
1.265 command_init(int argc, const char *argv[])
1.266 {
1.267 - struct stat buf;
1.268 - struct razor_set *set;
1.269 - char path[PATH_MAX];
1.270 -
1.271 - if (stat(root, &buf) < 0) {
1.272 - if (mkdir(root, 0777) < 0) {
1.273 - fprintf(stderr,
1.274 - "could not create install root \"%s\"\n",
1.275 - root);
1.276 - return -1;
1.277 - }
1.278 - fprintf(stderr, "created install root \"%s\"\n", root);
1.279 - } else if (!S_ISDIR(buf.st_mode)) {
1.280 - fprintf(stderr,
1.281 - "install root \"%s\" exists, but is not a directory\n",
1.282 - root);
1.283 - return -1;
1.284 - }
1.285 -
1.286 - snprintf(path, sizeof path, "%s/%s",
1.287 - razor_root_path, system_repo_filename);
1.288 - if (razor_create_dir(root, path) < 0) {
1.289 - fprintf(stderr, "could not create %s%s\n",
1.290 - root, razor_root_path);
1.291 - return -1;
1.292 - }
1.293 -
1.294 - set = razor_set_create();
1.295 - snprintf(path, sizeof path, "%s%s/%s",
1.296 - root, razor_root_path, system_repo_filename);
1.297 - if (razor_set_write(set, path) < 0) {
1.298 - fprintf(stderr, "could not write initial package set\n");
1.299 - return -1;
1.300 - }
1.301 - razor_set_destroy(set);
1.302 -
1.303 - return 0;
1.304 + return razor_root_create(root);
1.305 }
1.306
1.307 static int