]> err.no Git - moreutils/commitdiff
sponge fixes
authorBrock Noland <brockn@gmail.com>
Fri, 11 Apr 2008 18:16:09 +0000 (13:16 -0500)
committerJoey Hess <joey@kodama.kitenet.net>
Fri, 11 Apr 2008 19:45:45 +0000 (15:45 -0400)
*Fixed many bugs relating to renaming of temp file to output file
*Doesn't set umask, not sure what correct behavior is
*Does not try and delete /tmp/sponge.XXXXXX on exit if there was no temporary file used
*Uses temporary file when buffer * 2 is >= mem_available as the buffer will double shortly after this operation
*Only traps signals if we are creating a temporary file
*Cleaned up error messages

Signed-off-by: Brock Noland <brockn@gmail.com>
physmem.c
sponge.c

index 0fcb5e96aae4266b30c5c738e28fd7db464e478b..a53a2cf1906998c91533f5f5435ceeeeb1a7cd59 100644 (file)
--- a/physmem.c
+++ b/physmem.c
@@ -3,10 +3,10 @@
    Copyright (C) 2000, 2001, 2003, 2005, 2006 Free Software
    Foundation, Inc.
 
-   This program is free software: you can redistribute it and/or modify
+   This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,7 +14,8 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 /* Written by Paul Eggert.  */
 
index ba3dd95b93399155693f518937cfbd3add98b972..b452312370eea6b3e9e5416c780a27477d488cf2 100644 (file)
--- a/sponge.c
+++ b/sponge.c
@@ -37,7 +37,7 @@
 
 #include "physmem.c"
 
-#define MIN_SPONGE_SIZE     sizeof(8192)
+#define MIN_SPONGE_SIZE     BUFF_SIZE
 #define BUFF_SIZE           8192
 #define DEFAULT_TMP_NAME    "/tmp/sponge.XXXXXX"
 char tmpname[] = DEFAULT_TMP_NAME;
@@ -74,7 +74,9 @@ static void cs_leave (struct cs_status status) {
 }
 
 static void cleanup() {
-       unlink(tmpname);
+    if(strcmp(tmpname, DEFAULT_TMP_NAME)) {
+       unlink(tmpname);
+    }
 }
 
 static void onexit_cleanup (void) {
@@ -84,6 +86,7 @@ static void onexit_cleanup (void) {
 }
 
 static void sighandler (int sig) {
+    printf("caught sig %d\n", sig);
        if (! SA_NOCLDSTOP)
                signal(sig, SIG_IGN);
 
@@ -181,6 +184,36 @@ void trapsignals (void) {
 #endif
 }
 
+static void write_buff_tmp(char* buff, size_t length, FILE *fd) {
+    if (fwrite(buff, length, 1, fd) < 1) {
+        perror("error writing buffer to temporary file");
+        fclose(fd);
+        exit(1);
+    }
+}
+static void write_buff_out(char* buff, size_t length, FILE *fd) {
+    if (fwrite(buff, length, 1, fd) < 1) {
+        perror("error writing buffer to output file");
+        fclose(fd);
+        exit(1);
+    }
+}
+static void copy_tmpfile(FILE *tmpfile, FILE *outfd) {
+    char buf[BUFF_SIZE];
+    if (fseek(tmpfile, 0, SEEK_SET)) {
+        perror("could to seek to start of temporary file");
+        fclose(tmpfile);
+        exit(1);
+    }
+    // XXX I'd catch signals or writes errors here, but I
+    // I don't think it matters as the file is overwritten
+    while(fread(buf, BUFF_SIZE, 1, tmpfile) == 1) {
+        write_buff_out(buf, BUFF_SIZE, outfd);
+    }
+    fclose(tmpfile);
+    fclose(outfd);
+}
+
 int main (int argc, char **argv) {
        char *buf, *bufstart, *outname = NULL;
        size_t bufsize = BUFF_SIZE;
@@ -197,30 +230,26 @@ int main (int argc, char **argv) {
                perror("failed to allocate memory");
                exit(1);
        }
-
-       trapsignals();
-
        while ((i = read(0, buf, bufsize - bufused)) > 0) {
                bufused = bufused+i;
                if (bufused == bufsize) {
-                       if (bufsize >= mem_available) {
+                       if ((bufsize*2) >= mem_available) {
                                if (!tmpfile) {
-                                       umask(077);
+                    /* 
+                    umask(077); FIXME: Should we be setting umask, or using default?
+                    */
                                        struct cs_status cs = cs_enter();
                                        int tmpfd = mkstemp(tmpname);
-                                       atexit(onexit_cleanup); // if solaris on_exit(onexit_cleanup, 0);
+                                       atexit(onexit_cleanup); // solaris on_exit(onexit_cleanup, 0);
+                    trapsignals();
                                        cs_leave(cs);
                                        if (tmpfd < 0) {
-                                               perror("mkstemp");
+                                               perror("mkstemp failed");
                                                exit(1);
                                        }
                                        tmpfile = fdopen(tmpfd, "w+");
                                }
-                               if (fwrite(bufstart, bufsize, 1, tmpfile) < 1) {
-                                       perror("writing to tempory file failed"); 
-                                       fclose(tmpfile);
-                                       exit(1);
-                               }
+                write_buff_tmp(bufstart, bufused, tmpfile);
                                bufused = 0;
                        }
                        else {
@@ -242,50 +271,41 @@ int main (int argc, char **argv) {
                outname = argv[1];
        }
        if (tmpfile) {
-               if (fwrite(bufstart, bufused, 1, tmpfile) < 1) {
-                       perror("write tmpfile");
-                       fclose(tmpfile);
-                       exit(1);
-               }
-               if (outname) {
-                       fclose(tmpfile);
-                       if (rename(tmpname, outname)) {
-                               perror("error renaming temporary file to output file");
-                               exit(1);
-                       }
+        /* write whatever we have in memory to tmpfile */
+        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);
+                }
+                copy_tmpfile(tmpfile, outfd);
+            }
                }
                else {
-                       if (fseek(tmpfile, 0, SEEK_SET)) {
-                               perror("could to seek to start of temporary file");
-                               fclose(tmpfile);
-                               exit(1);
-                       }
-                       while (fread( buf, BUFF_SIZE, 1, tmpfile) < 1) {
-                               if (fwrite(buf, BUFF_SIZE, 1, stdout) < 1) { 
-                                       perror("error writing out merged file");
-                                       exit(1);
-                               }
-                       }
-                       fclose(tmpfile);
-                       unlink(tmpname);
+            copy_tmpfile(tmpfile, stdout);
                }
        }
        else {
+        FILE *outfd = stdout;
                if (outname) {
-                       FILE *outfd = fopen(outname, "w");
+                       outfd = fopen(outname, "w");
                        if (outfd < 0) {
                                perror("error opening output file");
                                exit(1);
                        }
-                       if (fwrite(bufstart, bufused, 1, outfd) < 1) {
-                               perror("error writing out merged file");
-                               exit(1);
-                       }
-               }
-               else if (fwrite(bufstart, bufused, 1, stdout) < 1) {
-                       perror("error writing out merged file");
-                       exit(1);
                }
+        write_buff_out(bufstart, bufused, outfd);
+        fclose(outfd);
        }
        return 0;
 }