summaryrefslogtreecommitdiff
path: root/sponge.c
diff options
context:
space:
mode:
authorJoey Hess <joey@kodama.kitenet.net>2008-04-11 17:42:38 -0400
committerJoey Hess <joey@kodama.kitenet.net>2008-04-11 17:42:38 -0400
commit6fa7d9907e7211f06656b296940aaca1d6b4d1df (patch)
tree5bfc0e4a8ef397b0cab901494afff0f3c056539c /sponge.c
parentdcb580b3998a19b112004f23298490a34af59fc8 (diff)
downloadmoreutils-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.c33
1 files changed, 18 insertions, 15 deletions
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 {