]> err.no Git - moreutils/commitdiff
sponge: Guarantee that output file is always updated atomically, by renaming a temp...
authorJoey Hess <joey@kitenet.net>
Mon, 13 Sep 2010 19:55:34 +0000 (15:55 -0400)
committerJoey Hess <joey@kitenet.net>
Mon, 13 Sep 2010 19:55:34 +0000 (15:55 -0400)
debian/changelog
sponge.c
sponge.docbook

index 1d6c0e51a59c97c35893f46e8e6837945caa7b54..ae71b8c64669d64e9ef7fe4c45ad3bfbebe67b14 100644 (file)
@@ -1,6 +1,8 @@
 moreutils (0.42) UNRELEASED; urgency=low
 
   * Typo. Closes: #596032
+  * sponge: Guarantee that output file is always updated atomically,
+    by renaming a temp file into place. Closes: #592144
 
  -- Joey Hess <joeyh@debian.org>  Wed, 08 Sep 2010 02:09:29 -0400
 
index 242298deb641650bd25e8b68b52ca72f82becfa4..ea343d051b591a039bddcaf6a4e3e84a32524119 100644 (file)
--- a/sponge.c
+++ b/sponge.c
@@ -262,6 +262,7 @@ int main (int argc, char **argv) {
        FILE *outfile, *tmpfile = 0;
        ssize_t i = 0;
        size_t mem_available = default_sponge_size();
+       struct stat statbuf;
 
        if (argc > 2 || (argc == 2 && strcmp(argv[1], "-h") == 0)) {
                usage();
@@ -269,7 +270,8 @@ int main (int argc, char **argv) {
        if (argc == 2) {
                outname = argv[1];
        }
-
+                               
+       tmpfile = open_tmpfile();
        bufstart = buf = malloc(bufsize);
        if (!buf) {
                perror("failed to allocate memory");
@@ -279,9 +281,6 @@ int main (int argc, char **argv) {
                bufused = bufused+i;
                if (bufused == bufsize) {
                        if ((bufsize*2) >= mem_available) {
-                               if (!tmpfile) {
-                                       tmpfile=open_tmpfile();
-                               }
                                write_buff_tmp(bufstart, bufused, tmpfile);
                                bufused = 0;
                        }
@@ -300,8 +299,6 @@ int main (int argc, char **argv) {
                perror("failed to read from stdin");
                exit(1);
        }
-       if (tmpfile) {
-               struct stat statbuf;
 
                /* write whatever we have in memory to tmpfile */
                if (bufused) 
@@ -319,6 +316,7 @@ int main (int argc, char **argv) {
                              ! S_ISLNK(statbuf.st_mode)
                             ) || errno == ENOENT) &&
                            rename(tmpname, outname) == 0) {
+                               tmpname=NULL;
                                /* Fix renamed file mode to match either
                                 * the old file mode, or the default file
                                 * mode for a newly created file. */
@@ -345,26 +343,11 @@ int main (int argc, char **argv) {
                                exit(1);
                        }
                        copy_tmpfile(tmpfile, outfile, bufstart, bufsize);
+                       fclose(outfile);
                }
                else {
                        copy_tmpfile(tmpfile, stdout, bufstart, bufsize);
                }
-       }
-       else {
-               if (outname) {
-                       outfile = fopen(outname, "w");
-                       if (!outfile) {
-                               perror("error opening output file");
-                               exit(1);
-                       }
-               }
-               else {
-                       outfile = stdout;
-               }
-               if (bufused)
-                       write_buff_out(bufstart, bufused, outfile);
-               fclose(outfile);
-       }
 
        return 0;
 }
index 24c432ac20eb502e58cf609037a3cfa4d1dc7a5f..ab2c42da784447c724981e3bb2ca6f82dad8796f 100644 (file)
@@ -58,7 +58,8 @@ USA
                        redirect, sponge soaks up all its input before
                        opening the output file. This allows constricting
                        pipelines that read from and write to
-                       the same file. </para>
+                       the same file. It also creates the output file
+                       atomically by renaming a temp file into place.</para>
                <para>If no output file is specified, sponge outputs to
                        stdout.</para>