source: MondoRescue/branches/stable/mindi-busybox/libbb/dump.c

Last change on this file was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File size: 18.9 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Support code for the hexdump and od applets,
4 * based on code from util-linux v 2.11l
5 *
6 * Copyright (c) 1989
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
10 *
11 * Original copyright notice is retained at the end of this file.
12 */
13
14#include "libbb.h"
15#include "dump.h"
16
17enum _vflag bb_dump_vflag = FIRST;
18FS *bb_dump_fshead; /* head of format strings */
19static FU *endfu;
20static char **_argv;
21static off_t savaddress; /* saved address/offset in stream */
22static off_t eaddress; /* end address */
23static off_t address; /* address/offset in stream */
24off_t bb_dump_skip; /* bytes to skip */
25static int exitval; /* final exit value */
26int bb_dump_blocksize; /* data block size */
27int bb_dump_length = -1; /* max bytes to read */
28
29static const char index_str[] ALIGN1 = ".#-+ 0123456789";
30
31static const char size_conv_str[] ALIGN1 =
32"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
33
34static const char lcc[] ALIGN1 = "diouxX";
35
36int bb_dump_size(FS * fs)
37{
38 FU *fu;
39 int bcnt, cur_size;
40 char *fmt;
41 const char *p;
42 int prec;
43
44 /* figure out the data block bb_dump_size needed for each format unit */
45 for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
46 if (fu->bcnt) {
47 cur_size += fu->bcnt * fu->reps;
48 continue;
49 }
50 for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
51 if (*fmt != '%')
52 continue;
53 /*
54 * bb_dump_skip any special chars -- save precision in
55 * case it's a %s format.
56 */
57 while (strchr(index_str + 1, *++fmt));
58 if (*fmt == '.' && isdigit(*++fmt)) {
59 prec = atoi(fmt);
60 while (isdigit(*++fmt));
61 }
62 if (!(p = strchr(size_conv_str + 12, *fmt))) {
63 if (*fmt == 's') {
64 bcnt += prec;
65 } else if (*fmt == '_') {
66 ++fmt;
67 if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) {
68 bcnt += 1;
69 }
70 }
71 } else {
72 bcnt += size_conv_str[p - (size_conv_str + 12)];
73 }
74 }
75 cur_size += bcnt * fu->reps;
76 }
77 return cur_size;
78}
79
80static void rewrite(FS * fs)
81{
82 enum { NOTOKAY, USEBCNT, USEPREC } sokay;
83 PR *pr, **nextpr = NULL;
84 FU *fu;
85 char *p1, *p2, *p3;
86 char savech, *fmtp;
87 const char *byte_count_str;
88 int nconv, prec = 0;
89
90 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
91 /*
92 * break each format unit into print units; each
93 * conversion character gets its own.
94 */
95 for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
96 /* NOSTRICT */
97 /* DBU:[dvae@cray.com] calloc so that forward ptrs start out NULL*/
98 pr = xzalloc(sizeof(PR));
99 if (!fu->nextpr)
100 fu->nextpr = pr;
101 /* ignore nextpr -- its unused inside the loop and is
102 * uninitialized 1st time thru.
103 */
104
105 /* bb_dump_skip preceding text and up to the next % sign */
106 for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
107
108 /* only text in the string */
109 if (!*p1) {
110 pr->fmt = fmtp;
111 pr->flags = F_TEXT;
112 break;
113 }
114
115 /*
116 * get precision for %s -- if have a byte count, don't
117 * need it.
118 */
119 if (fu->bcnt) {
120 sokay = USEBCNT;
121 /* bb_dump_skip to conversion character */
122 for (++p1; strchr(index_str, *p1); ++p1);
123 } else {
124 /* bb_dump_skip any special chars, field width */
125 while (strchr(index_str + 1, *++p1));
126 if (*p1 == '.' && isdigit(*++p1)) {
127 sokay = USEPREC;
128 prec = atoi(p1);
129 while (isdigit(*++p1));
130 } else
131 sokay = NOTOKAY;
132 }
133
134 p2 = p1 + 1; /* set end pointer */
135
136 /*
137 * figure out the byte count for each conversion;
138 * rewrite the format as necessary, set up blank-
139 * pbb_dump_adding for end of data.
140 */
141
142 if (*p1 == 'c') {
143 pr->flags = F_CHAR;
144 DO_BYTE_COUNT_1:
145 byte_count_str = "\001";
146 DO_BYTE_COUNT:
147 if (fu->bcnt) {
148 do {
149 if (fu->bcnt == *byte_count_str) {
150 break;
151 }
152 } while (*++byte_count_str);
153 }
154 /* Unlike the original, output the remainder of the format string. */
155 if (!*byte_count_str) {
156 bb_error_msg_and_die("bad byte count for conversion character %s", p1);
157 }
158 pr->bcnt = *byte_count_str;
159 } else if (*p1 == 'l') {
160 ++p2;
161 ++p1;
162 DO_INT_CONV:
163 {
164 const char *e;
165 if (!(e = strchr(lcc, *p1))) {
166 goto DO_BAD_CONV_CHAR;
167 }
168 pr->flags = F_INT;
169 if (e > lcc + 1) {
170 pr->flags = F_UINT;
171 }
172 byte_count_str = "\004\002\001";
173 goto DO_BYTE_COUNT;
174 }
175 /* NOTREACHED */
176 } else if (strchr(lcc, *p1)) {
177 goto DO_INT_CONV;
178 } else if (strchr("eEfgG", *p1)) {
179 pr->flags = F_DBL;
180 byte_count_str = "\010\004";
181 goto DO_BYTE_COUNT;
182 } else if (*p1 == 's') {
183 pr->flags = F_STR;
184 if (sokay == USEBCNT) {
185 pr->bcnt = fu->bcnt;
186 } else if (sokay == USEPREC) {
187 pr->bcnt = prec;
188 } else { /* NOTOKAY */
189 bb_error_msg_and_die("%%s requires a precision or a byte count");
190 }
191 } else if (*p1 == '_') {
192 ++p2;
193 switch (p1[1]) {
194 case 'A':
195 endfu = fu;
196 fu->flags |= F_IGNORE;
197 /* FALLTHROUGH */
198 case 'a':
199 pr->flags = F_ADDRESS;
200 ++p2;
201 if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
202 goto DO_BAD_CONV_CHAR;
203 }
204 *p1 = p1[2];
205 break;
206 case 'c':
207 pr->flags = F_C;
208 /* *p1 = 'c'; set in conv_c */
209 goto DO_BYTE_COUNT_1;
210 case 'p':
211 pr->flags = F_P;
212 *p1 = 'c';
213 goto DO_BYTE_COUNT_1;
214 case 'u':
215 pr->flags = F_U;
216 /* *p1 = 'c'; set in conv_u */
217 goto DO_BYTE_COUNT_1;
218 default:
219 goto DO_BAD_CONV_CHAR;
220 }
221 } else {
222 DO_BAD_CONV_CHAR:
223 bb_error_msg_and_die("bad conversion character %%%s", p1);
224 }
225
226 /*
227 * copy to PR format string, set conversion character
228 * pointer, update original.
229 */
230 savech = *p2;
231 p1[1] = '\0';
232 pr->fmt = xstrdup(fmtp);
233 *p2 = savech;
234 pr->cchar = pr->fmt + (p1 - fmtp);
235
236 /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost.
237 * Skip subsequent text and up to the next % sign and tack the
238 * additional text onto fmt: eg. if fmt is "%x is a HEX number",
239 * we lose the " is a HEX number" part of fmt.
240 */
241 for (p3 = p2; *p3 && *p3 != '%'; p3++);
242 if (p3 > p2)
243 {
244 savech = *p3;
245 *p3 = '\0';
246 pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt)+(p3-p2)+1);
247 strcat(pr->fmt, p2);
248 *p3 = savech;
249 p2 = p3;
250 }
251
252 fmtp = p2;
253
254 /* only one conversion character if byte count */
255 if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) {
256 bb_error_msg_and_die("byte count with multiple conversion characters");
257 }
258 }
259 /*
260 * if format unit byte count not specified, figure it out
261 * so can adjust rep count later.
262 */
263 if (!fu->bcnt)
264 for (pr = fu->nextpr; pr; pr = pr->nextpr)
265 fu->bcnt += pr->bcnt;
266 }
267 /*
268 * if the format string interprets any data at all, and it's
269 * not the same as the bb_dump_blocksize, and its last format unit
270 * interprets any data at all, and has no iteration count,
271 * repeat it as necessary.
272 *
273 * if, rep count is greater than 1, no trailing whitespace
274 * gets output from the last iteration of the format unit.
275 */
276 for (fu = fs->nextfu;; fu = fu->nextfu) {
277 if (!fu->nextfu && fs->bcnt < bb_dump_blocksize &&
278 !(fu->flags & F_SETREP) && fu->bcnt)
279 fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt;
280 if (fu->reps > 1) {
281 for (pr = fu->nextpr;; pr = pr->nextpr)
282 if (!pr->nextpr)
283 break;
284 for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
285 p2 = isspace(*p1) ? p1 : NULL;
286 if (p2)
287 pr->nospace = p2;
288 }
289 if (!fu->nextfu)
290 break;
291 }
292}
293
294static void do_skip(const char *fname, int statok)
295{
296 struct stat sbuf;
297
298 if (statok) {
299 if (fstat(STDIN_FILENO, &sbuf)) {
300 bb_perror_msg_and_die("%s", fname);
301 }
302 if ((!(S_ISCHR(sbuf.st_mode) ||
303 S_ISBLK(sbuf.st_mode) ||
304 S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) {
305 /* If bb_dump_size valid and bb_dump_skip >= size */
306 bb_dump_skip -= sbuf.st_size;
307 address += sbuf.st_size;
308 return;
309 }
310 }
311 if (fseek(stdin, bb_dump_skip, SEEK_SET)) {
312 bb_perror_msg_and_die("%s", fname);
313 }
314 savaddress = address += bb_dump_skip;
315 bb_dump_skip = 0;
316}
317
318static int next(char **argv)
319{
320 static smallint done;
321
322 int statok;
323
324 if (argv) {
325 _argv = argv;
326 return 1;
327 }
328 for (;;) {
329 if (*_argv) {
330 if (!(freopen(*_argv, "r", stdin))) {
331 bb_perror_msg("%s", *_argv);
332 exitval = 1;
333 ++_argv;
334 continue;
335 }
336 done = statok = 1;
337 } else {
338 if (done)
339 return 0;
340 done = 1;
341 statok = 0;
342 }
343 if (bb_dump_skip)
344 do_skip(statok ? *_argv : "stdin", statok);
345 if (*_argv)
346 ++_argv;
347 if (!bb_dump_skip)
348 return 1;
349 }
350 /* NOTREACHED */
351}
352
353static unsigned char *get(void)
354{
355 static smallint ateof = 1;
356 static unsigned char *curp = NULL, *savp; /*DBU:[dave@cray.com]initialize curp */
357
358 int n;
359 int need, nread;
360 unsigned char *tmpp;
361
362 if (!curp) {
363 address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/
364 curp = xmalloc(bb_dump_blocksize);
365 savp = xmalloc(bb_dump_blocksize);
366 } else {
367 tmpp = curp;
368 curp = savp;
369 savp = tmpp;
370 address = savaddress += bb_dump_blocksize;
371 }
372 for (need = bb_dump_blocksize, nread = 0;;) {
373 /*
374 * if read the right number of bytes, or at EOF for one file,
375 * and no other files are available, zero-pad the rest of the
376 * block and set the end flag.
377 */
378 if (!bb_dump_length || (ateof && !next((char **) NULL))) {
379 if (need == bb_dump_blocksize) {
380 return NULL;
381 }
382 if (bb_dump_vflag != ALL && !memcmp(curp, savp, nread)) {
383 if (bb_dump_vflag != DUP) {
384 puts("*");
385 }
386 return NULL;
387 }
388 memset((char *) curp + nread, 0, need);
389 eaddress = address + nread;
390 return curp;
391 }
392 n = fread((char *) curp + nread, sizeof(unsigned char),
393 bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin);
394 if (!n) {
395 if (ferror(stdin)) {
396 bb_perror_msg("%s", _argv[-1]);
397 }
398 ateof = 1;
399 continue;
400 }
401 ateof = 0;
402 if (bb_dump_length != -1) {
403 bb_dump_length -= n;
404 }
405 need -= n;
406 if (!need) {
407 if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST
408 || memcmp(curp, savp, bb_dump_blocksize)) {
409 if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) {
410 bb_dump_vflag = WAIT;
411 }
412 return curp;
413 }
414 if (bb_dump_vflag == WAIT) {
415 puts("*");
416 }
417 bb_dump_vflag = DUP;
418 address = savaddress += bb_dump_blocksize;
419 need = bb_dump_blocksize;
420 nread = 0;
421 } else {
422 nread += n;
423 }
424 }
425}
426
427static void bpad(PR * pr)
428{
429 char *p1, *p2;
430
431 /*
432 * remove all conversion flags; '-' is the only one valid
433 * with %s, and it's not useful here.
434 */
435 pr->flags = F_BPAD;
436 *pr->cchar = 's';
437 for (p1 = pr->fmt; *p1 != '%'; ++p1);
438 for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1)
439 if (pr->nospace) pr->nospace--;
440 while ((*p2++ = *p1++) != 0);
441}
442
443static const char conv_str[] ALIGN1 =
444 "\0\\0\0"
445 "\007\\a\0" /* \a */
446 "\b\\b\0"
447 "\f\\b\0"
448 "\n\\n\0"
449 "\r\\r\0"
450 "\t\\t\0"
451 "\v\\v\0"
452 ;
453
454
455static void conv_c(PR * pr, unsigned char * p)
456{
457 const char *str = conv_str;
458 char buf[10];
459
460 do {
461 if (*p == *str) {
462 ++str;
463 goto strpr;
464 }
465 str += 4;
466 } while (*str);
467
468 if (isprint(*p)) {
469 *pr->cchar = 'c';
470 (void) printf(pr->fmt, *p);
471 } else {
472 sprintf(buf, "%03o", (int) *p);
473 str = buf;
474 strpr:
475 *pr->cchar = 's';
476 printf(pr->fmt, str);
477 }
478}
479
480static void conv_u(PR * pr, unsigned char * p)
481{
482 static const char list[] ALIGN1 =
483 "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0"
484 "bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_"
485 "dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0"
486 "can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us";
487
488 /* od used nl, not lf */
489 if (*p <= 0x1f) {
490 *pr->cchar = 's';
491 printf(pr->fmt, list + (4 * (int)*p));
492 } else if (*p == 0x7f) {
493 *pr->cchar = 's';
494 printf(pr->fmt, "del");
495 } else if (isprint(*p)) {
496 *pr->cchar = 'c';
497 printf(pr->fmt, *p);
498 } else {
499 *pr->cchar = 'x';
500 printf(pr->fmt, (int) *p);
501 }
502}
503
504static void display(void)
505{
506/* extern FU *endfu; */
507 FS *fs;
508 FU *fu;
509 PR *pr;
510 int cnt;
511 unsigned char *bp;
512
513 off_t saveaddress;
514 unsigned char savech = 0, *savebp;
515
516 while ((bp = get()) != NULL) {
517 for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs;
518 fs = fs->nextfs, bp = savebp, address = saveaddress) {
519 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
520 if (fu->flags & F_IGNORE) {
521 break;
522 }
523 for (cnt = fu->reps; cnt; --cnt) {
524 for (pr = fu->nextpr; pr; address += pr->bcnt,
525 bp += pr->bcnt, pr = pr->nextpr) {
526 if (eaddress && address >= eaddress &&
527 !(pr->flags & (F_TEXT | F_BPAD))) {
528 bpad(pr);
529 }
530 if (cnt == 1 && pr->nospace) {
531 savech = *pr->nospace;
532 *pr->nospace = '\0';
533 }
534/* PRINT; */
535 switch (pr->flags) {
536 case F_ADDRESS:
537 printf(pr->fmt, (unsigned int) address);
538 break;
539 case F_BPAD:
540 printf(pr->fmt, "");
541 break;
542 case F_C:
543 conv_c(pr, bp);
544 break;
545 case F_CHAR:
546 printf(pr->fmt, *bp);
547 break;
548 case F_DBL:{
549 double dval;
550 float fval;
551
552 switch (pr->bcnt) {
553 case 4:
554 memmove((char *) &fval, (char *) bp,
555 sizeof(fval));
556 printf(pr->fmt, fval);
557 break;
558 case 8:
559 memmove((char *) &dval, (char *) bp,
560 sizeof(dval));
561 printf(pr->fmt, dval);
562 break;
563 }
564 break;
565 }
566 case F_INT:{
567 int ival;
568 short sval;
569
570 switch (pr->bcnt) {
571 case 1:
572 printf(pr->fmt, (int) *bp);
573 break;
574 case 2:
575 memmove((char *) &sval, (char *) bp,
576 sizeof(sval));
577 printf(pr->fmt, (int) sval);
578 break;
579 case 4:
580 memmove((char *) &ival, (char *) bp,
581 sizeof(ival));
582 printf(pr->fmt, ival);
583 break;
584 }
585 break;
586 }
587 case F_P:
588 printf(pr->fmt, isprint(*bp) ? *bp : '.');
589 break;
590 case F_STR:
591 printf(pr->fmt, (char *) bp);
592 break;
593 case F_TEXT:
594 printf(pr->fmt);
595 break;
596 case F_U:
597 conv_u(pr, bp);
598 break;
599 case F_UINT:{
600 unsigned int ival;
601 unsigned short sval;
602
603 switch (pr->bcnt) {
604 case 1:
605 printf(pr->fmt, (unsigned int) * bp);
606 break;
607 case 2:
608 memmove((char *) &sval, (char *) bp,
609 sizeof(sval));
610 printf(pr->fmt, (unsigned int) sval);
611 break;
612 case 4:
613 memmove((char *) &ival, (char *) bp,
614 sizeof(ival));
615 printf(pr->fmt, ival);
616 break;
617 }
618 break;
619 }
620 }
621 if (cnt == 1 && pr->nospace) {
622 *pr->nospace = savech;
623 }
624 }
625 }
626 }
627 }
628 }
629 if (endfu) {
630 /*
631 * if eaddress not set, error or file bb_dump_size was multiple of
632 * bb_dump_blocksize, and no partial block ever found.
633 */
634 if (!eaddress) {
635 if (!address) {
636 return;
637 }
638 eaddress = address;
639 }
640 for (pr = endfu->nextpr; pr; pr = pr->nextpr) {
641 switch (pr->flags) {
642 case F_ADDRESS:
643 (void) printf(pr->fmt, (unsigned int) eaddress);
644 break;
645 case F_TEXT:
646 (void) printf(pr->fmt);
647 break;
648 }
649 }
650 }
651}
652
653int bb_dump_dump(char **argv)
654{
655 FS *tfs;
656
657 /* figure out the data block bb_dump_size */
658 for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
659 tfs->bcnt = bb_dump_size(tfs);
660 if (bb_dump_blocksize < tfs->bcnt) {
661 bb_dump_blocksize = tfs->bcnt;
662 }
663 }
664 /* rewrite the rules, do syntax checking */
665 for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
666 rewrite(tfs);
667 }
668
669 next(argv);
670 display();
671
672 return exitval;
673}
674
675void bb_dump_add(const char *fmt)
676{
677 const char *p;
678 char *p1;
679 char *p2;
680 static FS **nextfs;
681 FS *tfs;
682 FU *tfu, **nextfu;
683 const char *savep;
684
685 /* start new linked list of format units */
686 tfs = xzalloc(sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */
687 if (!bb_dump_fshead) {
688 bb_dump_fshead = tfs;
689 } else {
690 *nextfs = tfs;
691 }
692 nextfs = &tfs->nextfs;
693 nextfu = &tfs->nextfu;
694
695 /* take the format string and break it up into format units */
696 for (p = fmt;;) {
697 /* bb_dump_skip leading white space */
698 p = skip_whitespace(p);
699 if (!*p) {
700 break;
701 }
702
703 /* allocate a new format unit and link it in */
704 /* NOSTRICT */
705 /* DBU:[dave@cray.com] calloc so that forward pointers start out NULL */
706 tfu = xzalloc(sizeof(FU));
707 *nextfu = tfu;
708 nextfu = &tfu->nextfu;
709 tfu->reps = 1;
710
711 /* if leading digit, repetition count */
712 if (isdigit(*p)) {
713 for (savep = p; isdigit(*p); ++p);
714 if (!isspace(*p) && *p != '/') {
715 bb_error_msg_and_die("bad format {%s}", fmt);
716 }
717 /* may overwrite either white space or slash */
718 tfu->reps = atoi(savep);
719 tfu->flags = F_SETREP;
720 /* bb_dump_skip trailing white space */
721 p = skip_whitespace(++p);
722 }
723
724 /* bb_dump_skip slash and trailing white space */
725 if (*p == '/') {
726 p = skip_whitespace(++p);
727 }
728
729 /* byte count */
730 if (isdigit(*p)) {
731// TODO: use bb_strtou
732 savep = p;
733 do p++; while (isdigit(*p));
734 if (!isspace(*p)) {
735 bb_error_msg_and_die("bad format {%s}", fmt);
736 }
737 tfu->bcnt = atoi(savep);
738 /* bb_dump_skip trailing white space */
739 p = skip_whitespace(++p);
740 }
741
742 /* format */
743 if (*p != '"') {
744 bb_error_msg_and_die("bad format {%s}", fmt);
745 }
746 for (savep = ++p; *p != '"';) {
747 if (*p++ == 0) {
748 bb_error_msg_and_die("bad format {%s}", fmt);
749 }
750 }
751 tfu->fmt = xmalloc(p - savep + 1);
752 strncpy(tfu->fmt, savep, p - savep);
753 tfu->fmt[p - savep] = '\0';
754/* escape(tfu->fmt); */
755
756 p1 = tfu->fmt;
757
758 /* alphabetic escape sequences have to be done in place */
759 for (p2 = p1;; ++p1, ++p2) {
760 if (!*p1) {
761 *p2 = *p1;
762 break;
763 }
764 if (*p1 == '\\') {
765 const char *cs = conv_str + 4;
766 ++p1;
767 *p2 = *p1;
768 do {
769 if (*p1 == cs[2]) {
770 *p2 = cs[0];
771 break;
772 }
773 cs += 4;
774 } while (*cs);
775 }
776 }
777
778 p++;
779 }
780}
781
782/*
783 * Copyright (c) 1989 The Regents of the University of California.
784 * All rights reserved.
785 *
786 * Redistribution and use in source and binary forms, with or without
787 * modification, are permitted provided that the following conditions
788 * are met:
789 * 1. Redistributions of source code must retain the above copyright
790 * notice, this list of conditions and the following disclaimer.
791 * 2. Redistributions in binary form must reproduce the above copyright
792 * notice, this list of conditions and the following disclaimer in the
793 * documentation and/or other materials provided with the distribution.
794 * 3. Neither the name of the University nor the names of its contributors
795 * may be used to endorse or promote products derived from this software
796 * without specific prior written permission.
797 *
798 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
799 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
800 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
801 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
802 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
803 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
804 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
805 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
806 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
807 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
808 * SUCH DAMAGE.
809 */
Note: See TracBrowser for help on using the repository browser.