diff options
author | Joey Hess <joey@kodama.kitenet.net> | 2008-04-11 17:42:38 -0400 |
---|---|---|
committer | Joey Hess <joey@kodama.kitenet.net> | 2008-04-11 17:42:38 -0400 |
commit | 6fa7d9907e7211f06656b296940aaca1d6b4d1df (patch) | |
tree | 5bfc0e4a8ef397b0cab901494afff0f3c056539c /sponge.c | |
parent | dcb580b3998a19b112004f23298490a34af59fc8 (diff) | |
download | moreutils-6fa7d9907e7211f06656b296940aaca1d6b4d1df.tar.gz |
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.
Diffstat (limited to 'sponge.c')
-rw-r--r-- | sponge.c | 33 |
1 files changed, 18 insertions, 15 deletions
@@ -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 { |