librazor/root.c
author Kristian H?gsberg <krh@redhat.com>
Fri Jun 20 21:56:43 2008 -0400 (2008-06-20)
changeset 254 ccb1c11968ab
parent 248 057933050c42
child 259 5b0601d184ed
permissions -rw-r--r--
Introduce install/remove iterators.

These iterator constructors lets you pass in two sets and creates
an iterator for the packages to remove or the packages to install.
The iterators will step through the packages in a sequence that respects
the pre, post, preun and postun modifiers.

Right now, the install order isn't actually implemented, this patch just
implements the API changes and updates the applications.
     1 #include <stdlib.h>
     2 #include <stdint.h>
     3 #include <stdio.h>
     4 #include <sys/stat.h>
     5 #include <dirent.h>
     6 #include <unistd.h>
     7 #include <fcntl.h>
     8 #include "razor.h"
     9 #include "razor-internal.h"
    10 
    11 static const char system_repo_filename[] = "system.repo";
    12 static const char next_repo_filename[] = "system-next.repo";
    13 static const char razor_root_path[] = "/var/lib/razor";
    14 
    15 struct razor_root {
    16 	struct razor_set *system;
    17 	struct razor_set *next;
    18 	int fd;
    19 	char path[PATH_MAX];
    20 	char new_path[PATH_MAX];
    21 };
    22 
    23 int
    24 razor_root_create(const char *root)
    25 {
    26 	struct stat buf;
    27 	struct razor_set *set;
    28 	char path[PATH_MAX];
    29 
    30 	if (stat(root, &buf) < 0) {
    31 		if (mkdir(root, 0777) < 0) {
    32 			fprintf(stderr,
    33 				"could not create install root \"%s\"\n",
    34 				root);
    35 			return -1;
    36 		}
    37 		fprintf(stderr, "created install root \"%s\"\n", root);
    38 	} else if (!S_ISDIR(buf.st_mode)) {
    39 		fprintf(stderr,
    40 			"install root \"%s\" exists, but is not a directory\n",
    41 			root);
    42 		return -1;
    43 	}
    44 
    45 	snprintf(path, sizeof path, "%s/%s",
    46 		 razor_root_path, system_repo_filename);
    47 	if (razor_create_dir(root, path) < 0) {
    48 		fprintf(stderr, "could not create %s%s\n",
    49 			root, razor_root_path);
    50 		return -1;
    51 	}
    52 
    53 	set = razor_set_create();
    54 	snprintf(path, sizeof path, "%s%s/%s",
    55 		 root, razor_root_path, system_repo_filename);
    56 	if (stat(path, &buf) == 0) {
    57 		fprintf(stderr,
    58 			"a razor install root is already initialized\n");
    59 		return -1;
    60 	}
    61 	if (razor_set_write(set, path) < 0) {
    62 		fprintf(stderr, "could not write initial package set\n");
    63 		return -1;
    64 	}
    65 	razor_set_destroy(set);
    66 
    67 	return 0;
    68 }
    69 
    70 struct razor_root *
    71 razor_root_open(const char *root)
    72 {
    73 	struct razor_root *image;
    74 
    75 	image = malloc(sizeof *image);
    76 	if (image == NULL)
    77 		return NULL;
    78 
    79 	/* Create the new next repo file up front to ensure exclusive
    80 	 * access. */
    81 	snprintf(image->new_path, sizeof image->new_path,
    82 		 "%s%s/%s", root, razor_root_path, next_repo_filename);
    83 	image->fd = open(image->new_path,
    84 			 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
    85 	if (image->fd < 0) {
    86 		fprintf(stderr, "failed to get lock file, "
    87 			"maybe previous operation crashed?\n");
    88 
    89 		/* FIXME: Use fcntl advisory locking on the system
    90 		 * package set file to figure out whether previous
    91 		 * operation crashed or is still in progress. */
    92 
    93 		free(image);
    94 		return NULL;
    95 	}
    96 
    97 	snprintf(image->path, sizeof image->path,
    98 		 "%s%s/%s", root, razor_root_path, system_repo_filename);
    99 	image->system = razor_set_open(image->path);
   100 	if (image->system == NULL) {
   101 		unlink(image->new_path);
   102 		close(image->fd);
   103 		free(image);
   104 		return NULL;
   105 	}
   106 
   107 	return image;
   108 }
   109 
   110 struct razor_set *
   111 razor_root_open_read_only(const char *root)
   112 {
   113 	char path[PATH_MAX];
   114 
   115 	snprintf(path, sizeof path, "%s%s/%s",
   116 		 root, razor_root_path, system_repo_filename);
   117 
   118 	return razor_set_open(path);
   119 }
   120 
   121 struct razor_set *
   122 razor_root_get_system_set(struct razor_root *root)
   123 {
   124 	return root->system;
   125 }
   126 
   127 int
   128 razor_root_close(struct razor_root *root)
   129 {
   130 	razor_set_destroy(root->system);
   131 	unlink(root->new_path);
   132 	close(root->fd);
   133 	free(root);
   134 
   135 	return 0;
   136 }
   137 
   138 void
   139 razor_root_update(struct razor_root *root, struct razor_set *next)
   140 {
   141 	razor_set_write_to_fd(next, root->fd);
   142 	root->next = next;
   143 
   144 	/* Sync the new repo file so the new package set is on disk
   145 	 * before we start upgrading. */
   146 	fsync(root->fd);
   147 	printf("wrote %s\n", root->new_path);
   148 }
   149 
   150 int
   151 razor_root_commit(struct razor_root *root)
   152 {
   153 	/* Make it so. */
   154 	rename(root->new_path, root->path);
   155 	printf("renamed %s to %s\n", root->new_path, root->path);
   156 	razor_set_destroy(root->system);
   157 	close(root->fd);
   158 	free(root);
   159 
   160 	return 0;
   161 }