main.c
changeset 232 2389f44500bb
parent 231 fef9808171ff
child 234 7f5d32472bef
     1.1 --- a/main.c	Mon Jun 09 14:38:58 2008 -0400
     1.2 +++ b/main.c	Mon Jun 09 15:39:23 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