librazor/root.c
author J. Ali Harlow <ali@juiblex.co.uk>
Tue Sep 09 15:04:24 2014 +0100 (2014-09-09)
changeset 446 4277359896dc
parent 441 cf499fd51df7
child 447 0a5e583393e1
permissions -rw-r--r--
Add razor_transaction_unsatisfied()
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>
krh@248
    27
#include <sys/stat.h>
krh@248
    28
#include <dirent.h>
krh@248
    29
#include <unistd.h>
krh@248
    30
#include <fcntl.h>
ali@325
    31
#include <limits.h>
richard@301
    32
#include <assert.h>
ali@340
    33
#ifdef MSWIN_API
ali@340
    34
#include <shlobj.h>
ali@340
    35
#endif
richard@301
    36
krh@248
    37
#include "razor.h"
krh@248
    38
#include "razor-internal.h"
krh@248
    39
ali@345
    40
#ifndef O_BINARY
ali@345
    41
#define O_BINARY	0
ali@345
    42
#endif
ali@345
    43
ali@445
    44
#ifndef FALSE
ali@445
    45
#define FALSE 0
ali@445
    46
#endif
ali@445
    47
ali@445
    48
#ifndef TRUE
ali@445
    49
#define TRUE (!FALSE)
ali@445
    50
#endif
ali@445
    51
richard@310
    52
static const char system_repo_filename[] = "system.rzdb";
ali@388
    53
/*
ali@388
    54
 * system_lock_filename is chosen to be the same as the pre v0.3
ali@388
    55
 * next_repo_filename. This means that once a system has been
ali@388
    56
 * updated by a v0.3+ copy of razor all pre v0.3 versions of razor
ali@388
    57
 * will see the system as permenantly locked.
ali@388
    58
 */
ali@388
    59
static const char system_lock_filename[] = "system-next.rzdb";
ali@340
    60
#ifdef MSWIN_API
ali@445
    61
#define RAZOR_DATABASE_PATH	NULL
ali@340
    62
#else
ali@445
    63
#define RAZOR_DATABASE_PATH	"/var/lib/razor"
ali@340
    64
#endif
ali@445
    65
static char *razor_database_path = RAZOR_DATABASE_PATH;
ali@445
    66
static int razor_database_path_alloced = FALSE;
krh@248
    67
krh@248
    68
struct razor_root {
krh@248
    69
	struct razor_set *system;
ali@424
    70
	char *path;
krh@248
    71
};
krh@248
    72
ali@340
    73
static void
ali@340
    74
razor_root_init(void)
ali@340
    75
{
ali@340
    76
#ifdef MSWIN_API
ali@445
    77
	static char database_path[MAX_PATH];
ali@445
    78
	if (!razor_database_path) {
ali@340
    79
		SHGetFolderPath(NULL,
ali@340
    80
			CSIDL_COMMON_APPDATA | CSIDL_FLAG_DONT_VERIFY, NULL, 0,
ali@445
    81
			database_path);
ali@445
    82
		strcat(database_path, "\\Razor");
ali@445
    83
		razor_database_path = database_path;
ali@445
    84
		razor_database_path_alloced = FALSE;
ali@340
    85
	}
ali@340
    86
#endif
ali@340
    87
}
ali@340
    88
ali@445
    89
RAZOR_EXPORT const char *
ali@445
    90
razor_get_database_path()
ali@445
    91
{
ali@445
    92
	razor_root_init();
ali@445
    93
ali@445
    94
	return razor_database_path;
ali@445
    95
}
ali@445
    96
ali@445
    97
RAZOR_EXPORT void
ali@445
    98
razor_set_database_path(const char *database_path)
ali@445
    99
{
ali@445
   100
	if (razor_database_path_alloced)
ali@445
   101
		free(razor_database_path);
ali@445
   102
ali@445
   103
	if (database_path) {
ali@445
   104
		razor_database_path = strdup(database_path);
ali@445
   105
		razor_database_path_alloced = TRUE;
ali@445
   106
	} else {
ali@445
   107
		razor_database_path = RAZOR_DATABASE_PATH;
ali@445
   108
		razor_database_path_alloced = FALSE;
ali@445
   109
	}
ali@445
   110
}
ali@445
   111
krh@269
   112
