Fix Joey's report of rename failing across moint points.
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 11 Feb 2010 01:09:08 +0000 (11:39 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 11 Feb 2010 01:09:08 +0000 (11:39 +1030)
tools/ccanlint/compulsory_tests/build.c
tools/ccanlint/tests/has_info_documentation.c
tools/namespacize.c
tools/tools.c
tools/tools.h

index e3f96d7d62c6c28b79e8a2f8b5bdd7f476b79725..d2b22ac5ef51726cc2c06c14d97b19239d1e6e5e 100644 (file)
@@ -46,7 +46,7 @@ static void *do_build(struct manifest *m)
        if (filename) {
                char *realname = talloc_asprintf(m, "%s.o", m->dir);
                /* We leave this object file around, all built. */
-               if (rename(filename, realname) != 0)
+               if (!move_file(filename, realname))
                        return talloc_asprintf(m, "Failed to rename %s to %s",
                                               filename, realname);
                return NULL;
index 9233e2883d7229acb3e132659cf36fd00339a5b6..17e4207eeaff856c3cf20b999bc5de02d212320d 100644 (file)
@@ -1,5 +1,6 @@
 #include <tools/ccanlint/ccanlint.h>
 #include <tools/doc_extract.h>
+#include <tools/tools.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -81,7 +82,7 @@ static void create_info_template_doc(struct manifest *m, void *check_result)
                unlink_noerr("_info.new");
                err(1, "Closing _info.new");
        }
-       if (rename("_info.new", "_info") != 0) {
+       if (!move_file("_info.new", "_info")) {
                unlink_noerr("_info.new");
                err(1, "Renaming _info.new to _info");
        }
index 77269aac317dac5a4d7c7b319aa794472739f116..545b28bb1a4f7d2dcd138b9a4fe9325907b81502 100644 (file)
@@ -406,7 +406,7 @@ static void setup_adjust_files(const char *dir,
 static void rename_files(const struct adjusted *adj)
 {
        while (adj) {
-               if (rename(adj->tmpfile, adj->file) != 0)
+               if (!move_file(adj->tmpfile, adj->file))
                        warn("Could not rename over '%s', we're in trouble",
                             adj->file);
                adj = adj->next;
index 87ff4a3b65f4fe9899cf8aebb6e99a40cd244221..18cc1b84cb299fcc8c5659a05b6c6c05da701a82 100644 (file)
@@ -1,7 +1,10 @@
 #include <ccan/talloc/talloc.h>
 #include <ccan/grab_file/grab_file.h>
+#include <ccan/noerr/noerr.h>
+#include <ccan/read_write_all/read_write_all.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <fcntl.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdarg.h>
@@ -107,3 +110,39 @@ char *temp_file(const void *ctx, const char *extension)
 
        return talloc_asprintf(ctx, "%s/%u%s", tmpdir, count++, extension);
 }
+
+bool move_file(const char *oldname, const char *newname)
+{
+       char *contents;
+       size_t size;
+       int fd;
+       bool ret;
+
+       /* Simple case: rename works. */
+       if (rename(oldname, newname) == 0)
+               return true;
+
+       /* Try copy and delete: not atomic! */
+       contents = grab_file(NULL, oldname, &size);
+       if (!contents)
+               return false;
+
+       fd = open(newname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+       if (fd < 0) {
+               ret = false;
+               goto free;
+       }
+
+       ret = write_all(fd, contents, size);
+       if (close(fd) != 0)
+               ret = false;
+
+       if (ret)
+               unlink(oldname);
+       else
+               unlink(newname);
+
+free:
+       talloc_free(contents);
+       return ret;
+}
index 2092042f7be6fc4606055965a35248b0c9950ef3..34c2f99ff1253fe38a888fe697c79f9bb07fb323 100644 (file)
@@ -29,6 +29,7 @@ char *talloc_dirname(const void *ctx, const char *dir);
 char *talloc_getcwd(const void *ctx);
 char *run_command(const void *ctx, const char *fmt, ...);
 char *temp_file(const void *ctx, const char *extension);
+bool move_file(const char *oldname, const char *newname);
 
 /* From compile.c.
  *