From: Brock Noland Date: Fri, 11 Apr 2008 18:16:09 +0000 (-0500) Subject: sponge fixes X-Git-Tag: 0.29~16 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=42c5c5a799502743307b392bf9e7c0205ef85ace;p=moreutils sponge fixes *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 --- diff --git a/physmem.c b/physmem.c index 0fcb5e9..a53a2cf 100644 --- 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 . */ + 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. */ diff --git a/sponge.c b/sponge.c index ba3dd95..b452312 100644 --- 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; }