RAZOR_EXPORT int
ali@425
   113
razor_root_create(const char *root, struct razor_error **error)
krh@248
   114
{
ali@403
   115
	int retval;
krh@248
   116
	struct stat buf;
krh@248
   117
	struct razor_set *set;
ali@403
   118
	struct razor_atomic *atomic;
ali@406
   119
	char *file, *path;
krh@248
   120
richard@301
   121
	assert (root != NULL);
richard@301
   122
ali@340
   123
	razor_root_init();
krh@317
   124
	if (root[0] == '\0') {
krh@317
   125
		/* root is file system root */
krh@317
   126
	} else if (stat(root, &buf) < 0) {
krh@248
   127
		if (mkdir(root, 0777) < 0) {
ali@425
   128
			razor_set_error(error, root,
ali@425
   129
					"Could not create install root");
krh@248
   130
			return -1;
krh@248
   131
		}
krh@248
   132
	} else if (!S_ISDIR(buf.st_mode)) {
ali@425
   133
		razor_set_error(error, root, "Not a directory");
krh@248
   134
		return -1;
krh@248
   135
	}
krh@248
   136
ali@445
   137
	file = razor_concat(razor_database_path, "/", system_repo_filename,
ali@445
   138
			    NULL);
ali@441
   139
	path = razor_path_add_root(file, root);
ali@403
   140
	retval = !stat(path, &buf);
ali@403
   141
	if (retval) {
ali@425
   142
		razor_set_error(error, NULL,
ali@425
   143
				"A razor install root is already initialized");
ali@406
   144
		free(path);
ali@406
   145
		free(file);
ali@403
   146
		return retval;
krh@248
   147
	}
krh@248
   148
ali@403
   149
	atomic = razor_atomic_open("Create initial package set");
ali@406
   150
	razor_atomic_make_dirs(atomic, root, file);
krh@248
   151
	set = razor_set_create();
ali@403
   152
	razor_set_write(set, atomic, path, RAZOR_SECTION_ALL);
ali@403
   153
	free(path);
ali@406
   154
	free(file);
ali@403
   155
	retval = razor_atomic_commit(atomic);
ali@403
   156
	if (retval)
ali@439
   157
		razor_propagate_error(error,
ali@439
   158
				      razor_atomic_get_error(atomic),
ali@439
   159
				      "Could not write initial package set");
ali@403
   160
	razor_set_unref(set);
ali@403
   161
	razor_atomic_destroy(atomic);
krh@248
   162
ali@403
   163
	return retval;
krh@248
   164
}
krh@248
   165
krh@269
   166
RAZOR_EXPORT struct razor_root *
ali@424
   167
razor_root_open(const char *root, struct razor_error **error)
krh@248
   168
{
krh@248
   169
	struct razor_root *image;
ali@441
   170
	char *s, *lock_path;
ali@403
   171
	int r;
krh@248
   172
richard@301
   173
	assert (root != NULL);
richard@301
   174
ali@340
   175
	razor_root_init();
krh@248
   176
	image = malloc(sizeof *image);
ali@403
   177
	if (image == NULL) {
ali@424
   178
		razor_set_error(error, NULL, "Not enough memory");
krh@248
   179
		return NULL;
ali@403
   180
	}
ali@403
   181
ali@388
   182
	image->system = razor_set_create_without_root();
ali@388
   183
	if (image->system == NULL) {
ali@388
   184
		free(image);
ali@424
   185
		razor_set_error(error, NULL, "Not enough memory");
ali@388
   186
		return NULL;
ali@388
   187
	}
ali@388
   188
ali@445
   189
	s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
ali@441
   190
	lock_path = razor_path_add_root(s, root);
ali@441
   191
	free(s);
ali@388
   192
ali@403
   193
	r = razor_set_aquire_lock(image->system, lock_path, 1);
ali@403
   194
ali@403
   195
	free(lock_path);
ali@403
   196
ali@403
   197
	if (r < 0) {
ali@424
   198
		razor_set_error(error, NULL,
ali@424
   199
				"Failed to aquire exclusive system lock");
ali@403
   200
		razor_set_unref(image->system);
krh@248
   201
		free(image);
krh@248
   202
		return NULL;
krh@248
   203
	}
krh@248
   204
ali@445
   205
	s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
ali@441
   206
	image->path = razor_path_add_root(s, root);
ali@441
   207
	free(s);
krh@317
   208
ali@424
   209
	if (razor_set_bind_sections(image->system, image->path,
ali@424
   210
				    RAZOR_SET_PRIVATE, error)) {
ali@403
   211
		free(image->path);
ali@403
   212
		razor_set_unref(image->system);
krh@248
   213
		free(image);
krh@248
   214
		return NULL;
krh@248
   215
	}
krh@248
   216
krh@248
   217
	return image;
krh@248
   218
}
krh@248
   219
