discover/file: Add replace_file()
authorJeremy Kerr <jk@ozlabs.org>
Thu, 8 Aug 2013 07:25:24 +0000 (15:25 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Thu, 8 Aug 2013 08:30:00 +0000 (16:30 +0800)
Add a function to atomically replace a file.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/file.c
discover/file.h

index 269421cb8d02c727fb33fd607506d9c67d83710f..1ebfe43b10ba02029dbedac3b8fcf0c3a088d7de 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <fcntl.h>
 #include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -75,3 +77,44 @@ err_close:
        close(fd);
        return -1;
 }
+
+static int write_fd(int fd, char *buf, int len)
+{
+       int i, rc;
+
+       for (i = 0; i < len; i += rc) {
+               rc = write(fd, buf + i, len - i);
+               if (rc < 0 && errno != -EINTR)
+                       return rc;
+       }
+
+       return 0;
+}
+
+int replace_file(const char *filename, char *buf, int len)
+{
+       char *tempfile;
+       mode_t oldmask;
+       int rc, fd;
+
+       tempfile = talloc_asprintf(NULL, "%s.XXXXXX", filename);
+
+       oldmask = umask(0644);
+       fd = mkstemp(tempfile);
+       umask(oldmask);
+       if (fd < 0) {
+               free(tempfile);
+               return fd;
+       }
+
+       rc = write_fd(fd, buf, len);
+       if (rc) {
+               unlink(tempfile);
+       } else {
+               rc = rename(tempfile, filename);
+       }
+
+       free(tempfile);
+       close(fd);
+       return rc;
+}
index 1997eca90edad320b7f2f7c697bbfd5b7719bec8..8aa7d3c92ced1142b5f1fcc742420c18aa85344d 100644 (file)
@@ -18,6 +18,7 @@
 #define FILE_H
 
 int read_file(void *ctx, const char *filename, char **bufp, int *lenp);
+int replace_file(const char *filename, char *buf, int len);
 
 #endif /* FILE_H */