librazor/root.c
author James Bowes <jbowes@redhat.com>
Wed Jul 09 10:11:13 2008 -0400 (2008-07-09)
changeset 318 829d6711b316
parent 315 1c52b84bfc33
child 325 73393734833c
permissions -rw-r--r--
Use strings to identify section types in the on-disk repo format.

Previously, a given razor file type had a fixed number of sections in a
fixed order, identified by an integer type. Now, sections are identified
by a named string (stored in a string pool after the section lists).

This will allow for razor files to contain arbitrary sections.

For bonus points, also drop the 4k section alignment and change the
magic byte string to "RZDB".

committer: Kristian H?gsberg <krh@redhat.com>
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License as published by
     7  * the Free Software Foundation; either version 2 of the License, or
     8  * (at your option) any later version.
     9  *
    10  * This program is distributed in the hope that it will be useful,
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  * GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along
    16  * with this program; if not, write to the Free Software Foundation, Inc.,
    17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18  */
    19 
    20 #include <stdlib.h>
    21 #include <stdint.h>
    22 #include <stdio.h>
    23 #include <string.h>
    24 #include <sys/stat.h>
    25 #include <dirent.h>
    26 #include <unistd.h>
    27 #include <fcntl.h>
    28 #include <assert.h>
    29 
    30 #include "razor.h"
    31 #include "razor-internal.h"
    32 
    33 static const char system_repo_filename[] = "system.rzdb";
    34 static const char system_repo_details_filename[] = "system-details.rzdb";
    35 static const char system_repo_files_filename[] = "system-files.rzdb";
    36 
    37 static const char next_repo_filename[] = "system-next.rzdb";
    38 static const char razor_root_path[] = "/var/lib/razor";
    39 
    40 struct razor_root {
    41 	struct razor_set *system;
    42 	struct razor_set *next;
    43 	int fd;
    44 	char root[PATH_MAX];
    45 	char path[PATH_MAX];
    46 	char new_path[PATH_MAX];
    47 };
    48 
    49 RAZOR_EXPORT int
    50 razor_root_create(const char *root)
    51 {
    52 	struct stat buf;
    53 	struct razor_set *set;
    54 	char path[PATH_MAX], details_path[PATH_MAX], files_path[PATH_MAX];
    55 
    56 	assert (root != NULL);
    57 
    58 	if (root[0] == '\0') {
    59 		/* root is file system root */
    60 	} else if (stat(root, &buf) < 0) {
    61 		if (mkdir(root, 0777) < 0) {
    62 			fprintf(stderr,
    63 				"could not create install root \"%s\"\n",
    64 				root);
    65 			return -1;
    66 		}
    67 		fprintf(stderr, "created install root \"%s\"\n", root);
    68 	} else if (!S_ISDIR(buf.st_mode)) {
    69 		fprintf(stderr,
    70 			"install root \"%s\" exists, but is not a directory\n",
    71 			root);
    72 		return -1;
    73 	}
    74 
    75 	snprintf(path, sizeof path, "%s/%s",
    76 		 razor_root_path, system_repo_filename);
    77 	if (razor_create_dir(root, path) < 0) {
    78 		fprintf(stderr, "could not create %s%s\n",
    79 			root, razor_root_path);
    80 		return -1;
    81 	}
    82 
    83 	set = razor_set_create();
    84 	snprintf(path, sizeof path, "%s%s/%s",
    85 		 root, razor_root_path, system_repo_filename);
    86 	snprintf(details_path, sizeof details_path, "%s%s/%s",
    87 		 root, razor_root_path, system_repo_details_filename);
    88 	snprintf(files_path, sizeof files_path, "%s%s/%s",
    89 		 root, razor_root_path, system_repo_files_filename);
    90 	if (stat(path, &buf) == 0) {
    91 		fprintf(stderr,
    92 			"a razor install root is already initialized\n");
    93 		return -1;
    94 	}
    95 	if (razor_set_write(set, path, RAZOR_REPO_FILE_MAIN) < 0 ||
    96 	    razor_set_write(set, details_path, RAZOR_REPO_FILE_DETAILS) < 0 ||
    97 	    razor_set_write(set, files_path, RAZOR_REPO_FILE_FILES) < 0 ) {
    98 		fprintf(stderr, "could not write initial package set\n");
    99 		return -1;
   100 	}
   101 	razor_set_destroy(set);
   102 
   103 	return 0;
   104 }
   105 
   106 RAZOR_EXPORT struct razor_root *
   107 razor_root_open(const char *root)
   108 {
   109 	struct razor_root *image;
   110 	char details_path[PATH_MAX], files_path[PATH_MAX];
   111 
   112 	assert (root != NULL);
   113 
   114 	image = malloc(sizeof *image);
   115 	if (image == NULL)
   116 		return NULL;
   117 
   118 	/* Create the new next repo file up front to ensure exclusive
   119 	 * access. */
   120 	snprintf(image->new_path, sizeof image->new_path,
   121 		 "%s%s/%s", root, razor_root_path, next_repo_filename);
   122 	image->fd = open(image->new_path,
   123 			 O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
   124 	if (image->fd < 0) {
   125 		fprintf(stderr, "failed to get lock file, "
   126 			"maybe previous operation crashed?\n");
   127 
   128 		/* FIXME: Use fcntl advisory locking on the system
   129 		 * package set file to figure out whether previous
   130 		 * operation crashed or is still in progress. */
   131 
   132 		free(image);
   133 		return NULL;
   134 	}
   135 
   136 	snprintf(image->path, sizeof image->path,
   137 		 "%s%s/%s", root, razor_root_path, system_repo_filename);
   138 	snprintf(details_path, sizeof details_path,
   139 		 "%s%s/%s", root, razor_root_path, system_repo_details_filename);
   140 	snprintf(files_path, sizeof files_path,
   141 		 "%s%s/%s", root, razor_root_path, system_repo_files_filename);
   142 
   143 	/* FIXME: We store the root path to make the hack in
   144 	 * razor_root_update() work.  Need to get rid of this. */
   145 	strcpy(image->root, root);
   146 
   147 	image->system = razor_set_open(image->path);
   148 	if (image->system == NULL ||
   149 	    razor_set_open_details(image->system, details_path) ||
   150 	    razor_set_open_files(image->system, files_path)) {
   151 		unlink(image->new_path);
   152 		close(image->fd);
   153 		free(image);
   154 		return NULL;
   155 	}
   156 
   157 	return image;
   158 }
   159 
   160 RAZOR_EXPORT struct razor_set *
   161 razor_root_open_read_only(const char *root)
   162 {
   163 	char path[PATH_MAX], details_path[PATH_MAX], files_path[PATH_MAX];
   164 	struct razor_set *set;
   165 
   166 	assert (root != NULL);
   167 
   168 	snprintf(path, sizeof path, "%s%s/%s",
   169 		 root, razor_root_path, system_repo_filename);
   170 	snprintf(details_path, sizeof details_path,
   171 		 "%s%s/%s", root, razor_root_path, system_repo_details_filename);
   172 	snprintf(files_path, sizeof files_path,
   173 		 "%s%s/%s", root, razor_root_path, system_repo_files_filename);
   174 
   175 
   176 	set = razor_set_open(path);
   177 	if (set == NULL)
   178 		return NULL;
   179 
   180 	if (razor_set_open_details(set, details_path) ||
   181 	    razor_set_open_files(set, files_path)) {
   182 		razor_set_destroy(set);
   183 		return NULL;
   184 	}
   185 
   186 	return set;
   187 }
   188 
   189 RAZOR_EXPORT struct razor_set *
   190 razor_root_get_system_set(struct razor_root *root)
   191 {
   192 	assert (root != NULL);
   193 
   194 	return root->system;
   195 }
   196 
   197 RAZOR_EXPORT int
   198 razor_root_close(struct razor_root *root)
   199 {
   200 	assert (root != NULL);
   201 
   202 	razor_set_destroy(root->system);
   203 	unlink(root->new_path);
   204 	close(root->fd);
   205 	free(root);
   206 
   207 	return 0;
   208 }
   209 
   210 RAZOR_EXPORT void
   211 razor_root_update(struct razor_root *root, struct razor_set *next)
   212 {
   213 	char path[PATH_MAX];
   214 
   215 	assert (root != NULL);
   216 	assert (next != NULL);
   217 
   218 	razor_set_write_to_fd(next, root->fd, RAZOR_REPO_FILE_MAIN);
   219 	root->next = next;
   220 
   221 	/* FIXME: This is a pretty bad hack that just overwrites the
   222 	 * system details and files rzdb files before the transaction
   223 	 * succeeds.  We need to fix this by merging the separate
   224 	 * details and files rzdb files back into the main rzdb
   225 	 * file. */
   226 	snprintf(path, sizeof path,
   227 		 "%s%s/%s", root->root, razor_root_path, system_repo_details_filename);
   228 	razor_set_write(next, path, RAZOR_REPO_FILE_DETAILS);
   229 	snprintf(path, sizeof path,
   230 		 "%s%s/%s", root->root, razor_root_path, system_repo_files_filename);
   231 	razor_set_write(next, path, RAZOR_REPO_FILE_FILES);
   232 
   233 	/* Sync the new repo file so the new package set is on disk
   234 	 * before we start upgrading. */
   235 	fsync(root->fd);
   236 	printf("wrote %s\n", root->new_path);
   237 }
   238 
   239 RAZOR_EXPORT int
   240 razor_root_commit(struct razor_root *root)
   241 {
   242 	assert (root != NULL);
   243 
   244 	/* Make it so. */
   245 	rename(root->new_path, root->path);
   246 	printf("renamed %s to %s\n", root->new_path, root->path);
   247 	razor_set_destroy(root->system);
   248 	close(root->fd);
   249 	free(root);
   250 
   251 	return 0;
   252 }