The unified diff between revisions [5d0b3e5c..] and [3660e007..] is displayed below. It can also be downloaded as a raw diff.

#
#
# add_file "pipeprogress.c"
#  content [864ba82162db98c922bd134b3e273fde40b94098]
#
============================================================
--- pipeprogress.c	864ba82162db98c922bd134b3e273fde40b94098
+++ pipeprogress.c	864ba82162db98c922bd134b3e273fde40b94098
@@ -0,0 +1,135 @@
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#define  BUFFER_SIZE    (32*(1<<10))
+#define  FALSE          0
+#define  TRUE           (!(FALSE))
+
+struct progress {
+        long pos, size;
+        int ticks, max_ticks;
+};
+
+void fail(const char *mesg)
+{
+        fprintf(stderr, "failure: %s (%s)\n", mesg, strerror(errno));
+        exit(1);
+}
+
+void
+display_progress(struct progress *p, int full_display)
+{
+        int i;
+
+        /* ANSI codes nicked from http://en.wikipedia.org/wiki/ANSI_X3.64 */
+        if (full_display) {
+                fputs("\x1B[2K", stderr);
+                fputs("\x1B[1G | ", stderr);
+                for (i=0;i<p->ticks;i++) {
+                        fputc('-', stderr);
+                }
+                for (;i<p->max_ticks;i++) {
+                        fputc(' ', stderr);
+                }
+                fputs(" |", stderr);
+        } else {
+                fprintf(stderr, "\x1B[%dG-", p->ticks+4);
+        }
+        fprintf(stderr, "\x1B[%dG%2.f%%", p->max_ticks+4+4, (100.0 * p->pos) / (p->size));
+}
+
+void
+new_progress(struct progress *p, long size, int max_ticks)
+{
+        p->pos = 0;
+        p->size = size;
+        p->ticks = 0;
+        p->max_ticks = max_ticks;
+        display_progress(p, TRUE);
+}
+
+void
+update_progress(struct progress *p, long bytes)
+{
+        int new_ticks;
+        p->pos += bytes;
+        new_ticks = (p->pos) / (p->size / p->max_ticks);
+        if (new_ticks != p->ticks) {
+                display_progress(p, FALSE);
+                p->ticks = new_ticks;
+        }
+}
+
+void
+finish_progress(struct progress *p)
+{
+        p->ticks = p->max_ticks;
+        display_progress(p, TRUE);
+        fputs("\n", stderr);
+}
+
+void
+copy_to_fd(const char *buf, ssize_t nbytes, int to_fd)
+{
+        ssize_t written = 0;
+
+        while (written < nbytes) {
+                ssize_t wbytes = write(to_fd, buf+written, nbytes-written);
+                if (wbytes < 0) {
+                        fail("failure writing to stdout");
+                }
+                written += wbytes;
+        }
+}
+
+void
+pipe_progress(const char *path)
+{
+        struct progress p;
+        char buf[BUFFER_SIZE];
+        struct stat st;
+        int fd;
+
+        fd = open(path, 0);
+        if (fd < 0) {
+                fail("unable to open output file");
+        }
+        if (fstat(fd, &st) < 0) {
+                fail("unable to stat file descriptor");
+        }
+        new_progress(&p, st.st_size, 60);
+        for (;;) {
+                int nbytes;
+                nbytes = read(fd, &buf, BUFFER_SIZE);
+                if (nbytes < 0) {
+                        fail("error reading from file");
+                } else if (nbytes == 0) {
+                        /* done! */
+                        break;
+                }
+                update_progress(&p, nbytes);
+                copy_to_fd(buf, nbytes, 1);
+        }
+        finish_progress(&p);
+}
+
+int
+main(int argc, char *argv[])
+{
+        int i;
+
+        for (i=1;i<argc;i++) {
+                pipe_progress(argv[i]);
+        }
+
+        return 0;
+}