librazor/root.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri Oct 17 09:57:19 2014 +0100 (2014-10-17)
changeset 456 bae5adee8c8c
parent 445 aada48958b92
child 475 008c75a5e08d
permissions -rw-r--r--
Add facility to specify razor command when running tests.

This makes it easy to run under eg., valgrind as:

./details "libtool --mode=execute valgrind --leak-check=yes ../src/razor"
richard@300
     1
/*
richard@300
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
richard@300
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@445
     4
 * Copyright (C) 2009, 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
richard@300
     5
 *
richard@300
     6
 * This program is free software; you can redistribute it and/or modify
richard@300
     7
 * it under the terms of the GNU General Public License as published by
richard@300
     8
 * the Free Software Foundation; either version 2 of the License, or
richard@300
     9
 * (at your option) any later version.
richard@300
    10
 *
richard@300
    11
 * This program is distributed in the hope that it will be useful,
richard@300
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
richard@300
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
richard@300
    14
 * GNU General Public License for more details.
richard@300
    15
 *
richard@300
    16
 * You should have received a copy of the GNU General Public License along
richard@300
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
richard@300
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
richard@300
    19
 */
richard@300
    20
ali@340
    21
#include "config.h"
ali@340
    22
krh@248
    23
#include <stdlib.h>
krh@248
    24
#include <stdint.h>
krh@248
    25
#include <stdio.h>
krh@317
    26
#include <string.h>
ali@447
    27
#include <errno.h>
krh@248
    28
#include <sys/stat.h>
krh@248
    29
#include <dirent.h>
krh@248
    30
#include <unistd.h>
krh@248
    31
#include <fcntl.h>
ali@325
    32
#include <limits.h>
richard@301
    33
#include <assert.h>
ali@340
    34
#ifdef MSWIN_API
ali@340
    35
#include <shlobj.h>
ali@340
    36
#endif
richard@301
    37
krh@248
    38
#include "razor.h"
krh@248
    39
#include "razor-internal.h"
krh@248
    40
ali@345
    41
#ifndef O_BINARY
ali@345
    42
#define O_BINARY	0
ali@345
    43
#endif
ali@345
    44
ali@445
    45
#ifndef FALSE
ali@445
    46
#define FALSE 0
ali@445
    47
#endif
ali@445
    48
ali@445
    49
#ifndef TRUE
ali@445
    50
#define TRUE (!FALSE)
ali@445
    51
#endif
ali@445
    52
richard@310
    53
static const char system_repo_filename[] = "system.rzdb";
ali@388
    54
/*
ali@388
    55
 * system_lock_filename is chosen to be the same as the pre v0.3
ali@388
    56
 * next_repo_filename. This means that once a system has been
ali@388
    57
 * updated by a v0.3+ copy of razor all pre v0.3 versions of razor
ali@388
    58
 * will see the system as permenantly locked.
ali@388
    59
 */
ali@388
    60
static const char system_lock_filename[] = "system-next.rzdb";
ali@340
    61
#ifdef MSWIN_API
ali@445
    62
#define RAZOR_DATABASE_PATH	NULL
ali@340
    63
#else
ali@445
    64
#define RAZOR_DATABASE_PATH	"/var/lib/razor"
ali@340
    65
#endif
ali@445
    66
static char *razor_database_path = RAZOR_DATABASE_PATH;
ali@445
    67
static int razor_database_path_alloced = FALSE;
krh@248
    68
krh@248
    69
struct razor_root {
krh@248
    70
	struct razor_set *system;
ali@424
    71
	char *path;
krh@248
    72
};
krh@248
    73
ali@340
    74
static void
ali@340
    75
razor_root_init(void)
ali@340
    76
{
ali@340
    77
#ifdef MSWIN_API
ali@445
    78
	static char database_path[MAX_PATH];
ali@445
    79
	if (!razor_database_path) {
ali@340
    80
		SHGetFolderPath(NULL,
ali@340
    81
			CSIDL_COMMON_APPDATA | CSIDL_FLAG_DONT_VERIFY, NULL, 0,
ali@445
    82
			database_path);
ali@445
    83
		strcat(database_path, "\\Razor");
ali@445
    84
		razor_database_path = database_path;
ali@445
    85
		razor_database_path_alloced = FALSE;
ali@340
    86
	}
ali@340
    87
#endif
ali@340
    88
}
ali@340
    89
ali@445
    90
RAZOR_EXPORT const char *
ali@445
    91
razor_get_database_path()
ali@445
    92
{
ali@445
    93
	razor_root_init();
ali@445
    94
ali@445
    95
	return razor_database_path;
ali@445
    96
}
ali@445
    97
ali@445
    98
RAZOR_EXPORT void
ali@445
    99
