From: Joey Hess Date: Fri, 11 Apr 2008 21:42:38 +0000 (-0400) Subject: fix two bugs writing the output file X-Git-Tag: 0.29~9 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6fa7d9907e7211f06656b296940aaca1d6b4d1df;p=moreutils fix two bugs writing the output file 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. --- diff --git a/sponge.c b/sponge.c index df1b7a1..d232b5d 100644 --- 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 {