librazor/root.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 09 17:27:41 2014 +0100 (2014-10-09)
changeset 455 df914f383f5c
parent 445 aada48958b92
child 475 008c75a5e08d
permissions -rw-r--r--
Support downloading from local repository even without libcurl

Using the --url option of the razor executable, it is possible
to specify a yum repository on the local machine (eg., on installation
media) and import from there, eg.,:

C> razor --url file:///d:/ import-yum

This will be handled by libcurl if available but if not, an internal
copy routine will be used.

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