razor_set_database_path(const char *database_path)
ali@445
   100
{
ali@445
   101
	if (razor_database_path_alloced)
ali@445
   102
		free(razor_database_path);
ali@445
   103
ali@445
   104
	if (database_path) {
ali@445
   105
		razor_database_path = strdup(database_path);
ali@445
   106
		razor_database_path_alloced = TRUE;
ali@445
   107
	} else {
ali@445
   108
		razor_database_path = RAZOR_DATABASE_PATH;
ali@445
   109
		razor_database_path_alloced = FALSE;
ali@445
   110
	}
ali@445
   111
}
ali@445
   112
krh@269
   113
RAZOR_EXPORT int
ali@425
   114
razor_root_create(const char *root, struct razor_error **error)
krh@248
   115
{
ali@403
   116
	int retval;
krh@248
   117
	struct stat buf;
krh@248
   118
	struct razor_set *set;
ali@403
   119
	struct razor_atomic *atomic;
ali@406
   120
	char *file, *path;
krh@248
   121
richard@301
   122
	assert (root != NULL);
richard@301
   123
ali@340
   124
	razor_root_init();
krh@317
   125
	if (root[0] == '\0') {
krh@317
   126
		/* root is file system root */
krh@317
   127
	} else if (stat(root, &buf) < 0) {
krh@248
   128
		if (mkdir(root, 0777) < 0) {
ali@447
   129
			razor_set_error(error, RAZOR_POSIX_ERROR, errno, root,
ali@425
   130
					"Could not create install root");
krh@248
   131
			return -1;
krh@248
   132
		}
krh@248
   133
	} else if (!S_ISDIR(buf.st_mode)) {
ali@447
   134
		razor_set_error(error, RAZOR_POSIX_ERROR, ENOTDIR, root,
ali@447
   135
				"Not a directory");
krh@248
   136
		return -1;
krh@248
   137
	}
krh@248
   138
ali@445
   139
	file = razor_concat(razor_database_path, "/", system_repo_filename,
ali@445
   140
			    NULL);
ali@441
   141
	path = razor_path_add_root(file, root);
ali@403
   142
	retval = !stat(path, &buf);
ali@403
   143
	if (retval) {
ali@447
   144
		razor_set_error(error, RAZOR_GENERAL_ERROR,
ali@447
   145
				RAZOR_GENERAL_ERROR_DATABASE_EXISTS, NULL,
ali@425
   146
				"A razor install root is already initialized");
ali@406
   147
		free(path);
ali@406
   148
		free(file);
ali@403
   149
		return retval;
krh@248
   150
	}
krh@248
   151
ali@403
   152
	atomic = razor_atomic_open("Create initial package set");
ali@406
   153
	razor_atomic_make_dirs(atomic, root, file);
krh@248
   154
	set = razor_set_create();
ali@403
   155
	razor_set_write(set, atomic, path, RAZOR_SECTION_ALL);
ali@403
   156
	free(path);
ali@406
   157
	free(file);
ali@403
   158
	retval = razor_atomic_commit(atomic);
ali@403
   159
	if (retval)
ali@439
   160
		razor_propagate_error(error,
ali@439
   161
				      razor_atomic_get_error(atomic),
ali@439
   162
				      "Could not write initial package set");
ali@403
   163
	razor_set_unref(set);
ali@403
   164
	razor_atomic_destroy(atomic);
krh@248
   165
ali@403
   166
	return retval;
krh@248
   167
}
krh@248
   168
krh@269
   169
RAZOR_EXPORT struct razor_root *
ali@424
   170
razor_root_open(const char *root, struct razor_error **error)
krh@248
   171
{
krh@248
   172
	struct razor_root *image;
ali@441
   173
	char *s, *lock_path;
ali@403
   174
	int r;
krh@248
   175
richard@301
   176
	assert (root != NULL);
richard@301
   177
ali@340
   178
	razor_root_init();
krh@248
   179
	image = malloc(sizeof *image);
ali@403
   180
	if (image == NULL) {
ali@447
   181
		razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
ali@447
   182
				"Not enough memory");
krh@248
   183
		return NULL;
ali@403
   184
	}
ali@403
   185
ali@388
   186
	image->system = razor_set_create_without_root();
ali@388
   187
	if (image->system == NULL) {
ali@388
   188
		free(image);
ali@447
   189
		razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
ali@447
   190
				"Not enough memory");
ali@388
   191
		return NULL;
ali@388
   192
	}
ali@388
   193
ali@445
   194
	s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
ali@441
   195
	lock_path = razor_path_add_root(s, root);
ali@441
   196
	free(s);
ali@388
   197
ali@403
   198
	r = razor_set_aquire_lock(image->system, lock_path, 1);
ali@403
   199
ali@403
   200
	free(lock_path);
ali@403
   201
