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