diff options
author | Ondrej Oprala | 2013-11-08 17:13:06 +0100 |
---|---|---|
committer | Karel Zak | 2013-12-02 13:44:17 +0100 |
commit | af324b1f72282ce4fa95546af0e865b46a10a457 (patch) | |
tree | f685e6392e937a54e7bd7cbe7332357860ffe078 /text-utils/hexdump-display.c | |
parent | script: check that stdin is a terminal (diff) | |
download | kernel-qcow2-util-linux-af324b1f72282ce4fa95546af0e865b46a10a457.tar.gz kernel-qcow2-util-linux-af324b1f72282ce4fa95546af0e865b46a10a457.tar.xz kernel-qcow2-util-linux-af324b1f72282ce4fa95546af0e865b46a10a457.zip |
hexdump: add the prefix 'hexdump-' to {conv,display,parse}.c
Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Diffstat (limited to 'text-utils/hexdump-display.c')
-rw-r--r-- | text-utils/hexdump-display.c | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/text-utils/hexdump-display.c b/text-utils/hexdump-display.c new file mode 100644 index 000000000..b6b1f140d --- /dev/null +++ b/text-utils/hexdump-display.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <sys/param.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "hexdump.h" +#include "xalloc.h" +#include "c.h" +#include "nls.h" + +static void doskip(const char *, int); +static u_char *get(void); + +enum _vflag vflag = FIRST; + +static off_t address; /* address/offset in stream */ +static off_t eaddress; /* end address */ + +static inline void +print(PR *pr, unsigned char *bp) { + + switch(pr->flags) { + case F_ADDRESS: + printf(pr->fmt, address); + break; + case F_BPAD: + printf(pr->fmt, ""); + break; + case F_C: + conv_c(pr, bp); + break; + case F_CHAR: + printf(pr->fmt, *bp); + break; + case F_DBL: + { + double dval; + float fval; + switch(pr->bcnt) { + case 4: + memmove(&fval, bp, sizeof(fval)); + printf(pr->fmt, fval); + break; + case 8: + memmove(&dval, bp, sizeof(dval)); + printf(pr->fmt, dval); + break; + } + break; + } + case F_INT: + { + short sval; /* int16_t */ + int ival; /* int32_t */ + long long Lval; /* int64_t, int64_t */ + + switch(pr->bcnt) { + case 1: + printf(pr->fmt, *bp); + break; + case 2: + memmove(&sval, bp, sizeof(sval)); + printf(pr->fmt, sval); + break; + case 4: + memmove(&ival, bp, sizeof(ival)); + printf(pr->fmt, ival); + break; + case 8: + memmove(&Lval, bp, sizeof(Lval)); + printf(pr->fmt, Lval); + break; + } + break; + } + case F_P: + printf(pr->fmt, isprint(*bp) ? *bp : '.'); + break; + case F_STR: + printf(pr->fmt, (char *)bp); + break; + case F_TEXT: + printf("%s", pr->fmt); + break; + case F_U: + conv_u(pr, bp); + break; + case F_UINT: + { + unsigned short sval; /* u_int16_t */ + unsigned int ival; /* u_int32_t */ + unsigned long long Lval;/* u_int64_t, u_int64_t */ + + switch(pr->bcnt) { + case 1: + printf(pr->fmt, *bp); + break; + case 2: + memmove(&sval, bp, sizeof(sval)); + printf(pr->fmt, sval); + break; + case 4: + memmove(&ival, bp, sizeof(ival)); + printf(pr->fmt, ival); + break; + case 8: + memmove(&Lval, bp, sizeof(Lval)); + printf(pr->fmt, Lval); + break; + } + break; + } + } +} + +static void bpad(PR *pr) +{ + static const char *spec = " -0+#"; + char *p1, *p2; + + /* + * remove all conversion flags; '-' is the only one valid + * with %s, and it's not useful here. + */ + pr->flags = F_BPAD; + pr->cchar[0] = 's'; + pr->cchar[1] = 0; + + p1 = pr->fmt; + while (*p1 != '%') + ++p1; + + p2 = ++p1; + while (*p1 && strchr(spec, *p1)) + ++p1; + + while ((*p2++ = *p1++)) + ; +} + +void display(void) +{ + register struct list_head *fs; + register FS *fss; + register FU *fu; + register PR *pr; + register int cnt; + register unsigned char *bp; + off_t saveaddress; + unsigned char savech = 0, *savebp; + struct list_head *p, *q, *r; + + while ((bp = get()) != NULL) { + fs = &fshead; savebp = bp; saveaddress = address; + + list_for_each(p, fs) { + fss = list_entry(p, FS, fslist); + + list_for_each(q, &fss->fulist) { + fu = list_entry(q, FU, fulist); + + if (fu->flags&F_IGNORE) + break; + + cnt = fu->reps; + + while (cnt) { + list_for_each(r, &fu->prlist) { + pr = list_entry(r, PR, prlist); + + if (eaddress && address >= eaddress + && !(pr->flags&(F_TEXT|F_BPAD))) + bpad(pr); + + if (cnt == 1 && pr->nospace) { + savech = *pr->nospace; + *pr->nospace = '\0'; + print(pr, bp); + *pr->nospace = savech; + } else + print(pr, bp); + + address += pr->bcnt; + bp += pr->bcnt; + } + --cnt; + } + } + bp = savebp; + address = saveaddress; + } + } + if (endfu) { + /* + * if eaddress not set, error or file size was multiple of + * blocksize, and no partial block ever found. + */ + if (!eaddress) { + if (!address) + return; + eaddress = address; + } + list_for_each (p, &endfu->prlist) { + pr = list_entry(p, PR, prlist); + switch(pr->flags) { + case F_ADDRESS: + printf(pr->fmt, eaddress); + break; + case F_TEXT: + printf("%s", pr->fmt); + break; + } + } + } +} + +static char **_argv; + +static u_char * +get(void) +{ + static int ateof = 1; + static u_char *curp, *savp; + ssize_t n, need, nread; + u_char *tmpp; + + if (!curp) { + curp = xcalloc(1, blocksize); + savp = xcalloc(1, blocksize); + } else { + tmpp = curp; + curp = savp; + savp = tmpp; + address += blocksize; + } + need = blocksize, nread = 0; + while (TRUE) { + /* + * if read the right number of bytes, or at EOF for one file, + * and no other files are available, zero-pad the rest of the + * block and set the end flag. + */ + if (!length || (ateof && !next(NULL))) { + if (need == blocksize) + goto retnul; + if (!need && vflag != ALL && + !memcmp(curp, savp, nread)) { + if (vflag != DUP) + printf("*\n"); + goto retnul; + } + if (need > 0) + memset((char *)curp + nread, 0, need); + eaddress = address + nread; + return(curp); + } + if (fileno(stdin) == -1) { + warnx(_("all input file arguments failed")); + goto retnul; + } + n = fread((char *)curp + nread, sizeof(unsigned char), + length == -1 ? need : min(length, need), stdin); + if (!n) { + if (ferror(stdin)) + warn("%s", _argv[-1]); + ateof = 1; + continue; + } + ateof = 0; + if (length != -1) + length -= n; + if (!(need -= n)) { + if (vflag == ALL || vflag == FIRST || + memcmp(curp, savp, blocksize)) { + if (vflag == DUP || vflag == FIRST) + vflag = WAIT; + return(curp); + } + if (vflag == WAIT) + printf("*\n"); + vflag = DUP; + address += blocksize; + need = blocksize; + nread = 0; + } + else + nread += n; + } +retnul: + free (curp); + free (savp); + return NULL; +} + +int next(char **argv) +{ + static int done; + int statok; + + if (argv) { + _argv = argv; + return(1); + } + while (TRUE) { + if (*_argv) { + if (!(freopen(*_argv, "r", stdin))) { + warn("%s", *_argv); + exitval = EXIT_FAILURE; + ++_argv; + continue; + } + statok = done = 1; + } else { + if (done++) + return(0); + statok = 0; + } + if (skip) + doskip(statok ? *_argv : "stdin", statok); + if (*_argv) + ++_argv; + if (!skip) + return(1); + } + /* NOTREACHED */ +} + +static void +doskip(const char *fname, int statok) +{ + struct stat sbuf; + + if (statok) { + if (fstat(fileno(stdin), &sbuf)) + err(EXIT_FAILURE, "%s", fname); + if (S_ISREG(sbuf.st_mode) && skip > sbuf.st_size) { + /* If size valid and skip >= size */ + skip -= sbuf.st_size; + address += sbuf.st_size; + return; + } + } + /* sbuf may be undefined here - do not test it */ + if (fseek(stdin, skip, SEEK_SET)) + err(EXIT_FAILURE, "%s", fname); + address += skip; + skip = 0; +} |