]> git.ipfire.org Git - thirdparty/util-linux.git/blame - text-utils/hexdump-display.c
libfdisk: (dos) accept start for log.partitions on template
[thirdparty/util-linux.git] / text-utils / hexdump-display.c
CommitLineData
6dbe3af9
KZ
1/*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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.
20 *
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
31 * SUCH DAMAGE.
32 */
33
6dbe3af9
KZ
34#include <sys/param.h>
35#include <sys/stat.h>
00c505d9 36#include <sys/types.h>
6dbe3af9
KZ
37#include <unistd.h>
38#include <errno.h>
39#include <ctype.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include "hexdump.h"
85bf44b7 44#include "xalloc.h"
3bbef076 45#include "c.h"
3c44e03f 46#include "nls.h"
098ab077 47#include "colors.h"
6dbe3af9 48
1f77e9c3
OO
49static void doskip(const char *, int, struct hexdump *);
50static u_char *get(struct hexdump *);
fd6b7a7f 51
6dbe3af9
KZ
52enum _vflag vflag = FIRST;
53
54static off_t address; /* address/offset in stream */
55static off_t eaddress; /* end address */
6dbe3af9 56
098ab077
OO
57static const char *color_cond(struct hexdump_pr *pr, unsigned char *bp, int bcnt)
58{
59 register struct list_head *p;
60 register struct hexdump_clr *clr;
61 off_t offt;
62 int match;
63
64 list_for_each(p, pr->colorlist) {
65 clr = list_entry(p, struct hexdump_clr, colorlist);
66 offt = clr->offt;
67 match = 0;
68
69 /* no offset or offset outside this print unit */
70 if (offt < 0)
71 offt = address;
72 if (offt < address || offt + clr->range > address + bcnt)
73 continue;
74
75 /* match a string */
76 if (clr->str) {
77 if (pr->flags == F_ADDRESS) {
78 /* TODO */
79 }
80 else if (!strncmp(clr->str, (char *)bp + offt
81 - address, clr->range))
82 match = 1;
83 /* match a value */
84 } else if (clr->val != -1) {
85 int val = 0;
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)
90 match = 1;
91 } else {
92 memcpy(&val, bp + offt - address, clr->range);
93 if (val == clr->val)
94 match = 1;
95 }
96 /* no conditions, only a color was specified */
97 } else
98 return clr->fmt;
99
100 /* return the format string or check for another */
101 if (match ^ clr->invert)
102 return clr->fmt;
103 continue;
104 }
105
106 /* no match */
107 return NULL;
108}
109
ffc43748 110static inline void
4c73d29c 111print(struct hexdump_pr *pr, unsigned char *bp) {
ffc43748 112
098ab077
OO
113 const char *color = NULL;
114
115 if (pr->colorlist && (color = color_cond(pr, bp, pr->bcnt)))
116 color_enable(color);
117
ffc43748
KZ
118 switch(pr->flags) {
119 case F_ADDRESS:
5988eede 120 printf(pr->fmt, address);
ffc43748
KZ
121 break;
122 case F_BPAD:
cbc6c0da 123 printf(pr->fmt, "");
ffc43748
KZ
124 break;
125 case F_C:
126 conv_c(pr, bp);
127 break;
128 case F_CHAR:
cbc6c0da 129 printf(pr->fmt, *bp);
ffc43748
KZ
130 break;
131 case F_DBL:
132 {
133 double dval;
134 float fval;
135 switch(pr->bcnt) {
136 case 4:
137 memmove(&fval, bp, sizeof(fval));
cbc6c0da 138 printf(pr->fmt, fval);
ffc43748
KZ
139 break;
140 case 8:
141 memmove(&dval, bp, sizeof(dval));
cbc6c0da 142 printf(pr->fmt, dval);
ffc43748
KZ
143 break;
144 }
145 break;
146 }
147 case F_INT:
148 {
149 short sval; /* int16_t */
150 int ival; /* int32_t */
95961ee2 151 long long Lval; /* int64_t, int64_t */
ffc43748
KZ
152
153 switch(pr->bcnt) {
154 case 1:
5500c817 155 printf(pr->fmt, (unsigned long long) *bp);
ffc43748
KZ
156 break;
157 case 2:
158 memmove(&sval, bp, sizeof(sval));
5500c817 159 printf(pr->fmt, (unsigned long long) sval);
ffc43748
KZ
160 break;
161 case 4:
162 memmove(&ival, bp, sizeof(ival));
5500c817 163 printf(pr->fmt, (unsigned long long) ival);
ffc43748
KZ
164 break;
165 case 8:
166 memmove(&Lval, bp, sizeof(Lval));
5988eede 167 printf(pr->fmt, Lval);
ffc43748
KZ
168 break;
169 }
170 break;
171 }
172 case F_P:
cbc6c0da 173 printf(pr->fmt, isprint(*bp) ? *bp : '.');
ffc43748
KZ
174 break;
175 case F_STR:
cbc6c0da 176 printf(pr->fmt, (char *)bp);
ffc43748
KZ
177 break;
178 case F_TEXT:
cbc6c0da 179 printf("%s", pr->fmt);
ffc43748
KZ
180 break;
181 case F_U:
182 conv_u(pr, bp);
183 break;
184 case F_UINT:
185 {
186 unsigned short sval; /* u_int16_t */
187 unsigned int ival; /* u_int32_t */
95961ee2 188 unsigned long long Lval;/* u_int64_t, u_int64_t */
ffc43748
KZ
189
190 switch(pr->bcnt) {
191 case 1:
5500c817 192 printf(pr->fmt, (unsigned long long) *bp);
ffc43748
KZ
193 break;
194 case 2:
195 memmove(&sval, bp, sizeof(sval));
5500c817 196 printf(pr->fmt, (unsigned long long) sval);
ffc43748
KZ
197 break;
198 case 4:
199 memmove(&ival, bp, sizeof(ival));
5500c817 200 printf(pr->fmt, (unsigned long long) ival);
ffc43748
KZ
201 break;
202 case 8:
203 memmove(&Lval, bp, sizeof(Lval));
5988eede 204 printf(pr->fmt, Lval);
ffc43748
KZ
205 break;
206 }
207 break;
208 }
209 }
098ab077
OO
210 if (color) /* did we colorize something? */
211 color_disable();
6dbe3af9
KZ
212}
213
4c73d29c 214static void bpad(struct hexdump_pr *pr)
fd6b7a7f 215{
ffc43748
KZ
216 static const char *spec = " -0+#";
217 char *p1, *p2;
fd6b7a7f
KZ
218
219 /*
220 * remove all conversion flags; '-' is the only one valid
221 * with %s, and it's not useful here.
222 */
223 pr->flags = F_BPAD;
ffc43748
KZ
224 pr->cchar[0] = 's';
225 pr->cchar[1] = 0;
d6e5614e
OO
226
227 p1 = pr->fmt;
228 while (*p1 != '%')
229 ++p1;
230
231 p2 = ++p1;
232 while (*p1 && strchr(spec, *p1))
233 ++p1;
234
235 while ((*p2++ = *p1++))
236 ;
fd6b7a7f
KZ
237}
238
1f77e9c3 239void display(struct hexdump *hex)
6dbe3af9 240{
cbc6c0da 241 register struct list_head *fs;
bb8ae572 242 register struct hexdump_fs *fss;
046921da 243 register struct hexdump_fu *fu;
4c73d29c 244 register struct hexdump_pr *pr;
6dbe3af9 245 register int cnt;
95961ee2 246 register unsigned char *bp;
6dbe3af9 247 off_t saveaddress;
95961ee2 248 unsigned char savech = 0, *savebp;
9db51207 249 struct list_head *p, *q, *r;
6dbe3af9 250
1f77e9c3
OO
251 while ((bp = get(hex)) != NULL) {
252 fs = &hex->fshead; savebp = bp; saveaddress = address;
cda43391 253
9db51207 254 list_for_each(p, fs) {
bb8ae572 255 fss = list_entry(p, struct hexdump_fs, fslist);
cda43391 256
bbc8c153 257 list_for_each(q, &fss->fulist) {
046921da 258 fu = list_entry(q, struct hexdump_fu, fulist);
cda43391 259
9db51207
OO
260 if (fu->flags&F_IGNORE)
261 break;
cda43391 262
9db51207 263 cnt = fu->reps;
cda43391 264
9db51207 265 while (cnt) {
bbc8c153 266 list_for_each(r, &fu->prlist) {
4c73d29c 267 pr = list_entry(r, struct hexdump_pr, prlist);
cda43391
OO
268
269 if (eaddress && address >= eaddress
270 && !(pr->flags&(F_TEXT|F_BPAD)))
271 bpad(pr);
272
273 if (cnt == 1 && pr->nospace) {
274 savech = *pr->nospace;
275 *pr->nospace = '\0';
276 print(pr, bp);
277 *pr->nospace = savech;
278 } else
279 print(pr, bp);
280
281 address += pr->bcnt;
282 bp += pr->bcnt;
9db51207
OO
283 }
284 --cnt;
285 }
286 }
cda43391
OO
287 bp = savebp;
288 address = saveaddress;
9db51207
OO
289 }
290 }
6dbe3af9
KZ
291 if (endfu) {
292 /*
293 * if eaddress not set, error or file size was multiple of
294 * blocksize, and no partial block ever found.
295 */
296 if (!eaddress) {
297 if (!address)
298 return;
299 eaddress = address;
300 }
bbc8c153 301 list_for_each (p, &endfu->prlist) {
098ab077 302 const char *color = NULL;
c308e205
SK
303
304 pr = list_entry(p, struct hexdump_pr, prlist);
098ab077
OO
305 if (colors_wanted() && pr->colorlist
306 && (color = color_cond(pr, bp, pr->bcnt))) {
307 color_enable(color);
308 }
309
6dbe3af9
KZ
310 switch(pr->flags) {
311 case F_ADDRESS:
5988eede 312 printf(pr->fmt, eaddress);
6dbe3af9
KZ
313 break;
314 case F_TEXT:
9db51207 315 printf("%s", pr->fmt);
6dbe3af9
KZ
316 break;
317 }
098ab077
OO
318 if (color) /* did we highlight something? */
319 color_disable();
9db51207 320 }
6dbe3af9
KZ
321 }
322}
323
6dbe3af9
KZ
324static char **_argv;
325
22853e4a 326static u_char *
1f77e9c3 327get(struct hexdump *hex)
6dbe3af9 328{
6dbe3af9
KZ
329 static int ateof = 1;
330 static u_char *curp, *savp;
b6b0ea09 331 ssize_t n, need, nread;
6dbe3af9
KZ
332 u_char *tmpp;
333
334 if (!curp) {
1f77e9c3
OO
335 curp = xcalloc(1, hex->blocksize);
336 savp = xcalloc(1, hex->blocksize);
6dbe3af9
KZ
337 } else {
338 tmpp = curp;
339 curp = savp;
340 savp = tmpp;
1f77e9c3 341 address += hex->blocksize;
6dbe3af9 342 }
1f77e9c3 343 need = hex->blocksize, nread = 0;
f77ad413 344 while (TRUE) {
6dbe3af9
KZ
345 /*
346 * if read the right number of bytes, or at EOF for one file,
347 * and no other files are available, zero-pad the rest of the
348 * block and set the end flag.
349 */
1f77e9c3
OO
350 if (!hex->length || (ateof && !next(NULL, hex))) {
351 if (need == hex->blocksize)
d2740b0e 352 goto retnul;
ffc43748
KZ
353 if (!need && vflag != ALL &&
354 !memcmp(curp, savp, nread)) {
6dbe3af9 355 if (vflag != DUP)
cbc6c0da 356 printf("*\n");
d2740b0e 357 goto retnul;
6dbe3af9 358 }
42c9ce52
KZ
359 if (need > 0)
360 memset((char *)curp + nread, 0, need);
6dbe3af9
KZ
361 eaddress = address + nread;
362 return(curp);
363 }
3c44e03f
SK
364 if (fileno(stdin) == -1) {
365 warnx(_("all input file arguments failed"));
d2740b0e 366 goto retnul;
3c44e03f 367 }
95961ee2 368 n = fread((char *)curp + nread, sizeof(unsigned char),
1f77e9c3 369 hex->length == -1 ? need : min(hex->length, need), stdin);
6dbe3af9
KZ
370 if (!n) {
371 if (ferror(stdin))
85bf44b7 372 warn("%s", _argv[-1]);
6dbe3af9
KZ
373 ateof = 1;
374 continue;
375 }
376 ateof = 0;
1f77e9c3
OO
377 if (hex->length != -1)
378 hex->length -= n;
6dbe3af9
KZ
379 if (!(need -= n)) {
380 if (vflag == ALL || vflag == FIRST ||
1f77e9c3 381 memcmp(curp, savp, hex->blocksize)) {
6dbe3af9
KZ
382 if (vflag == DUP || vflag == FIRST)
383 vflag = WAIT;
384 return(curp);
385 }
386 if (vflag == WAIT)
cbc6c0da 387 printf("*\n");
6dbe3af9 388 vflag = DUP;
1f77e9c3
OO
389 address += hex->blocksize;
390 need = hex->blocksize;
6dbe3af9
KZ
391 nread = 0;
392 }
393 else
394 nread += n;
395 }
d2740b0e
OO
396retnul:
397 free (curp);
398 free (savp);
399 return NULL;
6dbe3af9
KZ
400}
401
1f77e9c3 402int next(char **argv, struct hexdump *hex)
6dbe3af9 403{
6dbe3af9 404 static int done;
4ccf1137 405 int statok;
6dbe3af9
KZ
406
407 if (argv) {
408 _argv = argv;
409 return(1);
410 }
c889d525 411 while (TRUE) {
6dbe3af9
KZ
412 if (*_argv) {
413 if (!(freopen(*_argv, "r", stdin))) {
85bf44b7 414 warn("%s", *_argv);
1f77e9c3 415 hex->exitval = EXIT_FAILURE;
6dbe3af9
KZ
416 ++_argv;
417 continue;
418 }
419 statok = done = 1;
420 } else {
421 if (done++)
4ccf1137 422 return(0);
6dbe3af9
KZ
423 statok = 0;
424 }
1f77e9c3
OO
425 if (hex->skip)
426 doskip(statok ? *_argv : "stdin", statok, hex);
6dbe3af9
KZ
427 if (*_argv)
428 ++_argv;
1f77e9c3 429 if (!hex->skip)
6dbe3af9
KZ
430 return(1);
431 }
432 /* NOTREACHED */
433}
434
fd6b7a7f 435static void
1f77e9c3 436doskip(const char *fname, int statok, struct hexdump *hex)
6dbe3af9 437{
6dbe3af9
KZ
438 struct stat sbuf;
439
440 if (statok) {
85bf44b7
SK
441 if (fstat(fileno(stdin), &sbuf))
442 err(EXIT_FAILURE, "%s", fname);
1f77e9c3 443 if (S_ISREG(sbuf.st_mode) && hex->skip > sbuf.st_size) {
fd6b7a7f 444 /* If size valid and skip >= size */
1f77e9c3 445 hex->skip -= sbuf.st_size;
6dbe3af9
KZ
446 address += sbuf.st_size;
447 return;
448 }
449 }
ffc43748 450 /* sbuf may be undefined here - do not test it */
1f77e9c3 451 if (fseek(stdin, hex->skip, SEEK_SET))
85bf44b7 452 err(EXIT_FAILURE, "%s", fname);
1f77e9c3
OO
453 address += hex->skip;
454 hex->skip = 0;
6dbe3af9 455}