ali@403
   202
	if (r < 0) {
ali@447
   203
		razor_set_error(error, RAZOR_GENERAL_ERROR,
ali@447
   204
				RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
ali@424
   205
				"Failed to aquire exclusive system lock");
ali@403
   206
		razor_set_unref(image->system);
krh@248
   207
		free(image);
krh@248
   208
		return NULL;
krh@248
   209
	}
krh@248
   210
ali@445
   211
	s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
ali@441
   212
	image->path = razor_path_add_root(s, root);
ali@441
   213
	free(s);
krh@317
   214
ali@424
   215
	if (razor_set_bind_sections(image->system, image->path,
ali@424
   216
				    RAZOR_SET_PRIVATE, error)) {
ali@403
   217
		free(image->path);
ali@403
   218
		razor_set_unref(image->system);
krh@248
   219
		free(image);
krh@248
   220
		return NULL;
krh@248
   221
	}
krh@248
   222
krh@248
   223
	return image;
krh@248
   224
}
krh@248
   225
krh@269
   226
RAZOR_EXPORT struct razor_set *
ali@424
   227
razor_root_open_read_only(const char *root, struct razor_error **error)
krh@248
   228
{
ali@441
   229
	char *s, *path;
ali@388
   230
	struct razor_set *set;
krh@248
   231
richard@301
   232
	assert (root != NULL);
richard@301
   233
ali@340
   234
	razor_root_init();
ali@388
   235
	set = razor_set_create_without_root();
ali@403
   236
	if (set == NULL) {
ali@447
   237
		razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
ali@447
   238
				"Not enough memory");
ali@388
   239
		return NULL;
ali@388
   240
	}
ali@388
   241
ali@445
   242
	s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
ali@441
   243
	path = razor_path_add_root(s, root);
ali@441
   244
	free(s);
ali@441
   245
ali@403
   246
	if (razor_set_aquire_lock(set, path, 0) < 0) {
ali@447
   247
		razor_set_error(error, RAZOR_GENERAL_ERROR,
ali@447
   248
				RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
ali@424
   249
				"Failed to aquire non-exclusive system lock");
ali@403
   250
		free(path);
ali@403
   251
		razor_set_unref(set);
ali@388
   252
		return NULL;
ali@388
   253
	}
ali@388
   254
ali@403
   255
	free(path);
ali@441
   256
ali@445
   257
	s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
ali@441
   258
	path = razor_path_add_root(s, root);
ali@441
   259
	free(s);
ali@403
   260
ali@424
   261
	if (razor_set_bind_sections(set, path, 0, error)) {
ali@403
   262
		razor_set_unref(set);
ali@403
   263
		set = NULL;
ali@403
   264
	}
ali@403
   265
ali@403
   266
	free(path);
ali@403
   267
ali@388
   268
	return set;
krh@248
   269
}
krh@248
   270
krh@269
   271
RAZOR_EXPORT struct razor_set *
krh@250
   272
razor_root_get_system_set(struct razor_root *root)
krh@248
   273
{
richard@301
   274
	assert (root != NULL);
richard@301
   275
krh@250
   276
	return root->system;
krh@248
   277
}
krh@248
   278
krh@269
   279
RAZOR_EXPORT int
krh@250
   280
razor_root_close(struct razor_root *root)
krh@248
   281
{
richard@301
   282
	assert (root != NULL);
richard@301
   283
ali@403
   284
	razor_set_unref(root->system);
ali@403
   285
	free(root->path);
krh@250
   286
	free(root);
krh@248
   287
krh@248
   288
	return 0;
krh@248
   289
}
krh@248
   290
ali@424
   291
RAZOR_EXPORT int
ali@424
   292
razor_root_update(struct razor_root *root, struct razor_set *next,
ali@424
   293
		  struct razor_atomic *atomic)
krh@248
   294
{
ali@424
   295
	int handle, retval;
ali@424
   296
richard@301
   297
	assert (root != NULL);
richard@301
   298
	assert (next != NULL);
richard@301
   299
ali@424
   300
	handle = razor_atomic_create_file(atomic, root->path,
ali@424
   301
					  S_IRWXU | S_IRWXG | S_IRWXO);
ali@424
   302
	if (handle < 0)
ali@424
   303
		return handle;
krh@248
   304
ali@424
   305
	razor_set_write_to_handle(next, atomic, handle, RAZOR_SECTION_ALL);
krh@248
   306
ali@424
   307
	retval = razor_atomic_close(atomic, handle);
richard@301
   308
ali@424
   309
	if (!retval) {
ali@424
   310
		razor_set_unref(root->system);
ali@424
   311
		root->system = razor_set_ref(next);
ali@424
   312
	}
krh@248
   313
ali@346
   314
	return retval;
krh@248
   315
}