/* * Copyright (C) 2008 Kristian Høgsberg * Copyright (C) 2008 Red Hat, Inc * Copyright (C) 2009, 2011, 2012 J. Ali Harlow * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef MSWIN_API #include #endif #include "razor.h" #include "razor-internal.h" #ifndef O_BINARY #define O_BINARY 0 #endif static const char system_repo_filename[] = "system.rzdb"; /* * system_lock_filename is chosen to be the same as the pre v0.3 * next_repo_filename. This means that once a system has been * updated by a v0.3+ copy of razor all pre v0.3 versions of razor * will see the system as permenantly locked. */ static const char system_lock_filename[] = "system-next.rzdb"; #ifdef MSWIN_API #define RAZOR_ROOT_PATH NULL #else #define RAZOR_ROOT_PATH "/var/lib/razor" #endif static const char *razor_root_path = RAZOR_ROOT_PATH; struct razor_root { struct razor_set *system; char *path; }; static void razor_root_init(void) { #ifdef MSWIN_API static char root_path[MAX_PATH]; if (!razor_root_path) { SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_DONT_VERIFY, NULL, 0, root_path); strcat(root_path, "\\Razor"); razor_root_path = root_path; } #endif } RAZOR_EXPORT int razor_root_create(const char *root, struct razor_error **error) { int retval; struct stat buf; struct razor_set *set; struct razor_atomic *atomic; char *file, *path; assert (root != NULL); razor_root_init(); if (root[0] == '\0') { /* root is file system root */ } else if (stat(root, &buf) < 0) { if (mkdir(root, 0777) < 0) { razor_set_error(error, root, "Could not create install root"); return -1; } } else if (!S_ISDIR(buf.st_mode)) { razor_set_error(error, root, "Not a directory"); return -1; } file = razor_concat(razor_root_path, "/", system_repo_filename, NULL); path = razor_concat(root, file, NULL); retval = !stat(path, &buf); if (retval) { razor_set_error(error, NULL, "A razor install root is already initialized"); free(path); free(file); return retval; } atomic = razor_atomic_open("Create initial package set"); razor_atomic_make_dirs(atomic, root, file); set = razor_set_create(); razor_set_write(set, atomic, path, RAZOR_SECTION_ALL); free(path); free(file); retval = razor_atomic_commit(atomic); if (retval) razor_set_error(error, NULL, "Could not write initial package set"); razor_set_unref(set); razor_atomic_destroy(atomic); return retval; } RAZOR_EXPORT struct razor_root * razor_root_open(const char *root, struct razor_error **error) { struct razor_root *image; char *lock_path; int r; assert (root != NULL); razor_root_init(); image = malloc(sizeof *image); if (image == NULL) { razor_set_error(error, NULL, "Not enough memory"); return NULL; } image->system = razor_set_create_without_root(); if (image->system == NULL) { free(image); razor_set_error(error, NULL, "Not enough memory"); return NULL; } lock_path = razor_concat(root, razor_root_path, "/", system_lock_filename, NULL); r = razor_set_aquire_lock(image->system, lock_path, 1); free(lock_path); if (r < 0) { razor_set_error(error, NULL, "Failed to aquire exclusive system lock"); razor_set_unref(image->system); free(image); return NULL; } image->path = razor_concat(root, razor_root_path, "/", system_repo_filename, NULL); if (razor_set_bind_sections(image->system, image->path, RAZOR_SET_PRIVATE, error)) { free(image->path); razor_set_unref(image->system); free(image); return NULL; } return image; } RAZOR_EXPORT struct razor_set * razor_root_open_read_only(const char *root, struct razor_error **error) { char *path; struct razor_set *set; assert (root != NULL); razor_root_init(); set = razor_set_create_without_root(); if (set == NULL) { razor_set_error(error, NULL, "Not enough memory"); return NULL; } path = razor_concat(root, razor_root_path, "/", system_lock_filename, NULL); if (razor_set_aquire_lock(set, path, 0) < 0) { razor_set_error(error, NULL, "Failed to aquire non-exclusive system lock"); free(path); razor_set_unref(set); return NULL; } free(path); path = razor_concat(root, razor_root_path, "/", system_repo_filename, NULL); if (razor_set_bind_sections(set, path, 0, error)) { razor_set_unref(set); set = NULL; } free(path); return set; } RAZOR_EXPORT struct razor_set * razor_root_get_system_set(struct razor_root *root) { assert (root != NULL); return root->system; } RAZOR_EXPORT int razor_root_close(struct razor_root *root) { assert (root != NULL); razor_set_unref(root->system); free(root->path); free(root); return 0; } RAZOR_EXPORT int razor_root_update(struct razor_root *root, struct razor_set *next, struct razor_atomic *atomic) { int handle, retval; assert (root != NULL); assert (next != NULL); handle = razor_atomic_create_file(atomic, root->path, S_IRWXU | S_IRWXG | S_IRWXO); if (handle < 0) return handle; razor_set_write_to_handle(next, atomic, handle, RAZOR_SECTION_ALL); retval = razor_atomic_close(atomic, handle); if (!retval) { razor_set_unref(root->system); root->system = razor_set_ref(next); } return retval; }