Create the new repo file O_EXCL to prevent racing with another razor process.
authorKristian Høgsberg <krh@redhat.com>
Mon, 7 Apr 2008 04:31:01 +0000 (00:31 -0400)
committerKristian Høgsberg <krh@redhat.com>
Mon, 7 Apr 2008 04:35:27 +0000 (00:35 -0400)
And remember to clean it up on exit paths.

main.c
razor.c
razor.h

diff --git a/main.c b/main.c
index 6bcd996..a2ef1d0 100644 (file)
--- a/main.c
+++ b/main.c
@@ -5,6 +5,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <dirent.h>
 #include <curl/curl.h>
 #include <fnmatch.h>
@@ -530,33 +531,50 @@ command_install(int argc, const char *argv[])
        struct razor_transaction *trans;
        char path[PATH_MAX], new_path[PATH_MAX];
        CURL *curl;
-       int errors;
+       int errors, fd;
+
+       /* Create the new next repo file up front to ensure exclusive
+        * access. */
+       snprintf(new_path, sizeof new_path,
+                "%s%s/%s", root, razor_root_path, next_repo_filename);
+       fd = open(new_path, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0666);
+       if (fd < 0) {
+               fprintf(stderr, "failed to get lock file, "
+                       "maybe previous operation crashed?\n");
+
+               /* FIXME: Use fcntl advisory locking to figure out
+                * whether previous operation crashed or is still in
+                * progress. */
+
+               return -1;
+       }
 
        upstream = razor_set_open(rawhide_repo_filename);
        snprintf(path, sizeof path,
                 "%s%s/%s", root, razor_root_path, system_repo_filename);
        system = razor_set_open(path);
-       if (system == NULL || upstream == NULL)
+       if (system == NULL || upstream == NULL) {
+               unlink(new_path);
                return 1;
+       }
        trans = razor_transaction_create(system, upstream,
                                         argc, argv, 0, NULL);
        errors = razor_transaction_describe(trans);
-       if (errors)
+       if (errors) {
+               unlink(new_path);
                return 1;
+       }
 
        next = razor_transaction_finish(trans);
 
-       /* FIXME: Need razor_set_write_to_fd() so we can open it excl
-        * up front here or fail if it already exists. */
-       snprintf(new_path, sizeof new_path,
-                "%s%s/%s", root, razor_root_path, next_repo_filename);
-
-       razor_set_write(next, new_path);
+       razor_set_write_to_fd(next, fd);
        printf("wrote %s\n", new_path);
 
        curl = curl_easy_init();
-       if (curl == NULL)
+       if (curl == NULL) {
+               unlink(new_path);
                return 1;
+       }
        razor_set_diff(system, next, download_package, curl);   
        curl_easy_cleanup(curl);
 
diff --git a/razor.c b/razor.c
index 5e77402..722f41b 100644 (file)
--- a/razor.c
+++ b/razor.c
@@ -198,13 +198,13 @@ razor_set_destroy(struct razor_set *set)
 }
 
 int
-razor_set_write(struct razor_set *set, const char *filename)
+razor_set_write_to_fd(struct razor_set *set, int fd)
 {
        char data[4096];
        struct razor_set_header *header = (struct razor_set_header *) data;
        struct array *a;
        uint32_t offset;
-       int i, fd;
+       int i;
 
        memset(data, 0, sizeof data);
        header->magic = RAZOR_MAGIC;
@@ -225,10 +225,6 @@ razor_set_write(struct razor_set *set, const char *filename)
        header->sections[i].offset = 0;
        header->sections[i].size = 0;
 
-       fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
-       if (fd < 0)
-               return -1;
-
        razor_write(fd, data, sizeof data);
        memset(data, 0, sizeof data);
        for (i = 0; i < ARRAY_SIZE(razor_sections); i++) {
@@ -239,11 +235,27 @@ razor_set_write(struct razor_set *set, const char *filename)
                razor_write(fd, data, ALIGN(a->size, 4096) - a->size);
        }
 
-       close(fd);
-
        return 0;
 }
 
+int
+razor_set_write(struct razor_set *set, const char *filename)
+{
+       int fd, status;
+
+       fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0666);
+       if (fd < 0)
+               return -1;
+
+       status = razor_set_write_to_fd(set, fd);
+       if (status) {
+           close(fd);
+           return status;
+       }
+
+       return close(fd);
+}
+
 void
 razor_build_evr(char *evr_buf, int size, const char *epoch,
                const char *version, const char *release)
diff --git a/razor.h b/razor.h
index cc6a869..62e8e5f 100644 (file)
--- a/razor.h
+++ b/razor.h
@@ -26,6 +26,7 @@ extern const char * const razor_version_relations[];
 struct razor_set *razor_set_create(void);
 struct razor_set *razor_set_open(const char *filename);
 void razor_set_destroy(struct razor_set *set);
+int razor_set_write_to_fd(struct razor_set *set, int fd);
 int razor_set_write(struct razor_set *set, const char *filename);
 
 struct razor_package *