diff --git a/zio-dump.c b/zio-dump.c index 1611717bf576ea4f076628f2cd25b3f3dc9cda42..2964421a9d810d815c443c741bc2fde5a38b5207 100644 --- a/zio-dump.c +++ b/zio-dump.c @@ -10,40 +10,138 @@ #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/select.h> #include <linux/zio.h> #include <linux/zio-buffer.h> -#define FD_C 0 -#define FD_D 1 -#define ZIO_CONTROL_SIZE 512 -#define ZIO_NAME_LEN 32 - unsigned char buf[1024*1024]; +char *prgname; + +void read_channel(int cfd, int dfd, FILE *log) +{ + struct zio_control ctrl; + int i, j; + + i = read(cfd, &ctrl, sizeof(ctrl)); + switch(i) { + case -1: + fprintf(stderr, "%s: control read: %s\n", + prgname, strerror(errno)); + exit(1); + case 0: + fprintf(stderr, "%s: control read: unexpected EOF\n", + prgname); + exit(1); + default: + fprintf(stderr, "%s: ctrl read: %i bytes (expected %i)\n", + prgname, i, sizeof(ctrl)); + /* continue anyways */ + case sizeof(ctrl): + break; /* ok */ + } + + printf("Ctrl: version %i.%i, trigger %.16s, dev %.16s, " + "cset %i, chan %i\n", + ctrl.major_version, ctrl.minor_version, + ctrl.triggername, ctrl.devname, ctrl.cset_i, + ctrl.chan_i); + printf("Ctrl: seq %i, n %i, size %i, bits %i, " + "flags %08x (%s)\n", + ctrl.seq_num, + ctrl.nsamples, + ctrl.ssize, + ctrl.sbits, + ctrl.flags, + ctrl.flags & ZIO_CONTROL_LITTLE_ENDIAN + ? "little-endian" : + ctrl.flags & ZIO_CONTROL_BIG_ENDIAN + ? "big-endian" : "unknown-endian"); + printf("Ctrl: stamp %lli.%09lli (%lli)\n", + (long long)ctrl.tstamp.secs, + (long long)ctrl.tstamp.ticks, + (long long)ctrl.tstamp.bins); + /* FIXME: some control information is missing */ + + i = read(dfd, buf, sizeof(buf)); + if (i < 0) { + fprintf(stderr, "%s: data read: %s\n", + prgname, strerror(errno)); + return; /* next ctrl, let's see... */ + } + if (!i) { + fprintf(stderr, "%s: data read: unexpected EOF\n", prgname); + return; + } + if (i != ctrl.nsamples * ctrl.ssize) { + if (i == sizeof(buf)) { + fprintf(stderr, "%s: buffer too small: " + "please fix me and recompile\n", prgname); + /* FIXME: empty the data channel */ + } else { + fprintf(stderr, "%s: ctrl: read %i bytes " + "(exp %i)\n", prgname, i, + ctrl.nsamples * ctrl.ssize); + } + /* continue anyways */ + } + fwrite(buf, 1, i, log); + + /* report data to stdout */ + for (j = 0; j < i; j++) { + if (!(j & 0xf)) + printf("Data:"); + printf(" %02x", buf[j]); + if ((j & 0xf) == 0xf || j == i - 1) + putchar('\n'); + } + putchar('\n'); +} int main(int argc, char **argv) { FILE *f; char *outfname; - int fd[2]; - int i, j; + int *cfd; /* control file descriptors */ + int *dfd; /* data file descriptors */ + fd_set control_set, ready_set; + int i, j, maxfd, ndev; - if (argc != 3) { - fprintf(stderr, "%s: use \"%s <ctrl-file> <data-file>\"\n", + if (argc < 3 || (argc & 1) != 1) { + fprintf(stderr, "%s: Wrong number of arguments\n" + "Use: \"%s <ctrl-file> <data-file> [...]\"\n", argv[0], argv[0]); exit(1); } + prgname = argv[0]; + cfd = malloc(argc / 2 * sizeof(*cfd)); + dfd = malloc(argc / 2 * sizeof(*dfd)); + if (!cfd || !dfd) { + fprintf(stderr, "%s: malloc: %s\n", prgname, strerror(errno)); + exit(1); + } - for (i = 0; i < 2; i++) { - fd[i] = open(argv[i + 1], O_RDONLY); - if (fd[i] < 0) { - fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i + 1], + /* Open all pairs, and build the fd_set for later select() */ + FD_ZERO(&control_set); + for (i = 1, j = 0; i < argc; i+=2, j++) { + cfd[j] = open(argv[i], O_RDONLY); + dfd[j] = open(argv[i + 1], O_RDONLY); + if (cfd[j] < 0) { + fprintf(stderr, "%s: %s: %s\n", prgname, argv[i], + strerror(errno)); + exit(1); + } + if (dfd[j] < 0) { + fprintf(stderr, "%s: %s: %s\n", prgname, argv[i + 1], strerror(errno)); exit(1); } + /* ctrl file is used in select, data file is non-blocking */ + FD_SET(cfd[j], &control_set); + fcntl(dfd[j], F_SETFL, fcntl(dfd[j], F_GETFL) | O_NONBLOCK); + maxfd = dfd[j]; } - /* the data channel is non-blocking */ - fcntl(fd[FD_D], F_SETFL, fcntl(fd[FD_D], F_GETFL) | O_NONBLOCK); + ndev = j; /* always log data we read to some filename */ outfname = getenv("ZIO_DUMP_TO"); @@ -51,7 +149,7 @@ int main(int argc, char **argv) outfname = "/dev/null"; f = fopen(outfname, "w"); if (!f) { - fprintf(stderr, "%s: %s: %s\n", argv[0], outfname, + fprintf(stderr, "%s: %s: %s\n", prgname, outfname, strerror(errno)); exit(1); } @@ -59,83 +157,19 @@ int main(int argc, char **argv) setlinebuf(stdout); setbuf(f, NULL); - /* now read control and data, forever */ + /* now read control and then data, forever */ while (1) { - struct zio_control ctrl; - - /* This is a blocking read to the control file */ - i = read(fd[FD_C], &ctrl, sizeof(ctrl)); - switch (i) { - case -1: - fprintf(stderr, "%s: %s: read(): %s\n", - argv[0], argv[1 + FD_C], strerror(errno)); - exit(1); - case 0: - fprintf(stderr, "%s: %s: unexpected EOF\n", - argv[0], argv[1 + FD_C]); - exit(1); - default: - fprintf(stderr, "%s: ctrl: read %i bytes (exp %i)\n", - argv[0], i, sizeof(ctrl)); - /* continue anyways */ - case sizeof(ctrl): - break; /* ok */ - } - printf("Ctrl: version %i.%i, trigger %.16s, dev %.16s, " - "cset %i, chan %i\n", - ctrl.major_version, ctrl.minor_version, - ctrl.triggername, ctrl.devname, ctrl.cset_i, - ctrl.chan_i); - printf("Ctrl: seq %i, n %i, size %i, bits %i, " - "flags %08x (%s)\n", - ctrl.seq_num, - ctrl.nsamples, - ctrl.ssize, - ctrl.sbits, - ctrl.flags, - ctrl.flags & ZIO_CONTROL_LITTLE_ENDIAN - ? "little-endian" : - ctrl.flags & ZIO_CONTROL_BIG_ENDIAN - ? "big-endian" : "unknown-endian"); - printf("Ctrl: stamp %lli.%09lli (%lli)\n", - (long long)ctrl.tstamp.secs, - (long long)ctrl.tstamp.ticks, - (long long)ctrl.tstamp.bins); - /* FIXME: some control information is missing */ - - i = read(fd[FD_D], buf, sizeof(buf)); - if (i < 0) { - fprintf(stderr, "%s: %s: read(): %s\n", - argv[0], argv[1 + FD_D], strerror(errno)); - continue; /* next ctrl, let's see... */ - } - if (!i) { - fprintf(stderr, "%s: %s: unexpected EOF\n", - argv[0], argv[1 + FD_D]); + ready_set = control_set; + i = select(maxfd + 1, &ready_set, NULL, NULL, NULL); + if (i <0 && errno == EINTR) continue; + if (i < 0) { + fprintf(stderr, "%s: select(): %s\n", prgname, + strerror(errno)); + exit(1); } - if (i != ctrl.nsamples * ctrl.ssize) { - if (i == sizeof(buf)) { - fprintf(stderr, "%s: buffer too small\n", - argv[0]); - /* FIXME: empty the data channel */ - } else { - fprintf(stderr, "%s: ctrl: read %i bytes " - "(exp %i)\n", argv[0], i, - ctrl.nsamples * ctrl.ssize); - } - /* continue anyways */ - } - fwrite(buf, 1, i, f); - - /* report data to stdout */ - for (j = 0; j < i; j++) { - if (!(j & 0xf)) - printf("Data:"); - printf(" %02x", buf[j]); - if ((j & 0xf) == 0xf || j == i - 1) - putchar('\n'); - } - putchar('\n'); + for (j = 0; j < ndev; j++) + if (FD_ISSET(cfd[j], & ready_set)) + read_channel(cfd[j], dfd[j], f); } }