]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - text-utils/hexdump-display.c
2 * Copyright (c) 1989 The Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/param.h>
36 #include <sys/types.h>
49 static void doskip(const char *, int, struct hexdump
*);
50 static u_char
*get(struct hexdump
*);
52 enum _vflag vflag
= FIRST
;
54 static off_t address
; /* address/offset in stream */
55 static off_t eaddress
; /* end address */
57 static const char *color_cond(struct hexdump_pr
*pr
, unsigned char *bp
, int bcnt
)
59 register struct list_head
*p
;
60 register struct hexdump_clr
*clr
;
64 list_for_each(p
, pr
->colorlist
) {
65 clr
= list_entry(p
, struct hexdump_clr
, colorlist
);
69 /* no offset or offset outside this print unit */
72 if (offt
< address
|| offt
+ clr
->range
> address
+ bcnt
)
77 if (pr
->flags
== F_ADDRESS
) {
80 else if (!strncmp(clr
->str
, (char *)bp
+ offt
81 - address
, clr
->range
))
84 } else if (clr
->val
!= -1) {
86 /* addresses are not part of the input, so we can't
87 * compare with the contents of bp */
88 if (pr
->flags
== F_ADDRESS
) {
89 if (clr
->val
== address
)
92 memcpy(&val
, bp
+ offt
- address
, clr
->range
);
96 /* no conditions, only a color was specified */
100 /* return the format string or check for another */
101 if (match
^ clr
->invert
)
110 print(struct hexdump_pr
*pr
, unsigned char *bp
) {
112 const char *color
= NULL
;
114 if (pr
->colorlist
&& (color
= color_cond(pr
, bp
, pr
->bcnt
)))
119 printf(pr
->fmt
, address
);
128 printf(pr
->fmt
, *bp
);
136 memmove(&fval
, bp
, sizeof(fval
));
137 printf(pr
->fmt
, fval
);
140 memmove(&dval
, bp
, sizeof(dval
));
141 printf(pr
->fmt
, dval
);
148 short sval
; /* int16_t */
149 int ival
; /* int32_t */
150 long long Lval
; /* int64_t, int64_t */
154 printf(pr
->fmt
, (unsigned long long) *bp
);
157 memmove(&sval
, bp
, sizeof(sval
));
158 printf(pr
->fmt
, (unsigned long long) sval
);
161 memmove(&ival
, bp
, sizeof(ival
));
162 printf(pr
->fmt
, (unsigned long long) ival
);
165 memmove(&Lval
, bp
, sizeof(Lval
));
166 printf(pr
->fmt
, Lval
);
172 printf(pr
->fmt
, isprint(*bp
) ? *bp
: '.');
175 printf(pr
->fmt
, (char *)bp
);
178 printf("%s", pr
->fmt
);
185 unsigned short sval
; /* u_int16_t */
186 unsigned int ival
; /* u_int32_t */
187 unsigned long long Lval
;/* u_int64_t, u_int64_t */
191 printf(pr
->fmt
, (unsigned long long) *bp
);
194 memmove(&sval
, bp
, sizeof(sval
));
195 printf(pr
->fmt
, (unsigned long long) sval
);
198 memmove(&ival
, bp
, sizeof(ival
));
199 printf(pr
->fmt
, (unsigned long long) ival
);
202 memmove(&Lval
, bp
, sizeof(Lval
));
203 printf(pr
->fmt
, Lval
);
209 if (color
) /* did we colorize something? */
213 static void bpad(struct hexdump_pr
*pr
)
215 static const char *spec
= " -0+#";
219 * remove all conversion flags; '-' is the only one valid
220 * with %s, and it's not useful here.
231 while (*p1
&& strchr(spec
, *p1
))
234 while ((*p2
++ = *p1
++))
238 void display(struct hexdump
*hex
)
240 register struct list_head
*fs
;
241 register struct hexdump_fs
*fss
;
242 register struct hexdump_fu
*fu
;
243 register struct hexdump_pr
*pr
;
245 register unsigned char *bp
;
247 unsigned char savech
= 0, *savebp
;
248 struct list_head
*p
, *q
, *r
;
250 while ((bp
= get(hex
)) != NULL
) {
251 fs
= &hex
->fshead
; savebp
= bp
; saveaddress
= address
;
253 list_for_each(p
, fs
) {
254 fss
= list_entry(p
, struct hexdump_fs
, fslist
);
256 list_for_each(q
, &fss
->fulist
) {
257 fu
= list_entry(q
, struct hexdump_fu
, fulist
);
259 if (fu
->flags
&F_IGNORE
)
265 list_for_each(r
, &fu
->prlist
) {
266 pr
= list_entry(r
, struct hexdump_pr
, prlist
);
268 if (eaddress
&& address
>= eaddress
269 && !(pr
->flags
&(F_TEXT
|F_BPAD
)))
272 if (cnt
== 1 && pr
->nospace
) {
273 savech
= *pr
->nospace
;
276 *pr
->nospace
= savech
;
287 address
= saveaddress
;
292 * if eaddress not set, error or file size was multiple of
293 * blocksize, and no partial block ever found.
300 list_for_each (p
, &endfu
->prlist
) {
301 const char *color
= NULL
;
303 pr
= list_entry(p
, struct hexdump_pr
, prlist
);
304 if (colors_wanted() && pr
->colorlist
305 && (color
= color_cond(pr
, bp
, pr
->bcnt
))) {
311 printf(pr
->fmt
, eaddress
);
314 printf("%s", pr
->fmt
);
317 if (color
) /* did we highlight something? */
326 get(struct hexdump
*hex
)
328 static int ateof
= 1;
329 static u_char
*curp
, *savp
;
330 ssize_t n
, need
, nread
;
334 curp
= xcalloc(1, hex
->blocksize
);
335 savp
= xcalloc(1, hex
->blocksize
);
340 address
+= hex
->blocksize
;
342 need
= hex
->blocksize
, nread
= 0;
345 * if read the right number of bytes, or at EOF for one file,
346 * and no other files are available, zero-pad the rest of the
347 * block and set the end flag.
349 if (!hex
->length
|| (ateof
&& !next(NULL
, hex
))) {
350 if (need
== hex
->blocksize
)
352 if (!need
&& vflag
!= ALL
&&
353 !memcmp(curp
, savp
, nread
)) {
359 memset((char *)curp
+ nread
, 0, need
);
360 eaddress
= address
+ nread
;
363 if (fileno(stdin
) == -1) {
364 warnx(_("all input file arguments failed"));
367 n
= fread((char *)curp
+ nread
, sizeof(unsigned char),
368 hex
->length
== -1 ? need
: min(hex
->length
, need
), stdin
);
371 warn("%s", _argv
[-1]);
376 if (hex
->length
!= -1)
379 if (vflag
== ALL
|| vflag
== FIRST
||
380 memcmp(curp
, savp
, hex
->blocksize
) != 0) {
381 if (vflag
== DUP
|| vflag
== FIRST
)
388 address
+= hex
->blocksize
;
389 need
= hex
->blocksize
;
401 int next(char **argv
, struct hexdump
*hex
)
412 if (!(freopen(*_argv
, "r", stdin
))) {
414 hex
->exitval
= EXIT_FAILURE
;
425 doskip(statok
? *_argv
: "stdin", statok
, hex
);
435 doskip(const char *fname
, int statok
, struct hexdump
*hex
)
440 if (fstat(fileno(stdin
), &sbuf
))
441 err(EXIT_FAILURE
, "%s", fname
);
442 if (S_ISREG(sbuf
.st_mode
) && hex
->skip
> sbuf
.st_size
) {
443 /* If size valid and skip >= size */
444 hex
->skip
-= sbuf
.st_size
;
445 address
+= sbuf
.st_size
;
449 /* sbuf may be undefined here - do not test it */
450 if (fseek(stdin
, hex
->skip
, SEEK_SET
))
451 err(EXIT_FAILURE
, "%s", fname
);
452 address
+= hex
->skip
;