/*- * Copyright (c) 2015, 2016 Taylor R. Campbell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #define setprogname(argv0) ((void)0) #define getprogname() "dumpdesc" #include "descriptor.pb.h" #ifdef __GNUC__ #define GNUC_PREREQ(maj, min) \ ((__GNUC__ > (maj)) || \ ((__GNUC__ == (maj)) && (__GNUC_MINOR__ >= (min)))) #else #define GNUC_PREREQ(maj, min) 0 #endif #if GNUC_PREREQ(2,5) #define attr_noreturn __attribute__((__noreturn__)) #else #define attr_noreturn #endif static pb_decoder_callback_t decode_file_callback; static int decode_file_callback(void *cookie, void *buf, size_t *np) { FILE *file = cookie; size_t nreq, nread; nreq = *np; if (buf == NULL) { uint8_t scratch[BUFSIZ]; size_t nremain = nreq; while (nremain) { size_t nchunk = nremain; if (nchunk > sizeof scratch) nchunk = sizeof scratch; assert(0 < nchunk); nread = fread(scratch, 1, nchunk, file); assert(nread <= nchunk); assert(nchunk <= nremain); nremain -= nread; if (nread < nchunk) break; } nread = nreq - nremain; } else { nread = fread(buf, 1, nreq, file); } if (nread < nreq && ferror(file)) return errno; *np = nread; return 0; } static void attr_noreturn usage(void) { (void)fprintf(stderr, "Usage: %s [-bt]\n", getprogname()); exit(1); } int main(int argc, char **argv) { struct FileDescriptorSet descs; int bflag, tflag; int ch; int error; setprogname(argv[0]); if (signal(SIGPIPE, SIG_IGN)) err(1, "signal(SIGPIPE, SIG_IGN)"); bflag = 0; tflag = 0; while ((ch = getopt(argc, argv, "bt")) != -1) { switch (ch) { case 'b': if (tflag) { warnx("-b and -t are incompatible"); usage(); } bflag = 1; break; case 't': if (bflag) { warnx("-b and -t are incompatible"); usage(); } tflag = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc) usage(); if (!(bflag | tflag)) { warnx("one of -b or -t must be specified"); usage(); } pb_init(FileDescriptorSet(&descs)); error = pb_decode(FileDescriptorSet(&descs), &decode_file_callback, stdin); if (error) { errno = error; err(1, "decode"); } if (bflag) { void *buf; size_t n; error = pb_encoding_size(FileDescriptorSet(&descs), &n); if (error) { errno = error; err(1, "size"); } buf = malloc(n ? n : 1); if (buf == NULL) err(1, "malloc"); error = pb_encode_to_memory(FileDescriptorSet(&descs), buf, n); if (error) { errno = error; err(1, "encode"); } if (n && fwrite(buf, n, 1, stdout) < 1) err(1, "fwrite"); } else if (tflag) { error = pb_dump(stdout, FileDescriptorSet(&descs)); if (error) { errno = error; err(1, "dump"); } } else { assert(!"either bflag or tflag must have been specified"); } pb_destroy(FileDescriptorSet(&descs)); return 0; }