1.1 --- a/librazor/razor-internal.h Thu Oct 01 19:54:03 2009 +0100
1.2 +++ b/librazor/razor-internal.h Thu Oct 01 20:02:12 2009 +0100
1.3 @@ -119,6 +119,7 @@
1.4 struct array file_string_pool;
1.5 struct array details_string_pool;
1.6 struct razor_mapped_file *mapped_files;
1.7 + int lock_fd;
1.8 };
1.9
1.10 struct import_entry {
1.11 @@ -170,6 +171,9 @@
1.12 int post_order;
1.13 };
1.14
1.15 +int
1.16 +razor_set_aquire_lock(struct razor_set *set, const char *path, int exclusive);
1.17 +
1.18 struct razor_entry *
1.19 razor_set_find_entry(struct razor_set *set,
1.20 struct razor_entry *dir, const char *pattern);
2.1 --- a/librazor/razor.c Thu Oct 01 19:54:03 2009 +0100
2.2 +++ b/librazor/razor.c Thu Oct 01 20:02:12 2009 +0100
2.3 @@ -37,6 +37,9 @@
2.4 #include <fnmatch.h>
2.5 #include <limits.h>
2.6 #include <assert.h>
2.7 +#ifdef MSWIN_API
2.8 +#include <windows.h>
2.9 +#endif
2.10
2.11 #include "razor-internal.h"
2.12 #include "razor.h"
2.13 @@ -93,6 +96,8 @@
2.14 empty = array_add(&set->string_pool, 1);
2.15 *empty = '\0';
2.16
2.17 + set->lock_fd = -1;
2.18 +
2.19 return set;
2.20 }
2.21
2.22 @@ -138,6 +143,13 @@
2.23 return -1;
2.24 }
2.25
2.26 + if (set->mapped_files == NULL) {
2.27 + for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
2.28 + array = (void *) set + razor_sections[i].offset;
2.29 + array_release(array);
2.30 + }
2.31 + }
2.32 +
2.33 file->next = set->mapped_files;
2.34 set->mapped_files = file;
2.35
2.36 @@ -167,6 +179,7 @@
2.37 struct razor_set *set;
2.38
2.39 set = zalloc(sizeof *set);
2.40 + set->lock_fd = -1;
2.41 if (razor_set_bind_sections(set, filename)){
2.42 free(set);
2.43 return NULL;
2.44 @@ -174,6 +187,56 @@
2.45 return set;
2.46 }
2.47
2.48 +int
2.49 +razor_set_aquire_lock(struct razor_set *set, const char *path, int exclusive)
2.50 +{
2.51 + int fd;
2.52 + assert(set != NULL);
2.53 +
2.54 + if (path) {
2.55 + fd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0666);
2.56 + if (fd < 0)
2.57 + return -1;
2.58 + } else {
2.59 + fd = -1;
2.60 + }
2.61 +
2.62 +#ifdef MSWIN_API
2.63 + DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
2.64 + OVERLAPPED lock = {0};
2.65 +
2.66 + if (exclusive)
2.67 + flags |= LOCKFILE_EXCLUSIVE_LOCK;
2.68 + if (fd >= 0 && !LockFileEx(_get_osfhandle(fd), flags, 0, 1, 0, &lock)) {
2.69 + close(fd);
2.70 + return -1;
2.71 + }
2.72 + if (set->lock_fd >= 0)
2.73 + (void)UnlockFile(_get_osfhandle(set->lock_fd), 0, 0, 1, 0);
2.74 +#else
2.75 + struct flock lock = {0};
2.76 +
2.77 + lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
2.78 + lock.l_whence = SEEK_SET;
2.79 + lock.l_start = 0;
2.80 + lock.l_len = 0;
2.81 + if (fd >= 0 && fcntl(fd, F_SETLK, &lock) < 0) {
2.82 + close(fd);
2.83 + return -1;
2.84 + }
2.85 + if (set->lock_fd >= 0) {
2.86 + lock.l_type = F_UNLCK;
2.87 + (void)fcntl(set->lock_fd, F_SETLK, &lock);
2.88 + }
2.89 +#endif
2.90 +
2.91 + if (set->lock_fd >= 0)
2.92 + close(set->lock_fd);
2.93 + set->lock_fd = fd;
2.94 +
2.95 + return 0;
2.96 +}
2.97 +
2.98 RAZOR_EXPORT void
2.99 razor_set_destroy(struct razor_set *set)
2.100 {
2.101 @@ -196,6 +259,7 @@
2.102 }
2.103 }
2.104
2.105 + razor_set_aquire_lock(set, NULL, 0);
2.106 free(set);
2.107 }
2.108
3.1 --- a/librazor/root.c Thu Oct 01 19:54:03 2009 +0100
3.2 +++ b/librazor/root.c Thu Oct 01 20:02:12 2009 +0100
3.3 @@ -42,7 +42,14 @@
3.4 #endif
3.5
3.6 static const char system_repo_filename[] = "system.rzdb";
3.7 -static const char next_repo_filename[] = "system-next.rzdb";
3.8 +/*
3.9 + * system_lock_filename is chosen to be the same as the pre v0.3
3.10 + * next_repo_filename. This means that once a system has been
3.11 + * updated by a v0.3+ copy of razor all pre v0.3 versions of razor
3.12 + * will see the system as permenantly locked.
3.13 + */
3.14 +static const char system_lock_filename[] = "system-next.rzdb";
3.15 +static const char system_tmp_filename[] = "system.tmp";
3.16 #ifdef MSWIN_API
3.17 #define RAZOR_ROOT_PATH NULL
3.18 #else
3.19 @@ -129,6 +136,7 @@
3.20 razor_root_open(const char *root)
3.21 {
3.22 struct razor_root *image;
3.23 + char lock_path[PATH_MAX];
3.24
3.25 assert (root != NULL);
3.26
3.27 @@ -137,21 +145,28 @@
3.28 if (image == NULL)
3.29 return NULL;
3.30
3.31 - /* Create the new next repo file up front to ensure exclusive
3.32 - * access. */
3.33 + image->system = razor_set_create_without_root();
3.34 + if (image->system == NULL) {
3.35 + free(image);
3.36 + return NULL;
3.37 + }
3.38 +
3.39 + snprintf(lock_path, sizeof lock_path,
3.40 + "%s%s/%s", root, razor_root_path, system_lock_filename);
3.41 +
3.42 + if (razor_set_aquire_lock(image->system, lock_path, 1) < 0) {
3.43 + razor_set_destroy(image->system);
3.44 + free(image);
3.45 + return NULL;
3.46 + }
3.47 +
3.48 snprintf(image->new_path, sizeof image->new_path,
3.49 - "%s%s/%s", root, razor_root_path, next_repo_filename);
3.50 + "%s%s/%s", root, razor_root_path, system_tmp_filename);
3.51 image->fd = open(image->new_path,
3.52 - O_CREAT | O_WRONLY | O_TRUNC | O_EXCL | O_BINARY,
3.53 + O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
3.54 0666);
3.55 if (image->fd < 0) {
3.56 - fprintf(stderr, "failed to get lock file, "
3.57 - "maybe previous operation crashed?\n");
3.58 -
3.59 - /* FIXME: Use fcntl advisory locking on the system
3.60 - * package set file to figure out whether previous
3.61 - * operation crashed or is still in progress. */
3.62 -
3.63 + razor_set_destroy(image->system);
3.64 free(image);
3.65 return NULL;
3.66 }
3.67 @@ -159,10 +174,10 @@
3.68 snprintf(image->path, sizeof image->path,
3.69 "%s%s/%s", root, razor_root_path, system_repo_filename);
3.70
3.71 - image->system = razor_set_open(image->path);
3.72 - if (image->system == NULL) {
3.73 + if (razor_set_bind_sections(image->system, image->path)) {
3.74 + close(image->fd);
3.75 unlink(image->new_path);
3.76 - close(image->fd);
3.77 + razor_set_destroy(image->system);
3.78 free(image);
3.79 return NULL;
3.80 }
3.81 @@ -174,14 +189,31 @@
3.82 razor_root_open_read_only(const char *root)
3.83 {
3.84 char path[PATH_MAX];
3.85 + struct razor_set *set;
3.86
3.87 assert (root != NULL);
3.88
3.89 razor_root_init();
3.90 + set = razor_set_create_without_root();
3.91 + if (set == NULL)
3.92 + return NULL;
3.93 +
3.94 + snprintf(path, sizeof path,
3.95 + "%s%s/%s", root, razor_root_path, system_lock_filename);
3.96 + if (razor_set_aquire_lock(set, path, 0) < 0) {
3.97 + razor_set_destroy(set);
3.98 + return NULL;
3.99 + }
3.100 +
3.101 snprintf(path, sizeof path, "%s%s/%s",
3.102 root, razor_root_path, system_repo_filename);
3.103
3.104 - return razor_set_open(path);
3.105 + if (razor_set_bind_sections(set, path)) {
3.106 + razor_set_destroy(set);
3.107 + return NULL;
3.108 + }
3.109 +
3.110 + return set;
3.111 }
3.112
3.113 RAZOR_EXPORT struct razor_set *