Create the new repo file O_EXCL to prevent racing with another razor process.
And remember to clean it up on exit paths.
1.1 --- a/main.c Mon Apr 07 00:06:22 2008 -0400
1.2 +++ b/main.c Mon Apr 07 00:35:27 2008 -0400
1.3 @@ -5,6 +5,7 @@
1.4 #include <string.h>
1.5 #include <sys/stat.h>
1.6 #include <unistd.h>
1.7 +#include <fcntl.h>
1.8 #include <dirent.h>
1.9 #include <curl/curl.h>
1.10 #include <fnmatch.h>
1.11 @@ -530,33 +531,50 @@
1.12 struct razor_transaction *trans;
1.13 char path[PATH_MAX], new_path[PATH_MAX];
1.14 CURL *curl;
1.15 - int errors;
1.16 + int errors, fd;
1.17 +
1.18 + /* Create the new next repo file up front to ensure exclusive
1.19 + * access. */
1.20 + snprintf(new_path, sizeof new_path,
1.21 + "%s%s/%s", root, razor_root_path, next_repo_filename);
1.22 + fd = open(new_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
1.23 + if (fd < 0) {
1.24 + fprintf(stderr, "failed to get lock file, "
1.25 + "maybe previous operation crashed?\n");
1.26 +
1.27 + /* FIXME: Use fcntl advisory locking to figure out
1.28 + * whether previous operation crashed or is still in
1.29 + * progress. */
1.30 +
1.31 + return -1;
1.32 + }
1.33
1.34 upstream = razor_set_open(rawhide_repo_filename);
1.35 snprintf(path, sizeof path,
1.36 "%s%s/%s", root, razor_root_path, system_repo_filename);
1.37 system = razor_set_open(path);
1.38 - if (system == NULL || upstream == NULL)
1.39 + if (system == NULL || upstream == NULL) {
1.40 + unlink(new_path);
1.41 return 1;
1.42 + }
1.43 trans = razor_transaction_create(system, upstream,
1.44 argc, argv, 0, NULL);
1.45 errors = razor_transaction_describe(trans);
1.46 - if (errors)
1.47 + if (errors) {
1.48 + unlink(new_path);
1.49 return 1;
1.50 + }
1.51
1.52 next = razor_transaction_finish(trans);
1.53
1.54 - /* FIXME: Need razor_set_write_to_fd() so we can open it excl
1.55 - * up front here or fail if it already exists. */
1.56 - snprintf(new_path, sizeof new_path,
1.57 - "%s%s/%s", root, razor_root_path, next_repo_filename);
1.58 -
1.59 - razor_set_write(next, new_path);
1.60 + razor_set_write_to_fd(next, fd);
1.61 printf("wrote %s\n", new_path);
1.62
1.63 curl = curl_easy_init();
1.64 - if (curl == NULL)
1.65 + if (curl == NULL) {
1.66 + unlink(new_path);
1.67 return 1;
1.68 + }
1.69 razor_set_diff(system, next, download_package, curl);
1.70 curl_easy_cleanup(curl);
1.71
2.1 --- a/razor.c Mon Apr 07 00:06:22 2008 -0400
2.2 +++ b/razor.c Mon Apr 07 00:35:27 2008 -0400
2.3 @@ -198,13 +198,13 @@
2.4 }
2.5
2.6 int
2.7 -razor_set_write(struct razor_set *set, const char *filename)
2.8 +razor_set_write_to_fd(struct razor_set *set, int fd)
2.9 {
2.10 char data[4096];
2.11 struct razor_set_header *header = (struct razor_set_header *) data;
2.12 struct array *a;
2.13 uint32_t offset;
2.14 - int i, fd;
2.15 + int i;
2.16
2.17 memset(data, 0, sizeof data);
2.18 header->magic = RAZOR_MAGIC;
2.19 @@ -225,10 +225,6 @@
2.20 header->sections[i].offset = 0;
2.21 header->sections[i].size = 0;
2.22
2.23 - fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
2.24 - if (fd < 0)
2.25 - return -1;
2.26 -
2.27 razor_write(fd, data, sizeof data);
2.28 memset(data, 0, sizeof data);
2.29 for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
2.30 @@ -239,11 +235,27 @@
2.31 razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
2.32 }
2.33
2.34 - close(fd);
2.35 -
2.36 return 0;
2.37 }
2.38
2.39 +int
2.40 +razor_set_write(struct razor_set *set, const char *filename)
2.41 +{
2.42 + int fd, status;
2.43 +
2.44 + fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
2.45 + if (fd < 0)
2.46 + return -1;
2.47 +
2.48 + status = razor_set_write_to_fd(set, fd);
2.49 + if (status) {
2.50 + close(fd);
2.51 + return status;
2.52 + }
2.53 +
2.54 + return close(fd);
2.55 +}
2.56 +
2.57 void
2.58 razor_build_evr(char *evr_buf, int size, const char *epoch,
2.59 const char *version, const char *release)
3.1 --- a/razor.h Mon Apr 07 00:06:22 2008 -0400
3.2 +++ b/razor.h Mon Apr 07 00:35:27 2008 -0400
3.3 @@ -26,6 +26,7 @@
3.4 struct razor_set *razor_set_create(void);
3.5 struct razor_set *razor_set_open(const char *filename);
3.6 void razor_set_destroy(struct razor_set *set);
3.7 +int razor_set_write_to_fd(struct razor_set *set, int fd);
3.8 int razor_set_write(struct razor_set *set, const char *filename);
3.9
3.10 struct razor_package *