#include <fnmatch.h>
#include <limits.h>
#include <assert.h>
+#ifdef MSWIN_API
+#include <windows.h>
+#endif
#include "razor-internal.h"
#include "razor.h"
empty = array_add(&set->string_pool, 1);
*empty = '\0';
+ set->lock_fd = -1;
+
return set;
}
return -1;
}
+ if (set->mapped_files == NULL) {
+ for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
+ array = (void *) set + razor_sections[i].offset;
+ array_release(array);
+ }
+ }
+
file->next = set->mapped_files;
set->mapped_files = file;
struct razor_set *set;
set = zalloc(sizeof *set);
+ set->lock_fd = -1;
if (razor_set_bind_sections(set, filename)){
free(set);
return NULL;
return set;
}
+int
+razor_set_aquire_lock(struct razor_set *set, const char *path, int exclusive)
+{
+ int fd;
+ assert(set != NULL);
+
+ if (path) {
+ fd = open(path, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0666);
+ if (fd < 0)
+ return -1;
+ } else {
+ fd = -1;
+ }
+
+#ifdef MSWIN_API
+ DWORD flags = LOCKFILE_FAIL_IMMEDIATELY;
+ OVERLAPPED lock = {0};
+
+ if (exclusive)
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ if (fd >= 0 && !LockFileEx(_get_osfhandle(fd), flags, 0, 1, 0, &lock)) {
+ close(fd);
+ return -1;
+ }
+ if (set->lock_fd >= 0)
+ (void)UnlockFile(_get_osfhandle(set->lock_fd), 0, 0, 1, 0);
+#else
+ struct flock lock = {0};
+
+ lock.l_type = exclusive ? F_WRLCK : F_RDLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = 0;
+ lock.l_len = 0;
+ if (fd >= 0 && fcntl(fd, F_SETLK, &lock) < 0) {
+ close(fd);
+ return -1;
+ }
+ if (set->lock_fd >= 0) {
+ lock.l_type = F_UNLCK;
+ (void)fcntl(set->lock_fd, F_SETLK, &lock);
+ }
+#endif
+
+ if (set->lock_fd >= 0)
+ close(set->lock_fd);
+ set->lock_fd = fd;
+
+ return 0;
+}
+
RAZOR_EXPORT void
razor_set_destroy(struct razor_set *set)
{
}
}
+ razor_set_aquire_lock(set, NULL, 0);
free(set);
}
#endif
static const char system_repo_filename[] = "system.rzdb";
-static const char next_repo_filename[] = "system-next.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";
+static const char system_tmp_filename[] = "system.tmp";
#ifdef MSWIN_API
#define RAZOR_ROOT_PATH NULL
#else
razor_root_open(const char *root)
{
struct razor_root *image;
+ char lock_path[PATH_MAX];
assert (root != NULL);
if (image == NULL)
return NULL;
- /* Create the new next repo file up front to ensure exclusive
- * access. */
+ image->system = razor_set_create_without_root();
+ if (image->system == NULL) {
+ free(image);
+ return NULL;
+ }
+
+ snprintf(lock_path, sizeof lock_path,
+ "%s%s/%s", root, razor_root_path, system_lock_filename);
+
+ if (razor_set_aquire_lock(image->system, lock_path, 1) < 0) {
+ razor_set_destroy(image->system);
+ free(image);
+ return NULL;
+ }
+
snprintf(image->new_path, sizeof image->new_path,
- "%s%s/%s", root, razor_root_path, next_repo_filename);
+ "%s%s/%s", root, razor_root_path, system_tmp_filename);
image->fd = open(image->new_path,
- O_CREAT | O_WRONLY | O_TRUNC | O_EXCL | O_BINARY,
+ O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
0666);
if (image->fd < 0) {
- fprintf(stderr, "failed to get lock file, "
- "maybe previous operation crashed?\n");
-
- /* FIXME: Use fcntl advisory locking on the system
- * package set file to figure out whether previous
- * operation crashed or is still in progress. */
-
+ razor_set_destroy(image->system);
free(image);
return NULL;
}
snprintf(image->path, sizeof image->path,
"%s%s/%s", root, razor_root_path, system_repo_filename);
- image->system = razor_set_open(image->path);
- if (image->system == NULL) {
- unlink(image->new_path);
+ if (razor_set_bind_sections(image->system, image->path)) {
close(image->fd);
+ unlink(image->new_path);
+ razor_set_destroy(image->system);
free(image);
return NULL;
}
razor_root_open_read_only(const char *root)
{
char path[PATH_MAX];
+ struct razor_set *set;
assert (root != NULL);
razor_root_init();
+ set = razor_set_create_without_root();
+ if (set == NULL)
+ return NULL;
+
+ snprintf(path, sizeof path,
+ "%s%s/%s", root, razor_root_path, system_lock_filename);
+ if (razor_set_aquire_lock(set, path, 0) < 0) {
+ razor_set_destroy(set);
+ return NULL;
+ }
+
snprintf(path, sizeof path, "%s%s/%s",
root, razor_root_path, system_repo_filename);
- return razor_set_open(path);
+ if (razor_set_bind_sections(set, path)) {
+ razor_set_destroy(set);
+ return NULL;
+ }
+
+ return set;
}
RAZOR_EXPORT struct razor_set *