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;
+}