krh@269
   220
RAZOR_EXPORT struct razor_set *
ali@424
   221
razor_root_open_read_only(const char *root, struct razor_error **error)
krh@248
   222
{
ali@441
   223
	char *s, *path;
ali@388
   224
	struct razor_set *set;
krh@248
   225
richard@301
   226
	assert (root != NULL);
richard@301
   227
ali@340
   228
	razor_root_init();
ali@388
   229
	set = razor_set_create_without_root();
ali@403
   230
	if (set == NULL) {
ali@424
   231
		razor_set_error(error, NULL, "Not enough memory");
ali@388
   232
		return NULL;
ali@388
   233
	}
ali@388
   234
ali@445
   235
	s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
ali@441
   236
	path = razor_path_add_root(s, root);
ali@441
   237
	free(s);
ali@441
   238
ali@403
   239
	if (razor_set_aquire_lock(set, path, 0) < 0) {
ali@424
   240
		razor_set_error(error, NULL,
ali@424
   241
				"Failed to aquire non-exclusive system lock");
ali@403
   242
		free(path);
ali@403
   243
		razor_set_unref(set);
ali@388
   244
		return NULL;
ali@388
   245
	}
ali@388
   246
ali@403
   247
	free(path);
ali@441
   248
ali@445
   249
	s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
ali@441
   250
	path = razor_path_add_root(s, root);
ali@441
   251
	free(s);
ali@403
   252
ali@424
   253
	if (razor_set_bind_sections(set, path, 0, error)) {
ali@403
   254
		razor_set_unref(set);
ali@403
   255
		set = NULL;
ali@403
   256
	}
ali@403
   257
ali@403
   258
	free(path);
ali@403
   259
ali@388
   260
	return set;
krh@248
   261
}
krh@248
   262
krh@269
   263
RAZOR_EXPORT struct razor_set *
krh@250
   264
razor_root_get_system_set(struct razor_root *root)
krh@248
   265
{
richard@301
   266
	assert (root != NULL);
richard@301
   267
krh@250
   268
	return root->system;
krh@248
   269
}
krh@248
   270
krh@269
   271
RAZOR_EXPORT int
krh@250
   272
razor_root_close(struct razor_root *root)
krh@248
   273
{
richard@301
   274
	assert (root != NULL);
richard@301
   275
ali@403
   276
	razor_set_unref(root->system);
ali@403
   277
	free(root->path);
krh@250
   278
	free(root);
krh@248
   279
krh@248
   280
	return 0;
krh@248
   281
}
krh@248
   282
ali@424
   283
RAZOR_EXPORT int
ali@424
   284
razor_root_update(struct razor_root *root, struct razor_set *next,
ali@424
   285
		  struct razor_atomic *atomic)
krh@248
   286
{
ali@424
   287
	int handle, retval;
ali@424
   288
richard@301
   289
	assert (root != NULL);
richard@301
   290
	assert (next != NULL);
richard@301
   291
ali@424
   292
	handle = razor_atomic_create_file(atomic, root->path,
ali@424
   293
					  S_IRWXU | S_IRWXG | S_IRWXO);
ali@424
   294
	if (handle < 0)
ali@424
   295
		return handle;
krh@248
   296
ali@424
   297
	razor_set_write_to_handle(next, atomic, handle, RAZOR_SECTION_ALL);
krh@248
   298
ali@424
   299
	retval = razor_atomic_close(atomic, handle);
richard@301
   300
ali@424
   301
	if (!retval) {
ali@424
   302
		razor_set_unref(root->system);
ali@424
   303
		root->system = razor_set_ref(next);
ali@424
   304
	}
krh@248
   305
ali@346
   306
	return retval;
krh@248
   307
}