librazor/root.c
author Kristian H?gsberg <krh@redhat.com>
Fri Jun 20 22:27:07 2008 -0400 (2008-06-20)
changeset 256 3603b635d6c9
parent 248 057933050c42
child 259 5b0601d184ed
permissions -rw-r--r--
Call exit() instead of just returning if child fails.
     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 }