librazor/root.c
changeset 485 5e309e37906e
parent 447 0a5e583393e1
child 499 c89e5edb8eae
     1.1 --- a/librazor/root.c	Tue Sep 09 15:27:12 2014 +0100
     1.2 +++ b/librazor/root.c	Fri Jul 08 17:52:02 2016 +0100
     1.3 @@ -1,7 +1,7 @@
     1.4  /*
     1.5   * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     1.6   * Copyright (C) 2008  Red Hat, Inc
     1.7 - * Copyright (C) 2009, 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
     1.8 + * Copyright (C) 2009, 2011, 2012, 2014, 2016  J. Ali Harlow <ali@juiblex.co.uk>
     1.9   *
    1.10   * This program is free software; you can redistribute it and/or modify
    1.11   * it under the terms of the GNU General Public License as published by
    1.12 @@ -25,7 +25,6 @@
    1.13  #include <stdio.h>
    1.14  #include <string.h>
    1.15  #include <errno.h>
    1.16 -#include <sys/stat.h>
    1.17  #include <dirent.h>
    1.18  #include <unistd.h>
    1.19  #include <fcntl.h>
    1.20 @@ -59,102 +58,130 @@
    1.21   */
    1.22  static const char system_lock_filename[] = "system-next.rzdb";
    1.23  #ifdef MSWIN_API
    1.24 -#define RAZOR_DATABASE_PATH	NULL
    1.25 +#define RAZOR_DATABASE_URI	NULL
    1.26  #else
    1.27 -#define RAZOR_DATABASE_PATH	"/var/lib/razor"
    1.28 +/*
    1.29 + * The non-MSWIN default is a relative-ref and thus affected by the root
    1.30 + */
    1.31 +#define RAZOR_DATABASE_URI	"var/lib/razor"
    1.32  #endif
    1.33 -static char *razor_database_path = RAZOR_DATABASE_PATH;
    1.34 -static int razor_database_path_alloced = FALSE;
    1.35 +static char *razor_database_uri = RAZOR_DATABASE_URI;
    1.36 +static int razor_database_uri_alloced = FALSE;
    1.37  
    1.38  struct razor_root {
    1.39  	struct razor_set *system;
    1.40 -	char *path;
    1.41 +	char *uri;
    1.42  };
    1.43  
    1.44  static void
    1.45  razor_root_init(void)
    1.46  {
    1.47  #ifdef MSWIN_API
    1.48 -	static char database_path[MAX_PATH];
    1.49 -	if (!razor_database_path) {
    1.50 +	/*
    1.51 +	 * The MSWIN default is an absolute-URI and thus unaffected by the root
    1.52 +	 */
    1.53 +	char database_path[MAX_PATH];
    1.54 +	if (!razor_database_uri) {
    1.55  		SHGetFolderPath(NULL,
    1.56  			CSIDL_COMMON_APPDATA | CSIDL_FLAG_DONT_VERIFY, NULL, 0,
    1.57  			database_path);
    1.58  		strcat(database_path, "\\Razor");
    1.59 -		razor_database_path = database_path;
    1.60 -		razor_database_path_alloced = FALSE;
    1.61 +		razor_database_uri = razor_path_to_uri(database_path);
    1.62 +		razor_database_uri_alloced = TRUE;
    1.63  	}
    1.64  #endif
    1.65  }
    1.66  
    1.67 -RAZOR_EXPORT const char *
    1.68 -razor_get_database_path()
    1.69 +RAZOR_EXPORT const char *razor_get_database_uri(void)
    1.70  {
    1.71  	razor_root_init();
    1.72 -
    1.73 -	return razor_database_path;
    1.74 +	return razor_database_uri;
    1.75  }
    1.76  
    1.77  RAZOR_EXPORT void
    1.78 -razor_set_database_path(const char *database_path)
    1.79 +razor_set_database_uri(const char *database_uri)
    1.80  {
    1.81 -	if (razor_database_path_alloced)
    1.82 -		free(razor_database_path);
    1.83 +	if (razor_database_uri_alloced)
    1.84 +		free(razor_database_uri);
    1.85  
    1.86 -	if (database_path) {
    1.87 -		razor_database_path = strdup(database_path);
    1.88 -		razor_database_path_alloced = TRUE;
    1.89 +	if (database_uri) {
    1.90 +		razor_database_uri = strdup(database_uri);
    1.91 +		razor_database_uri_alloced = TRUE;
    1.92  	} else {
    1.93 -		razor_database_path = RAZOR_DATABASE_PATH;
    1.94 -		razor_database_path_alloced = FALSE;
    1.95 +		razor_database_uri = RAZOR_DATABASE_URI;
    1.96 +		razor_database_uri_alloced = FALSE;
    1.97  	}
    1.98  }
    1.99  
   1.100 +char *razor_resolve_database_file(const char *root_uri, const char *filename,
   1.101 +				  struct razor_error **error)
   1.102 +{
   1.103 +	char *s, *uri;
   1.104 +
   1.105 +	razor_root_init();
   1.106 +
   1.107 +	s = razor_concat(razor_database_uri, "/", filename, NULL);
   1.108 +
   1.109 +	uri = razor_resolve_uri_root(root_uri, s, -1, error);
   1.110 +
   1.111 +	free(s);
   1.112 +
   1.113 +	return uri;
   1.114 +}
   1.115 +
   1.116  RAZOR_EXPORT int
   1.117 -razor_root_create(const char *root, struct razor_error **error)
   1.118 +razor_root_create(const char *root_uri, struct razor_error **error)
   1.119  {
   1.120 -	int retval;
   1.121 -	struct stat buf;
   1.122 +	int retval, is_within_root, is_directory;
   1.123  	struct razor_set *set;
   1.124  	struct razor_atomic *atomic;
   1.125 -	char *file, *path;
   1.126 +	struct razor_error *tmp_err = NULL;
   1.127 +	char *uri;
   1.128  
   1.129 -	assert (root != NULL);
   1.130 +	uri = razor_resolve_database_file(root_uri, system_repo_filename,
   1.131 +					  error);
   1.132  
   1.133 -	razor_root_init();
   1.134 -	if (root[0] == '\0') {
   1.135 -		/* root is file system root */
   1.136 -	} else if (stat(root, &buf) < 0) {
   1.137 -		if (mkdir(root, 0777) < 0) {
   1.138 -			razor_set_error(error, RAZOR_POSIX_ERROR, errno, root,
   1.139 +	if (!uri)
   1.140 +		return -1;
   1.141 +
   1.142 +	if (razor_uri_is_directory(uri, NULL) >= 0) {
   1.143 +		razor_set_error(error, RAZOR_GENERAL_ERROR,
   1.144 +				RAZOR_GENERAL_ERROR_DATABASE_EXISTS, NULL,
   1.145 +				"A razor install root is already initialized");
   1.146 +		free(uri);
   1.147 +		return -1;
   1.148 +	}
   1.149 +
   1.150 +	is_within_root = root_uri && strchr(root_uri, '/') &&
   1.151 +			 str_has_prefix(uri, root_uri);
   1.152 +
   1.153 +	atomic = razor_atomic_open("Create initial package set");
   1.154 +
   1.155 +	if (is_within_root) {
   1.156 +		is_directory = razor_uri_is_directory(root_uri, NULL);
   1.157 +
   1.158 +		if (!is_directory) {
   1.159 +			razor_set_error(error, RAZOR_POSIX_ERROR, ENOTDIR,
   1.160 +					root_uri, "Not a directory");
   1.161 +			return -1;
   1.162 +		} else if (is_directory < 0 &&
   1.163 +			   razor_uri_mkdir(root_uri, 0777, &tmp_err) < 0) {
   1.164 +			razor_set_error(error,
   1.165 +					razor_error_get_domain(tmp_err),
   1.166 +					razor_error_get_code(tmp_err),
   1.167 +					root_uri,
   1.168  					"Could not create install root");
   1.169  			return -1;
   1.170  		}
   1.171 -	} else if (!S_ISDIR(buf.st_mode)) {
   1.172 -		razor_set_error(error, RAZOR_POSIX_ERROR, ENOTDIR, root,
   1.173 -				"Not a directory");
   1.174 -		return -1;
   1.175 -	}
   1.176  
   1.177 -	file = razor_concat(razor_database_path, "/", system_repo_filename,
   1.178 -			    NULL);
   1.179 -	path = razor_path_add_root(file, root);
   1.180 -	retval = !stat(path, &buf);
   1.181 -	if (retval) {
   1.182 -		razor_set_error(error, RAZOR_GENERAL_ERROR,
   1.183 -				RAZOR_GENERAL_ERROR_DATABASE_EXISTS, NULL,
   1.184 -				"A razor install root is already initialized");
   1.185 -		free(path);
   1.186 -		free(file);
   1.187 -		return retval;
   1.188 -	}
   1.189 +		razor_atomic_make_dirs(atomic, root_uri,
   1.190 +				       uri + strlen(root_uri));
   1.191 +	} else
   1.192 +		razor_atomic_make_dirs(atomic, "", uri);
   1.193  
   1.194 -	atomic = razor_atomic_open("Create initial package set");
   1.195 -	razor_atomic_make_dirs(atomic, root, file);
   1.196  	set = razor_set_create();
   1.197 -	razor_set_write(set, atomic, path, RAZOR_SECTION_ALL);
   1.198 -	free(path);
   1.199 -	free(file);
   1.200 +	razor_set_write(set, atomic, uri, RAZOR_SECTION_ALL);
   1.201 +	free(uri);
   1.202  	retval = razor_atomic_commit(atomic);
   1.203  	if (retval)
   1.204  		razor_propagate_error(error,
   1.205 @@ -167,17 +194,21 @@
   1.206  }
   1.207  
   1.208  RAZOR_EXPORT struct razor_root *
   1.209 -razor_root_open(const char *root, struct razor_error **error)
   1.210 +razor_root_open(const char *root_uri, struct razor_error **error)
   1.211  {
   1.212  	struct razor_root *image;
   1.213 -	char *s, *lock_path;
   1.214 +	char *lock_uri;
   1.215  	int r;
   1.216  
   1.217 -	assert (root != NULL);
   1.218 +	lock_uri = razor_resolve_database_file(root_uri, system_lock_filename,
   1.219 +					       error);
   1.220  
   1.221 -	razor_root_init();
   1.222 +	if (!lock_uri)
   1.223 +		return NULL;
   1.224 +
   1.225  	image = malloc(sizeof *image);
   1.226  	if (image == NULL) {
   1.227 +		free(lock_uri);
   1.228  		razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
   1.229  				"Not enough memory");
   1.230  		return NULL;
   1.231 @@ -186,35 +217,37 @@
   1.232  	image->system = razor_set_create_without_root();
   1.233  	if (image->system == NULL) {
   1.234  		free(image);
   1.235 +		free(lock_uri);
   1.236  		razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
   1.237  				"Not enough memory");
   1.238  		return NULL;
   1.239  	}
   1.240  
   1.241 -	s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
   1.242 -	lock_path = razor_path_add_root(s, root);
   1.243 -	free(s);
   1.244 +	r = razor_set_acquire_lock(image->system, lock_uri, 1);
   1.245  
   1.246 -	r = razor_set_aquire_lock(image->system, lock_path, 1);
   1.247 -
   1.248 -	free(lock_path);
   1.249 +	free(lock_uri);
   1.250  
   1.251  	if (r < 0) {
   1.252  		razor_set_error(error, RAZOR_GENERAL_ERROR,
   1.253  				RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
   1.254 -				"Failed to aquire exclusive system lock");
   1.255 +				"Failed to acquire exclusive system lock");
   1.256  		razor_set_unref(image->system);
   1.257  		free(image);
   1.258  		return NULL;
   1.259  	}
   1.260  
   1.261 -	s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
   1.262 -	image->path = razor_path_add_root(s, root);
   1.263 -	free(s);
   1.264 +	image->uri = razor_resolve_database_file(root_uri, system_repo_filename,
   1.265 +						 error);
   1.266  
   1.267 -	if (razor_set_bind_sections(image->system, image->path,
   1.268 +	if (!image->uri) {
   1.269 +		razor_set_unref(image->system);
   1.270 +		free(image);
   1.271 +		return NULL;
   1.272 +	}
   1.273 +
   1.274 +	if (razor_set_bind_sections(image->system, image->uri,
   1.275  				    RAZOR_SET_PRIVATE, error)) {
   1.276 -		free(image->path);
   1.277 +		free(image->uri);
   1.278  		razor_set_unref(image->system);
   1.279  		free(image);
   1.280  		return NULL;
   1.281 @@ -224,46 +257,47 @@
   1.282  }
   1.283  
   1.284  RAZOR_EXPORT struct razor_set *
   1.285 -razor_root_open_read_only(const char *root, struct razor_error **error)
   1.286 +razor_root_open_read_only(const char *root_uri, struct razor_error **error)
   1.287  {
   1.288 -	char *s, *path;
   1.289 +	int r;
   1.290 +	char *uri;
   1.291  	struct razor_set *set;
   1.292  
   1.293 -	assert (root != NULL);
   1.294 +	uri = razor_resolve_database_file(root_uri, system_lock_filename,
   1.295 +					  error);
   1.296  
   1.297 -	razor_root_init();
   1.298 +	if (!uri)
   1.299 +		return NULL;
   1.300 +
   1.301  	set = razor_set_create_without_root();
   1.302  	if (set == NULL) {
   1.303 +		free(uri);
   1.304  		razor_set_error(error, RAZOR_POSIX_ERROR, ENOMEM, NULL,
   1.305  				"Not enough memory");
   1.306  		return NULL;
   1.307  	}
   1.308  
   1.309 -	s = razor_concat(razor_database_path, "/", system_lock_filename, NULL);
   1.310 -	path = razor_path_add_root(s, root);
   1.311 -	free(s);
   1.312 +	r = razor_set_acquire_lock(set, uri, 0);
   1.313  
   1.314 -	if (razor_set_aquire_lock(set, path, 0) < 0) {
   1.315 +	free(uri);
   1.316 +
   1.317 +	if (r < 0) {
   1.318  		razor_set_error(error, RAZOR_GENERAL_ERROR,
   1.319  				RAZOR_GENERAL_ERROR_DATABASE_LOCKED, NULL,
   1.320 -				"Failed to aquire non-exclusive system lock");
   1.321 -		free(path);
   1.322 +				"Failed to acquire non-exclusive system lock");
   1.323  		razor_set_unref(set);
   1.324  		return NULL;
   1.325  	}
   1.326  
   1.327 -	free(path);
   1.328 +	uri = razor_resolve_database_file(root_uri, system_repo_filename,
   1.329 +					  error);
   1.330  
   1.331 -	s = razor_concat(razor_database_path, "/", system_repo_filename, NULL);
   1.332 -	path = razor_path_add_root(s, root);
   1.333 -	free(s);
   1.334 -
   1.335 -	if (razor_set_bind_sections(set, path, 0, error)) {
   1.336 +	if (!uri || razor_set_bind_sections(set, uri, 0, error)) {
   1.337  		razor_set_unref(set);
   1.338  		set = NULL;
   1.339  	}
   1.340  
   1.341 -	free(path);
   1.342 +	free(uri);
   1.343  
   1.344  	return set;
   1.345  }
   1.346 @@ -282,7 +316,7 @@
   1.347  	assert (root != NULL);
   1.348  
   1.349  	razor_set_unref(root->system);
   1.350 -	free(root->path);
   1.351 +	free(root->uri);
   1.352  	free(root);
   1.353  
   1.354  	return 0;
   1.355 @@ -297,7 +331,7 @@
   1.356  	assert (root != NULL);
   1.357  	assert (next != NULL);
   1.358  
   1.359 -	handle = razor_atomic_create_file(atomic, root->path,
   1.360 +	handle = razor_atomic_create_file(atomic, root->uri,
   1.361  					  S_IRWXU | S_IRWXG | S_IRWXO);
   1.362  	if (handle < 0)
   1.363  		return handle;