Add write_or_die(), a helper function
authorRene Scharfe <rene.scharfe@lsrfire.ath.cx>
Mon, 21 Aug 2006 18:43:43 +0000 (20:43 +0200)
committerJunio C Hamano <junkio@cox.net>
Tue, 22 Aug 2006 03:22:23 +0000 (20:22 -0700)
The little helper write_or_die() won't come back with bad news about
full disks or broken pipes.  It either succeeds or terminates the
program, making additional error handling unnecessary.

This patch adds the new function and uses it to replace two similar
ones (the one in tar-tree originally has been copied from cat-file
btw.).  I chose to add the fd parameter which both lacked to make
write_or_die() just as flexible as write() and thus suitable for
lib-ification.

There is a regression: error messages emitted by this function don't
show the program name, while the replaced two functions did.  That's
acceptable, I think; a lot of other functions do the same.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Makefile
builtin-cat-file.c
builtin-tar-tree.c
cache.h
write_or_die.c [new file with mode: 0644]

index 23cd8a017ba05986c309c605ae06fba6a98e5c07..b15b420ea218b23a53548577bdc874f8484a6d78 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -248,6 +248,7 @@ LIB_OBJS = \
        server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
        tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
        fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
+       write_or_die.o \
        alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS)
 
 BUILTIN_OBJS = \
index df009ade7aae3ad82974a915efa16525e76ccaed..7a6fa56e93034f0553e5a119180b3841cc773cb4 100644 (file)
@@ -9,23 +9,6 @@
 #include "tree.h"
 #include "builtin.h"
 
-static void flush_buffer(const char *buf, unsigned long size)
-{
-       while (size > 0) {
-               long ret = xwrite(1, buf, size);
-               if (ret < 0) {
-                       /* Ignore epipe */
-                       if (errno == EPIPE)
-                               break;
-                       die("git-cat-file: %s", strerror(errno));
-               } else if (!ret) {
-                       die("git-cat-file: disk full?");
-               }
-               size -= ret;
-               buf += ret;
-       }
-}
-
 static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long size)
 {
        /* the parser in tag.c is useless here. */
@@ -42,7 +25,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
                        /* Found the tagger line.  Copy out the contents
                         * of the buffer so far.
                         */
-                       flush_buffer(buf, cp - buf);
+                       write_or_die(1, buf, cp - buf);
 
                        /*
                         * Do something intelligent, like pretty-printing
@@ -61,18 +44,18 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
                                                sp++;
                                        if (sp == cp) {
                                                /* give up */
-                                               flush_buffer(tagger,
+                                               write_or_die(1, tagger,
                                                             cp - tagger);
                                                break;
                                        }
                                        while (sp < cp &&
                                               !('0' <= *sp && *sp <= '9'))
                                                sp++;
-                                       flush_buffer(tagger, sp - tagger);
+                                       write_or_die(1, tagger, sp - tagger);
                                        date = strtoul(sp, &ep, 10);
                                        tz = strtol(ep, NULL, 10);
                                        sp = show_date(date, tz);
-                                       flush_buffer(sp, strlen(sp));
+                                       write_or_die(1, sp, strlen(sp));
                                        xwrite(1, "\n", 1);
                                        break;
                                }
@@ -90,7 +73,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
         * remainder as is.
         */
        if (cp < endp)
-               flush_buffer(cp, endp - cp);
+               write_or_die(1, cp, endp - cp);
 }
 
 int cmd_cat_file(int argc, const char **argv, const char *prefix)
@@ -162,6 +145,6 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
        if (!buf)
                die("git-cat-file %s: bad file", argv[2]);
 
-       flush_buffer(buf, size);
+       write_or_die(1, buf, size);
        return 0;
 }
index aeb5a8c2ad886f60bc402eb56a1bd2e37698ab7d..e0bcb0a1e146c3f85fa98463a0d4bb5913a3f2b2 100644 (file)
@@ -22,30 +22,11 @@ static unsigned long offset;
 static time_t archive_time;
 static int tar_umask;
 
-/* tries hard to write, either succeeds or dies in the attempt */
-static void reliable_write(const void *data, unsigned long size)
-{
-       const char *buf = data;
-
-       while (size > 0) {
-               long ret = xwrite(1, buf, size);
-               if (ret < 0) {
-                       if (errno == EPIPE)
-                               exit(0);
-                       die("git-tar-tree: %s", strerror(errno));
-               } else if (!ret) {
-                       die("git-tar-tree: disk full?");
-               }
-               size -= ret;
-               buf += ret;
-       }
-}
-
 /* writes out the whole block, but only if it is full */
 static void write_if_needed(void)
 {
        if (offset == BLOCKSIZE) {
-               reliable_write(block, BLOCKSIZE);
+               write_or_die(1, block, BLOCKSIZE);
                offset = 0;
        }
 }
@@ -70,7 +51,7 @@ static void write_blocked(const void *data, unsigned long size)
                write_if_needed();
        }
        while (size >= BLOCKSIZE) {
-               reliable_write(buf, BLOCKSIZE);
+               write_or_die(1, buf, BLOCKSIZE);
                size -= BLOCKSIZE;
                buf += BLOCKSIZE;
        }
@@ -94,10 +75,10 @@ static void write_trailer(void)
 {
        int tail = BLOCKSIZE - offset;
        memset(block + offset, 0, tail);
-       reliable_write(block, BLOCKSIZE);
+       write_or_die(1, block, BLOCKSIZE);
        if (tail < 2 * RECORDSIZE) {
                memset(block, 0, offset);
-               reliable_write(block, BLOCKSIZE);
+               write_or_die(1, block, BLOCKSIZE);
        }
 }
 
diff --git a/cache.h b/cache.h
index f99254bf991af312e2e15aa279e75db4a3b1dbdd..08d6a91279c87ad1e4d7ce1be1ac927b52a6113e 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -388,6 +388,7 @@ extern char git_default_name[MAX_GITNAME];
 extern char git_commit_encoding[MAX_ENCODING_LENGTH];
 
 extern int copy_fd(int ifd, int ofd);
+extern void write_or_die(int fd, const void *buf, size_t count);
 
 /* Finish off pack transfer receiving end */
 extern int receive_unpack_pack(int fd[2], const char *me, int quiet, int);
diff --git a/write_or_die.c b/write_or_die.c
new file mode 100644 (file)
index 0000000..ab4cb8a
--- /dev/null
@@ -0,0 +1,20 @@
+#include "cache.h"
+
+void write_or_die(int fd, const void *buf, size_t count)
+{
+       const char *p = buf;
+       ssize_t written;
+
+       while (count > 0) {
+               written = xwrite(fd, p, count);
+               if (written == 0)
+                       die("disk full?");
+               else if (written < 0) {
+                       if (errno == EPIPE)
+                               exit(0);
+                       die("write error (%s)", strerror(errno));
+               }
+               count -= written;
+               p += written;
+       }
+}