librazor/razor-root.c
changeset 242 f2218527ad4a
child 243 f37f5f4a2403
     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 +}