Implement proper locking
authorJ. Ali Harlow <ali@juiblex.co.uk>
Thu Oct 01 20:02:12 2009 +0100 (2009-10-01)
changeset 3886a6462ce8a08
parent 387 ef9237601f24
child 389 4aac72ec4537
Implement proper locking
librazor/razor-internal.h
librazor/razor.c
librazor/root.c
     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 *