]> err.no Git - moreutils/commitdiff
fix two bugs writing the output file
authorJoey Hess <joey@kodama.kitenet.net>
Fri, 11 Apr 2008 21:42:38 +0000 (17:42 -0400)
committerJoey Hess <joey@kodama.kitenet.net>
Fri, 11 Apr 2008 21:42:38 +0000 (17:42 -0400)
If the output file doesn't exist, the new code was buggy and did not create
it.

Also, the rename could fail (ie, /tmp on another filesystem). So if it
falls fall back to the manual copy.

sponge.c

index df1b7a15e88a481d262b3e31d0aeea8e56267499..d232b5d4b018e87f8479a09fa1a6a26eff2fc16c 100644 (file)
--- a/sponge.c
+++ b/sponge.c
@@ -286,25 +286,28 @@ int main (int argc, char **argv) {
                outname = argv[1];
        }
        if (tmpfile) {
+               struct stat statbuf;
+
                /* write whatever we have in memory to tmpfile */
                if (bufused) 
                        write_buff_tmp(bufstart, bufused, tmpfile);
-               struct stat statbuf;
-               if (outname && !stat(outname, &statbuf)) {
-                       /* regular file */
-                       if (S_ISREG(statbuf.st_mode) && !fclose(tmpfile)) {
-                               if (rename(tmpname, outname)) {
-                                       perror("error renaming temporary file to output file");
-                                       exit(1);
-                               }
-                       }
-                       else {
-                               FILE *outfd = fopen(outname, "w");
-                               if (outfd < 0) {
-                                       perror("error opening output file");
-                                       exit(1);
+               fclose(tmpfile);
+
+               if (outname) {
+                       /* If it's a regular file, or does not yet exist,
+                        * attempt a fast rename of the temp file. */
+                       if ((stat(outname, &statbuf) == 0 &&
+                            S_ISREG(statbuf.st_mode)) ||
+                           errno == ENOENT) {
+                               if (rename(tmpname, outname) != 0) {
+                                       /* Slow copy. */
+                                       FILE *outfd = fopen(outname, "w");
+                                               if (outfd < 0) {
+                                               perror("error opening output file");
+                                               exit(1);
+                                       }
+                                       copy_tmpfile(tmpfile, outfd);
                                }
-                               copy_tmpfile(tmpfile, outfd);
                        }
                }
                else {