|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Computer Consoles Inc. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted ! 9: * provided that: (1) source distributions retain this entire copyright ! 10: * notice and comment, and (2) distributions including binaries display ! 11: * the following acknowledgement: ``This product includes software ! 12: * developed by the University of California, Berkeley and its contributors'' ! 13: * in the documentation or other materials provided with the distribution ! 14: * and in all advertising materials mentioning features or use of this ! 15: * software. Neither the name of the University nor the names of its ! 16: * contributors may be used to endorse or promote products derived ! 17: * from this software without specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: char copyright[] = ! 25: "@(#) Copyright (c) 1988 Regents of the University of California.\n\ ! 26: All rights reserved.\n"; ! 27: #endif /* not lint */ ! 28: ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)fsdb.c 5.8 (Berkeley) 6/1/90"; ! 31: #endif /* not lint */ ! 32: ! 33: /* ! 34: * fsdb - file system debugger ! 35: * ! 36: * usage: fsdb [options] special ! 37: * options: ! 38: * -? display usage ! 39: * -o override some error conditions ! 40: * -p"string" set prompt to string ! 41: * -w open for write ! 42: */ ! 43: ! 44: #include <sys/param.h> ! 45: #include <sys/signal.h> ! 46: #include <sys/file.h> ! 47: #include <sys/dir.h> ! 48: #include <ufs/fs.h> ! 49: #include <ufs/dinode.h> ! 50: #include <stdio.h> ! 51: #include <setjmp.h> ! 52: #include <paths.h> ! 53: ! 54: /* ! 55: * Defines from the 4.3-tahoe file system, for systems with the 4.2 or 4.3 ! 56: * file system. ! 57: */ ! 58: #ifndef FS_42POSTBLFMT ! 59: #define cg_blktot(cgp) (((cgp))->cg_btot) ! 60: #define cg_blks(fs, cgp, cylno) (((cgp))->cg_b[cylno]) ! 61: #define cg_inosused(cgp) (((cgp))->cg_iused) ! 62: #define cg_blksfree(cgp) (((cgp))->cg_free) ! 63: #define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC) ! 64: #endif ! 65: ! 66: /* ! 67: * Never changing defines. ! 68: */ ! 69: #define OCTAL 8 /* octal base */ ! 70: #define DECIMAL 10 /* decimal base */ ! 71: #define HEX 16 /* hexadecimal base */ ! 72: ! 73: /* ! 74: * Adjustable defines. ! 75: */ ! 76: #define NBUF 10 /* number of cache buffers */ ! 77: #define PROMPTSIZE 80 /* size of user definable prompt */ ! 78: #define MAXFILES 40000 /* max number of files ls can handle */ ! 79: #define FIRST_DEPTH 10 /* default depth for find and ls */ ! 80: #define SECOND_DEPTH 100 /* second try at depth (maximum) */ ! 81: #define INPUTBUFFER 1040 /* size of input buffer */ ! 82: #define BYTESPERLINE 16 /* bytes per line of /dxo output */ ! 83: #define NREG 36 /* number of save registers */ ! 84: ! 85: /* ! 86: * Values dependent on sizes of structs and such. ! 87: */ ! 88: #define NUMB 3 /* these three are arbitrary, */ ! 89: #define BLOCK 5 /* but must be different from */ ! 90: #define FRAGMENT 7 /* the rest (hence odd). */ ! 91: #define BITSPERCHAR 8 /* couldn't find it anywhere */ ! 92: #define CHAR (sizeof (char)) ! 93: #define SHORT (sizeof (short)) ! 94: #define LONG (sizeof (long)) ! 95: #define INODE (sizeof (struct dinode)) ! 96: #define DIRECTORY (sizeof (struct direct)) ! 97: #define CGRP (sizeof (struct cg)) ! 98: #define SB (sizeof (struct fs)) ! 99: #define BLKSIZE (fs->fs_bsize) /* for clarity */ ! 100: #define FRGSIZE (fs->fs_fsize) ! 101: #define BLKSHIFT (fs->fs_bshift) ! 102: #define FRGSHIFT (fs->fs_fshift) ! 103: ! 104: /* ! 105: * Messy macros that would otherwise clutter up such glamorous code. ! 106: */ ! 107: #define itob(i) ((itod(fs, (i)) << FRGSHIFT) + itoo(fs, (i)) * INODE) ! 108: #define min(x, y) ((x) < (y) ? (x) : (y)) ! 109: #define STRINGSIZE(d) ((long)d->d_reclen - \ ! 110: ((long)&d->d_name[0] - (long)&d->d_ino)) ! 111: #define letter(c) ((((c) >= 'a')&&((c) <= 'z')) ||\ ! 112: (((c) >= 'A')&&((c) <= 'Z'))) ! 113: #define digit(c) (((c) >= '0') && ((c) <= '9')) ! 114: #define HEXLETTER(c) (((c) >= 'A') && ((c) <= 'F')) ! 115: #define hexletter(c) (((c) >= 'a') && ((c) <= 'f')) ! 116: #define octaldigit(c) (((c) >= '0') && ((c) <= '7')) ! 117: #define uppertolower(c) ((c) - 'A' + 'a') ! 118: #define hextodigit(c) ((c) - 'a' + 10) ! 119: #define numtodigit(c) ((c) - '0') ! 120: #define loword(X) (((ushort *)&X)[1]) ! 121: #define lobyte(X) (((unsigned char *)&X)[1]) ! 122: ! 123: /* ! 124: * buffer cache structure. ! 125: */ ! 126: struct buf { ! 127: struct buf *fwd; ! 128: struct buf *back; ! 129: char *blkaddr; ! 130: short valid; ! 131: long blkno; ! 132: } buf[NBUF], bhdr; ! 133: ! 134: /* ! 135: * used to hold save registers (see '<' and '>'). ! 136: */ ! 137: struct save_registers { ! 138: long sv_addr; ! 139: long sv_value; ! 140: long sv_objsz; ! 141: } regs[NREG]; ! 142: ! 143: /* ! 144: * cd, find, and ls use this to hold filenames. Each filename is broken ! 145: * up by a slash. In other words, /usr/src/adm would have a len field ! 146: * of 2 (starting from 0), and filenames->fname[0-2] would hold usr, ! 147: * src, and adm components of the pathname. ! 148: */ ! 149: struct filenames { ! 150: long ino; /* inode */ ! 151: long len; /* number of components */ ! 152: char flag; /* flag if using SECOND_DEPTH allocator */ ! 153: char find; /* flag if found by find */ ! 154: char **fname; /* hold components of pathname */ ! 155: } *filenames, *top; ! 156: ! 157: struct fs filesystem, *fs; /* super block */ ! 158: ! 159: /* ! 160: * Global data. ! 161: */ ! 162: char *input_path[MAXPATHLEN]; ! 163: char *stack_path[MAXPATHLEN]; ! 164: char *current_path[MAXPATHLEN]; ! 165: char input_buffer[INPUTBUFFER]; ! 166: char *prompt; ! 167: char *buffers; ! 168: char scratch[64]; ! 169: char BASE[] = "o u x"; ! 170: char PROMPT[PROMPTSIZE] = "> "; ! 171: char laststyle = '/'; ! 172: char lastpo = 'x'; ! 173: short input_pointer; ! 174: short current_pathp; ! 175: short stack_pathp; ! 176: short input_pathp; ! 177: short cmp_level; ! 178: short nfiles; ! 179: short type = NUMB; ! 180: short dirslot; ! 181: short fd; ! 182: short c_count; ! 183: short error; ! 184: short paren; ! 185: short trapped; ! 186: short doing_cd; ! 187: short doing_find; ! 188: short find_by_name; ! 189: short find_by_inode; ! 190: short long_list; ! 191: short recursive; ! 192: short objsz = SHORT; ! 193: short override = 0; ! 194: short wrtflag; ! 195: short base = HEX; ! 196: short acting_on_inode; ! 197: short acting_on_directory; ! 198: short should_print = 1; ! 199: short clear; ! 200: short star; ! 201: long addr; ! 202: long bod_addr; ! 203: long value; ! 204: long erraddr; ! 205: long errcur_bytes; ! 206: long errino; ! 207: long errinum; ! 208: long cur_cgrp; ! 209: long cur_ino; ! 210: long cur_inum; ! 211: long cur_dir; ! 212: long cur_block; ! 213: long cur_bytes; ! 214: long find_ino; ! 215: long filesize; ! 216: long blocksize; ! 217: long stringsize; ! 218: long count = 1; ! 219: long commands; ! 220: long read_requests; ! 221: long actual_disk_reads; ! 222: jmp_buf env; ! 223: ! 224: extern char *malloc(), *calloc(); ! 225: char getachar(); ! 226: char *getblk(), *fmtentry(); ! 227: int err(); ! 228: long get(), bmap(), expr(), term(), getnumb(); ! 229: unsigned long *print_check(); ! 230: ! 231: /* ! 232: * main - lines are read up to the unprotected ('\') newline and ! 233: * held in an input buffer. Characters may be read from the ! 234: * input buffer using getachar() and unread using ungetachar(). ! 235: * Reading the whole line ahead allows the use of debuggers ! 236: * which would otherwise be impossible since the debugger ! 237: * and fsdb could not share stdin. ! 238: */ ! 239: ! 240: main(argc,argv) ! 241: short argc; ! 242: char **argv; ! 243: { ! 244: ! 245: register char c, *cptr; ! 246: register short i, j, *iptr; ! 247: register struct direct *dirp; ! 248: register struct buf *bp; ! 249: struct filenames *fn; ! 250: char *progname; ! 251: short colon, mode; ! 252: long temp; ! 253: unsigned block; ! 254: int ffcmp(); ! 255: ! 256: setbuf(stdin, NULL); ! 257: ! 258: progname = argv[0]; ! 259: prompt = &PROMPT[0]; ! 260: /* ! 261: * Parse options. ! 262: */ ! 263: while (argc>1 && argv[1][0] == '-') { ! 264: if (strcmp("-?", argv[1]) == 0) ! 265: goto usage; ! 266: if (strcmp("-o", argv[1]) == 0) { ! 267: printf("error checking off\n"); ! 268: override = 1; ! 269: argc--; argv++; ! 270: continue; ! 271: } ! 272: if (strncmp("-p", argv[1],2) == 0) { ! 273: prompt = &argv[1][2]; ! 274: argc--; argv++; ! 275: continue; ! 276: } ! 277: if (strcmp("-w", argv[1]) == 0) { ! 278: wrtflag = 2; /* suitable for open */ ! 279: argc--; argv++; ! 280: continue; ! 281: } ! 282: } ! 283: if (argc!=2) { ! 284: usage: ! 285: printf("usage: %s [options] special\n", progname); ! 286: printf("options:\n"); ! 287: printf("\t-? display usage\n"); ! 288: printf("\t-o override some error conditions\n"); ! 289: printf("\t-p\"string\" set prompt to string\n"); ! 290: printf("\t-w open for write\n"); ! 291: exit(1); ! 292: } ! 293: /* ! 294: * Attempt to open the special file. ! 295: */ ! 296: if ((fd = open(argv[1],wrtflag)) < 0) { ! 297: perror(argv[1]); ! 298: exit(1); ! 299: } ! 300: /* ! 301: * Read in the super block and validate (not too picky). ! 302: */ ! 303: if (lseek(fd, SBLOCK * DEV_BSIZE, 0) == -1) { ! 304: perror(argv[1]); ! 305: exit(1); ! 306: } ! 307: if (read(fd, &filesystem, sizeof filesystem) != sizeof filesystem) { ! 308: printf("%s: cannot read superblock\n", argv[1]); ! 309: exit(1); ! 310: } ! 311: fs = &filesystem; ! 312: if (fs->fs_magic != FS_MAGIC) { ! 313: printf("%s: Bad magic number in file system\n", argv[1]); ! 314: exit(1); ! 315: } ! 316: #ifdef FS_42POSTBLFMT ! 317: if (fs->fs_postblformat == FS_42POSTBLFMT) ! 318: fs->fs_nrpos = 8; ! 319: #endif ! 320: printf("fsdb of %s %s -- last mounted on %s\n", ! 321: argv[1], wrtflag ? "(Opened for write)" : "(Read only)", ! 322: &fs->fs_fsmnt[0]); ! 323: /* ! 324: * Malloc buffers and set up cache. ! 325: */ ! 326: buffers = malloc(NBUF * BLKSIZE); ! 327: bhdr.fwd = bhdr.back = &bhdr; ! 328: for (i=0; i<NBUF; i++) { ! 329: bp = &buf[i]; ! 330: bp->blkaddr = buffers + (i * BLKSIZE); ! 331: bp->valid = 0; ! 332: insert(bp); ! 333: } ! 334: /* ! 335: * Malloc filenames structure. The space for the actual filenames ! 336: * is allocated as it needs it. ! 337: */ ! 338: filenames = (struct filenames *)calloc(MAXFILES, ! 339: sizeof (struct filenames)); ! 340: if (filenames == NULL) { ! 341: printf("out of memory\n"); ! 342: exit(1); ! 343: } ! 344: ! 345: fn = filenames; ! 346: ! 347: restore_inode(2); ! 348: /* ! 349: * Malloc a few filenames (needed by pwd for example). ! 350: */ ! 351: for (i = 0; i < MAXPATHLEN; i++) { ! 352: input_path[i] = calloc(1, MAXNAMLEN); ! 353: stack_path[i] = calloc(1, MAXNAMLEN); ! 354: current_path[i] = calloc(1, MAXNAMLEN); ! 355: if (current_path[i] == NULL) { ! 356: printf("out of memory\n"); ! 357: exit(1); ! 358: } ! 359: } ! 360: current_pathp = -1; ! 361: ! 362: signal(2,err); ! 363: setjmp(env); ! 364: ! 365: getnextinput(); ! 366: /* ! 367: * Main loop and case statement. If an error condition occurs ! 368: * initialization and recovery is attempted. ! 369: */ ! 370: for (;;) { ! 371: if (error) { ! 372: freemem(filenames, nfiles); ! 373: nfiles = 0; ! 374: c_count = 0; ! 375: count = 1; ! 376: star = 0; ! 377: error = 0; ! 378: paren = 0; ! 379: acting_on_inode = 0; ! 380: acting_on_directory = 0; ! 381: should_print = 1; ! 382: addr = erraddr; ! 383: cur_ino = errino; ! 384: cur_inum = errinum; ! 385: cur_bytes = errcur_bytes; ! 386: printf("?\n"); ! 387: getnextinput(); ! 388: if (error) ! 389: continue; ! 390: } ! 391: c_count++; ! 392: ! 393: switch (c = getachar()) { ! 394: ! 395: case '\n': /* command end */ ! 396: freemem(filenames, nfiles); ! 397: nfiles = 0; ! 398: if (should_print && laststyle == '=') { ! 399: ungetachar(c); ! 400: goto calc; ! 401: } ! 402: if (c_count == 1) { ! 403: clear = 0; ! 404: should_print = 1; ! 405: erraddr = addr; ! 406: errino = cur_ino; ! 407: errinum = cur_inum; ! 408: errcur_bytes = cur_bytes; ! 409: switch (objsz) { ! 410: case DIRECTORY: ! 411: if ((addr = ! 412: getdirslot(dirslot+1)) == 0) ! 413: should_print = 0; ! 414: if (error) { ! 415: ungetachar(c); ! 416: continue; ! 417: } ! 418: break; ! 419: case INODE: ! 420: cur_inum++; ! 421: addr = itob(cur_inum); ! 422: if (!icheck(addr)) { ! 423: cur_inum--; ! 424: should_print = 0; ! 425: } ! 426: break; ! 427: case CGRP: ! 428: case SB: ! 429: cur_cgrp++; ! 430: if ((addr=cgrp_check(cur_cgrp)) == 0) { ! 431: cur_cgrp--; ! 432: continue; ! 433: } ! 434: break; ! 435: default: ! 436: addr += objsz; ! 437: cur_bytes += objsz; ! 438: if (valid_addr() == 0) ! 439: continue; ! 440: } ! 441: } ! 442: if (type == NUMB) ! 443: trapped = 0; ! 444: if (should_print) ! 445: switch (objsz) { ! 446: case DIRECTORY: ! 447: fprnt('?', 'd'); ! 448: break; ! 449: case INODE: ! 450: fprnt('?', 'i'); ! 451: if (!error) ! 452: cur_ino = addr; ! 453: break; ! 454: case CGRP: ! 455: fprnt('?', 'c'); ! 456: break; ! 457: case SB: ! 458: fprnt('?', 's'); ! 459: break; ! 460: case CHAR: ! 461: case SHORT: ! 462: case LONG: ! 463: fprnt(laststyle, lastpo); ! 464: } ! 465: if (error) { ! 466: ungetachar(c); ! 467: continue; ! 468: } ! 469: c_count = colon = acting_on_inode = 0; ! 470: acting_on_directory = 0; ! 471: should_print = 1; ! 472: getnextinput(); ! 473: if (error) ! 474: continue; ! 475: erraddr = addr; ! 476: errino = cur_ino; ! 477: errinum = cur_inum; ! 478: errcur_bytes = cur_bytes; ! 479: continue; ! 480: ! 481: case '(': /* numeric expression or unknown command */ ! 482: default: ! 483: colon = 0; ! 484: if (digit(c) || c == '(') { ! 485: ungetachar(c); ! 486: addr = expr(); ! 487: type = NUMB; ! 488: value = addr; ! 489: continue; ! 490: } ! 491: printf("unknown command or bad syntax\n"); ! 492: error++; ! 493: continue; ! 494: ! 495: case '?': /* general print facilities */ ! 496: case '/': ! 497: fprnt(c, getachar()); ! 498: continue; ! 499: ! 500: case ';': /* command separator and . */ ! 501: case '\t': ! 502: case ' ': ! 503: case '.': ! 504: continue; ! 505: ! 506: case ':': /* command indicator */ ! 507: colon++; ! 508: commands++; ! 509: should_print = 0; ! 510: stringsize = 0; ! 511: trapped = 0; ! 512: continue; ! 513: ! 514: case ',': /* count indicator */ ! 515: colon = star = 0; ! 516: if ((c = getachar()) == '*') { ! 517: star = 1; ! 518: count = BLKSIZE; ! 519: } else { ! 520: ungetachar(c); ! 521: count = expr(); ! 522: if (error) ! 523: continue; ! 524: if (!count) ! 525: count = 1; ! 526: } ! 527: clear = 0; ! 528: continue; ! 529: ! 530: case '+': /* address addition */ ! 531: colon = 0; ! 532: c = getachar(); ! 533: ungetachar(c); ! 534: if (c == '\n') ! 535: temp = 1; ! 536: else { ! 537: temp = expr(); ! 538: if (error) ! 539: continue; ! 540: } ! 541: erraddr = addr; ! 542: errcur_bytes = cur_bytes; ! 543: switch (objsz) { ! 544: case DIRECTORY: ! 545: addr = getdirslot(dirslot + temp); ! 546: if (error) ! 547: continue; ! 548: break; ! 549: case INODE: ! 550: cur_inum += temp; ! 551: addr = itob(cur_inum); ! 552: if (!icheck(addr)) { ! 553: cur_inum -= temp; ! 554: continue; ! 555: } ! 556: break; ! 557: case CGRP: ! 558: case SB: ! 559: cur_cgrp += temp; ! 560: if ((addr = cgrp_check(cur_cgrp)) == 0) { ! 561: cur_cgrp -= temp; ! 562: continue; ! 563: } ! 564: break; ! 565: default: ! 566: laststyle = '/'; ! 567: addr += temp * objsz; ! 568: cur_bytes += temp * objsz; ! 569: if (valid_addr() == 0) ! 570: continue; ! 571: } ! 572: value = get(objsz); ! 573: continue; ! 574: ! 575: case '-': /* address subtraction */ ! 576: colon = 0; ! 577: c = getachar(); ! 578: ungetachar(c); ! 579: if (c == '\n') ! 580: temp = 1; ! 581: else { ! 582: temp = expr(); ! 583: if (error) ! 584: continue; ! 585: } ! 586: erraddr = addr; ! 587: errcur_bytes = cur_bytes; ! 588: switch (objsz) { ! 589: case DIRECTORY: ! 590: addr = getdirslot(dirslot - temp); ! 591: if (error) ! 592: continue; ! 593: break; ! 594: case INODE: ! 595: cur_inum -= temp; ! 596: addr = itob(cur_inum); ! 597: if (!icheck(addr)) { ! 598: cur_inum += temp; ! 599: continue; ! 600: } ! 601: break; ! 602: case CGRP: ! 603: case SB: ! 604: cur_cgrp -= temp; ! 605: if ((addr = cgrp_check(cur_cgrp)) == 0) { ! 606: cur_cgrp += temp; ! 607: continue; ! 608: } ! 609: break; ! 610: default: ! 611: laststyle = '/'; ! 612: addr -= temp * objsz; ! 613: cur_bytes -= temp * objsz; ! 614: if (valid_addr() == 0) ! 615: continue; ! 616: } ! 617: value = get(objsz); ! 618: continue; ! 619: ! 620: case '*': /* address multiplication */ ! 621: colon = 0; ! 622: temp = expr(); ! 623: if (error) ! 624: continue; ! 625: if (objsz != INODE && objsz != DIRECTORY) ! 626: laststyle = '/'; ! 627: addr *= temp; ! 628: value = get(objsz); ! 629: continue; ! 630: ! 631: case '%': /* address division */ ! 632: colon = 0; ! 633: temp = expr(); ! 634: if (error) ! 635: continue; ! 636: if (!temp) { ! 637: printf("divide by zero\n"); ! 638: error++; ! 639: continue; ! 640: } ! 641: if (objsz != INODE && objsz != DIRECTORY) ! 642: laststyle = '/'; ! 643: addr /= temp; ! 644: value = get(objsz); ! 645: continue; ! 646: ! 647: case '=': { /* assignment operation */ ! 648: short tbase = base; ! 649: ! 650: calc: ! 651: c = getachar(); ! 652: if (c == '\n') { ! 653: ungetachar(c); ! 654: c = lastpo; ! 655: if (acting_on_inode == 1) { ! 656: if (c != 'o' && c != 'd' && c != 'x' && ! 657: c != 'O' && c != 'D' && c != 'X') { ! 658: switch (objsz) { ! 659: case LONG: ! 660: c = lastpo = 'X'; ! 661: break; ! 662: case SHORT: ! 663: c = lastpo = 'x'; ! 664: break; ! 665: case CHAR: ! 666: c = lastpo = 'c'; ! 667: } ! 668: } ! 669: } else { ! 670: if (acting_on_inode == 2) ! 671: c = lastpo = 't'; ! 672: } ! 673: } else if (acting_on_inode) ! 674: lastpo = c; ! 675: should_print = star = 0; ! 676: count = 1; ! 677: erraddr = addr; ! 678: errcur_bytes = cur_bytes; ! 679: switch (c) { ! 680: case '"': /* character string */ ! 681: if (type == NUMB) { ! 682: blocksize = BLKSIZE; ! 683: filesize = BLKSIZE * 2; ! 684: cur_bytes = blkoff(fs, addr); ! 685: if (objsz==DIRECTORY || objsz==INODE) ! 686: lastpo = 'X'; ! 687: } ! 688: puta(); ! 689: continue; ! 690: case '+': /* =+ operator */ ! 691: temp = expr(); ! 692: value = get(objsz); ! 693: if (!error) ! 694: put(value+temp,objsz); ! 695: continue; ! 696: case '-': /* =- operator */ ! 697: temp = expr(); ! 698: value = get(objsz); ! 699: if (!error) ! 700: put(value-temp,objsz); ! 701: continue; ! 702: case 'b': ! 703: case 'c': ! 704: if (objsz == CGRP) ! 705: fprnt('?', c); ! 706: else ! 707: fprnt('/', c); ! 708: continue; ! 709: case 'i': ! 710: addr = cur_ino; ! 711: fprnt('?', 'i'); ! 712: continue; ! 713: case 's': ! 714: fprnt('?', 's'); ! 715: continue; ! 716: case 't': ! 717: case 'T': ! 718: laststyle = '='; ! 719: printf("\t\t"); ! 720: printf("%s", ctime(&value)); ! 721: continue; ! 722: case 'o': ! 723: base = OCTAL; ! 724: goto otx; ! 725: case 'd': ! 726: if (objsz == DIRECTORY) { ! 727: addr = cur_dir; ! 728: fprnt('?', 'd'); ! 729: continue; ! 730: } ! 731: base = DECIMAL; ! 732: goto otx; ! 733: case 'x': ! 734: base = HEX; ! 735: otx: ! 736: laststyle = '='; ! 737: printf("\t\t"); ! 738: if (acting_on_inode) ! 739: print(value & 0177777L, 12, -8, 0); ! 740: else ! 741: print(addr & 0177777L, 12, -8, 0); ! 742: printf("\n"); ! 743: base = tbase; ! 744: continue; ! 745: case 'O': ! 746: base = OCTAL; ! 747: goto OTX; ! 748: case 'D': ! 749: base = DECIMAL; ! 750: goto OTX; ! 751: case 'X': ! 752: base = HEX; ! 753: OTX: ! 754: laststyle = '='; ! 755: printf("\t\t"); ! 756: if (acting_on_inode) ! 757: print(value, 12, -8, 0); ! 758: else ! 759: print(addr, 12, -8, 0); ! 760: printf("\n"); ! 761: base = tbase; ! 762: continue; ! 763: default: /* regular assignment */ ! 764: ungetachar(c); ! 765: value = expr(); ! 766: if (error) ! 767: printf("syntax error\n"); ! 768: else ! 769: put(value,objsz); ! 770: continue; ! 771: } ! 772: } ! 773: ! 774: case '>': /* save current address */ ! 775: colon = 0; ! 776: should_print = 0; ! 777: c = getachar(); ! 778: if (!letter(c) && !digit(c)) { ! 779: printf("invalid register specification, "); ! 780: printf("must be letter or digit\n"); ! 781: error++; ! 782: continue; ! 783: } ! 784: if (letter(c)) { ! 785: if (c < 'a') ! 786: c = uppertolower(c); ! 787: c = hextodigit(c); ! 788: } else ! 789: c = numtodigit(c); ! 790: regs[c].sv_addr = addr; ! 791: regs[c].sv_value = value; ! 792: regs[c].sv_objsz = objsz; ! 793: continue; ! 794: ! 795: case '<': /* restore saved address */ ! 796: colon = 0; ! 797: should_print = 0; ! 798: c = getachar(); ! 799: if (!letter(c) && !digit(c)) { ! 800: printf("invalid register specification, "); ! 801: printf("must be letter or digit\n"); ! 802: error++; ! 803: continue; ! 804: } ! 805: if (letter(c)) { ! 806: if (c < 'a') ! 807: c = uppertolower(c); ! 808: c = hextodigit(c); ! 809: } else ! 810: c = numtodigit(c); ! 811: addr = regs[c].sv_addr; ! 812: value = regs[c].sv_value; ! 813: objsz = regs[c].sv_objsz; ! 814: continue; ! 815: ! 816: case 'a': ! 817: if (colon) ! 818: colon = 0; ! 819: else ! 820: goto no_colon; ! 821: if (match("at", 2)) { /* access time */ ! 822: acting_on_inode = 2; ! 823: should_print = 1; ! 824: addr = (long) ! 825: &((struct dinode *)cur_ino)->di_atime; ! 826: value = get(LONG); ! 827: type = NULL; ! 828: continue; ! 829: } ! 830: goto bad_syntax; ! 831: ! 832: case 'b': ! 833: if (colon) ! 834: colon = 0; ! 835: else ! 836: goto no_colon; ! 837: if (match("block", 2)) { /* block conversion */ ! 838: if (type == NUMB) { ! 839: value = addr; ! 840: cur_bytes = 0; ! 841: blocksize = BLKSIZE; ! 842: filesize = BLKSIZE * 2; ! 843: } ! 844: addr = value << FRGSHIFT; ! 845: bod_addr = addr; ! 846: value = get(LONG); ! 847: type = BLOCK; ! 848: dirslot = 0; ! 849: trapped++; ! 850: continue; ! 851: } ! 852: if (match("bs", 2)) { /* block size */ ! 853: acting_on_inode = 1; ! 854: should_print = 1; ! 855: if (icheck(cur_ino) == 0) ! 856: continue; ! 857: addr = (long) ! 858: &((struct dinode *)cur_ino)->di_blocks; ! 859: value = get(LONG); ! 860: type = NULL; ! 861: continue; ! 862: } ! 863: if (match("base", 2)) { /* change/show base */ ! 864: showbase: ! 865: if ((c = getachar()) == '\n') { ! 866: ungetachar(c); ! 867: printf("base =\t\t"); ! 868: switch (base) { ! 869: case OCTAL: ! 870: printf("OCTAL\n"); ! 871: continue; ! 872: case DECIMAL: ! 873: printf("DECIMAL\n"); ! 874: continue; ! 875: case HEX: ! 876: printf("HEX\n"); ! 877: continue; ! 878: } ! 879: } ! 880: if (c != '=') { ! 881: printf("missing '='\n"); ! 882: error++; ! 883: continue; ! 884: } ! 885: value = expr(); ! 886: switch (value) { ! 887: default: ! 888: printf("invalid base\n"); ! 889: error++; ! 890: break; ! 891: case OCTAL: ! 892: case DECIMAL: ! 893: case HEX: ! 894: base = value; ! 895: } ! 896: goto showbase; ! 897: } ! 898: goto bad_syntax; ! 899: ! 900: case 'c': ! 901: if (colon) ! 902: colon = 0; ! 903: else ! 904: goto no_colon; ! 905: if (match("cd", 2)) { /* change directory */ ! 906: top = filenames - 1; ! 907: eat_spaces(); ! 908: if ((c = getachar()) == '\n') { ! 909: ungetachar(c); ! 910: current_pathp = -1; ! 911: restore_inode(2); ! 912: continue; ! 913: } ! 914: ungetachar(c); ! 915: temp = cur_inum; ! 916: doing_cd = 1; ! 917: parse(); ! 918: doing_cd = 0; ! 919: if (nfiles != 1) { ! 920: restore_inode(temp); ! 921: if (!error) { ! 922: print_path(input_path, ! 923: input_pathp); ! 924: if (nfiles == 0) ! 925: printf(" not found\n"); ! 926: else ! 927: printf(" ambiguous\n"); ! 928: error++; ! 929: } ! 930: continue; ! 931: } ! 932: restore_inode(filenames->ino); ! 933: if ((mode = icheck(addr)) == 0) ! 934: continue; ! 935: if ((mode & IFMT) != IFDIR) { ! 936: restore_inode(temp); ! 937: print_path(input_path, input_pathp); ! 938: printf(" not a directory\n"); ! 939: error++; ! 940: continue; ! 941: } ! 942: for (i = 0; i <= top->len; i++) ! 943: strcpy(current_path[i], ! 944: top->fname[i]); ! 945: current_pathp = top->len; ! 946: continue; ! 947: } ! 948: if (match("cg", 2)) { /* cylinder group */ ! 949: if (type == NUMB) ! 950: value = addr; ! 951: if (value > fs->fs_ncg - 1) { ! 952: printf("maximum cylinder group is "); ! 953: print(fs->fs_ncg - 1, 8, -8, 0); ! 954: printf("\n"); ! 955: error++; ! 956: continue; ! 957: } ! 958: type = objsz = CGRP; ! 959: cur_cgrp = value; ! 960: addr = cgtod(fs, cur_cgrp) << FRGSHIFT; ! 961: continue; ! 962: } ! 963: if (match("ct", 2)) { /* creation time */ ! 964: acting_on_inode = 2; ! 965: should_print = 1; ! 966: addr = (long) ! 967: &((struct dinode *)cur_ino)->di_ctime; ! 968: value = get(LONG); ! 969: type = NULL; ! 970: continue; ! 971: } ! 972: goto bad_syntax; ! 973: ! 974: case 'd': ! 975: if (colon) ! 976: colon = 0; ! 977: else ! 978: goto no_colon; ! 979: if (match("directory", 2)) { /* directory offsets */ ! 980: if (type == NUMB) ! 981: value = addr; ! 982: objsz = DIRECTORY; ! 983: type = DIRECTORY; ! 984: addr = getdirslot(value); ! 985: continue; ! 986: } ! 987: if (match("db", 2)) { /* direct block */ ! 988: acting_on_inode = 1; ! 989: should_print = 1; ! 990: if (type == NUMB) ! 991: value = addr; ! 992: if (value >= NDADDR) { ! 993: printf("direct blocks are 0 to "); ! 994: print(NDADDR - 1, 0, 0, 0); ! 995: printf("\n"); ! 996: error++; ! 997: continue; ! 998: } ! 999: addr = cur_ino; ! 1000: if (!icheck(addr)) ! 1001: continue; ! 1002: addr = (long) ! 1003: &((struct dinode *)cur_ino)->di_db[value]; ! 1004: bod_addr = addr; ! 1005: cur_bytes = (value) * BLKSIZE; ! 1006: cur_block = value; ! 1007: type = BLOCK; ! 1008: dirslot = 0; ! 1009: value = get(LONG); ! 1010: if (!value && !override) { ! 1011: printf("non existent block\n"); ! 1012: error++; ! 1013: } ! 1014: continue; ! 1015: } ! 1016: goto bad_syntax; ! 1017: ! 1018: case 'f': ! 1019: if (colon) ! 1020: colon = 0; ! 1021: else ! 1022: goto no_colon; ! 1023: if (match("find", 3)) { /* find command */ ! 1024: find(); ! 1025: continue; ! 1026: } ! 1027: if (match("fragment", 2)) { /* fragment conv. */ ! 1028: if (type == NUMB) { ! 1029: value = addr; ! 1030: cur_bytes = 0; ! 1031: blocksize = FRGSIZE; ! 1032: filesize = FRGSIZE * 2; ! 1033: } ! 1034: if (min(blocksize, filesize) - cur_bytes > ! 1035: FRGSIZE) { ! 1036: blocksize = cur_bytes + FRGSIZE; ! 1037: filesize = blocksize * 2; ! 1038: } ! 1039: addr = value << FRGSHIFT; ! 1040: bod_addr = addr; ! 1041: value = get(LONG); ! 1042: type = FRAGMENT; ! 1043: dirslot = 0; ! 1044: trapped++; ! 1045: continue; ! 1046: } ! 1047: if (match("file", 4)) { /* access as file */ ! 1048: acting_on_inode = 1; ! 1049: should_print = 1; ! 1050: if (type == NUMB) ! 1051: value = addr; ! 1052: addr = cur_ino; ! 1053: if ((mode = icheck(addr)) == 0) ! 1054: continue; ! 1055: if ((mode & IFCHR) && !override) { ! 1056: printf("special device\n"); ! 1057: error++; ! 1058: continue; ! 1059: } ! 1060: if ((addr = (bmap(value) << FRGSHIFT)) == 0) ! 1061: continue; ! 1062: cur_block = value; ! 1063: bod_addr = addr; ! 1064: type = BLOCK; ! 1065: dirslot = 0; ! 1066: continue; ! 1067: } ! 1068: if (match("fill", 4)) { /* fill */ ! 1069: if (getachar() != '=') { ! 1070: printf("missing '='\n"); ! 1071: error++; ! 1072: continue; ! 1073: } ! 1074: if (objsz == INODE || objsz == DIRECTORY) { ! 1075: printf("can't fill inode or directory\n"); ! 1076: error++; ! 1077: continue; ! 1078: } ! 1079: fill(); ! 1080: continue; ! 1081: } ! 1082: goto bad_syntax; ! 1083: ! 1084: case 'g': ! 1085: if (colon) ! 1086: colon = 0; ! 1087: else ! 1088: goto no_colon; ! 1089: if (match("gid", 1)) { /* group id */ ! 1090: acting_on_inode = 1; ! 1091: should_print = 1; ! 1092: addr = (long) ! 1093: &((struct dinode *)cur_ino)->di_gid; ! 1094: value = get(SHORT); ! 1095: type = NULL; ! 1096: continue; ! 1097: } ! 1098: goto bad_syntax; ! 1099: ! 1100: case 'i': ! 1101: if (colon) ! 1102: colon = 0; ! 1103: else ! 1104: goto no_colon; ! 1105: if (match("inode", 2)) { /* i# to inode conversion */ ! 1106: if (c_count == 2) { ! 1107: addr = cur_ino; ! 1108: value = get(INODE); ! 1109: type = NULL; ! 1110: laststyle = '='; ! 1111: lastpo = 'i'; ! 1112: should_print = 1; ! 1113: continue; ! 1114: } ! 1115: if (type == NUMB) ! 1116: value = addr; ! 1117: addr = itob(value); ! 1118: if (!icheck(addr)) ! 1119: continue; ! 1120: cur_ino = addr; ! 1121: cur_inum = value; ! 1122: value = get(INODE); ! 1123: type = NULL; ! 1124: continue; ! 1125: } ! 1126: if (match("ib", 2)) { /* indirect block */ ! 1127: acting_on_inode = 1; ! 1128: should_print = 1; ! 1129: if (type == NUMB) ! 1130: value = addr; ! 1131: if (value >= NIADDR) { ! 1132: printf("indirect blocks are 0 to "); ! 1133: print(NIADDR - 1, 0, 0, 0); ! 1134: printf("\n"); ! 1135: error++; ! 1136: continue; ! 1137: } ! 1138: addr = (long) ! 1139: &((struct dinode *)cur_ino)->di_ib[value]; ! 1140: cur_bytes = (NDADDR - 1) * BLKSIZE; ! 1141: temp = 1; ! 1142: for (i = 0; i < value; i++) { ! 1143: temp *= NINDIR(fs) * BLKSIZE; ! 1144: cur_bytes += temp; ! 1145: } ! 1146: type = BLOCK; ! 1147: dirslot = 0; ! 1148: value = get(LONG); ! 1149: if (!value && !override) { ! 1150: printf("non existent block\n"); ! 1151: error++; ! 1152: } ! 1153: continue; ! 1154: } ! 1155: goto bad_syntax; ! 1156: ! 1157: case 'l': ! 1158: if (colon) ! 1159: colon = 0; ! 1160: else ! 1161: goto no_colon; ! 1162: if (match("ls", 2)) { /* ls command */ ! 1163: temp = cur_inum; ! 1164: recursive = long_list = 0; ! 1165: top = filenames - 1; ! 1166: for (;;) { ! 1167: eat_spaces(); ! 1168: if ((c = getachar()) == '-') { ! 1169: if ((c = getachar()) == 'R') { ! 1170: recursive = 1; ! 1171: continue; ! 1172: } else if (c == 'l') { ! 1173: long_list = 1; ! 1174: } else { ! 1175: printf("unknown option "); ! 1176: printf("'%c'\n", c); ! 1177: error++; ! 1178: break; ! 1179: } ! 1180: } else ! 1181: ungetachar(c); ! 1182: if ((c = getachar()) == '\n') { ! 1183: if (c_count != 2) { ! 1184: ungetachar(c); ! 1185: break; ! 1186: } ! 1187: } ! 1188: c_count++; ! 1189: ungetachar(c); ! 1190: parse(); ! 1191: restore_inode(temp); ! 1192: if (error) ! 1193: break; ! 1194: } ! 1195: recursive = 0; ! 1196: if (error || nfiles == 0) { ! 1197: if (!error) { ! 1198: print_path(input_path, ! 1199: input_pathp); ! 1200: printf(" not found\n"); ! 1201: } ! 1202: continue; ! 1203: } ! 1204: if (nfiles) { ! 1205: cmp_level = 0; ! 1206: qsort((char *)filenames, nfiles, ! 1207: sizeof (struct filenames), ffcmp); ! 1208: ls(filenames, filenames + (nfiles - 1), 0); ! 1209: } else { ! 1210: printf("no match\n"); ! 1211: error++; ! 1212: } ! 1213: restore_inode(temp); ! 1214: continue; ! 1215: } ! 1216: if (match("ln", 2)) { /* link count */ ! 1217: acting_on_inode = 1; ! 1218: should_print = 1; ! 1219: addr = (long) ! 1220: &((struct dinode *)cur_ino)->di_nlink; ! 1221: value = get(SHORT); ! 1222: type = NULL; ! 1223: continue; ! 1224: } ! 1225: goto bad_syntax; ! 1226: ! 1227: case 'm': ! 1228: if (colon) ! 1229: colon = 0; ! 1230: else ! 1231: goto no_colon; ! 1232: addr = cur_ino; ! 1233: if ((mode = icheck(addr)) == 0) ! 1234: continue; ! 1235: if (match("mt", 2)) { /* modification time */ ! 1236: acting_on_inode = 2; ! 1237: should_print = 1; ! 1238: addr = (long) ! 1239: &((struct dinode *)cur_ino)->di_mtime; ! 1240: value = get(LONG); ! 1241: type = NULL; ! 1242: continue; ! 1243: } ! 1244: if (match("md", 2)) { /* mode */ ! 1245: acting_on_inode = 1; ! 1246: should_print = 1; ! 1247: addr = (long) ! 1248: &((struct dinode *)cur_ino)->di_mode; ! 1249: value = get(SHORT); ! 1250: type = NULL; ! 1251: continue; ! 1252: } ! 1253: if (match("maj", 2)) { /* major device number */ ! 1254: acting_on_inode = 1; ! 1255: should_print = 1; ! 1256: if (devcheck(mode)) ! 1257: continue; ! 1258: addr = (long) ! 1259: &((struct dinode *)cur_ino)->di_db[1]; ! 1260: value = get(LONG); ! 1261: type = NULL; ! 1262: continue; ! 1263: } ! 1264: if (match("min", 2)) { /* minor device number */ ! 1265: acting_on_inode = 1; ! 1266: should_print = 1; ! 1267: if (devcheck(mode)) ! 1268: continue; ! 1269: addr = (long) ! 1270: &((struct dinode *)cur_ino)->di_db[0]; ! 1271: value = get(LONG); ! 1272: type = NULL; ! 1273: continue; ! 1274: } ! 1275: goto bad_syntax; ! 1276: ! 1277: case 'n': ! 1278: if (colon) ! 1279: colon = 0; ! 1280: else ! 1281: goto no_colon; ! 1282: if (match("nm", 1)) { /* directory name */ ! 1283: objsz = DIRECTORY; ! 1284: acting_on_directory = 1; ! 1285: cur_dir = addr; ! 1286: if ((cptr = getblk(addr)) == 0) ! 1287: continue; ! 1288: dirp = (struct direct *)(cptr+blkoff(fs, addr)); ! 1289: stringsize = (long)dirp->d_reclen - ! 1290: ((long)&dirp->d_name[0] - (long)&dirp->d_ino); ! 1291: addr = (long) ! 1292: &((struct direct *)addr)->d_name[0]; ! 1293: type = NULL; ! 1294: continue; ! 1295: } ! 1296: goto bad_syntax; ! 1297: ! 1298: case 'o': ! 1299: if (colon) ! 1300: colon = 0; ! 1301: else ! 1302: goto no_colon; ! 1303: if (match("override", 1)) { /* override flip flop */ ! 1304: if (override = !override) ! 1305: printf("error checking off\n"); ! 1306: else ! 1307: printf("error checking on\n"); ! 1308: continue; ! 1309: } ! 1310: goto bad_syntax; ! 1311: ! 1312: case 'p': ! 1313: if (colon) ! 1314: colon = 0; ! 1315: else ! 1316: goto no_colon; ! 1317: if (match("pwd", 2)) { /* print working dir */ ! 1318: print_path(current_path, current_pathp); ! 1319: printf("\n"); ! 1320: continue; ! 1321: } ! 1322: if (match("prompt", 2)) { /* change prompt */ ! 1323: if ((c = getachar()) != '=') { ! 1324: printf("missing '='\n"); ! 1325: error++; ! 1326: continue; ! 1327: } ! 1328: if ((c = getachar()) != '"') { ! 1329: printf("missing '\"'\n"); ! 1330: error++; ! 1331: continue; ! 1332: } ! 1333: i = 0; ! 1334: prompt = &prompt[0]; ! 1335: while ((c = getachar()) != '"' && ! 1336: c != '\n') { ! 1337: prompt[i++] = c; ! 1338: if (i >= PROMPTSIZE) { ! 1339: printf("string too long\n"); ! 1340: error++; ! 1341: break; ! 1342: } ! 1343: } ! 1344: prompt[i] = '\0'; ! 1345: continue; ! 1346: } ! 1347: goto bad_syntax; ! 1348: ! 1349: case 'q': ! 1350: if (!colon) ! 1351: goto no_colon; ! 1352: if (match("quit", 1)) { /* quit */ ! 1353: if ((c = getachar()) != '\n') { ! 1354: error++; ! 1355: continue; ! 1356: } ! 1357: exit(0); ! 1358: } ! 1359: goto bad_syntax; ! 1360: ! 1361: case 's': ! 1362: if (colon) ! 1363: colon = 0; ! 1364: else ! 1365: goto no_colon; ! 1366: if (match("sb", 2)) { /* super block */ ! 1367: if (c_count == 2) { ! 1368: cur_cgrp = -1; ! 1369: type = objsz = SB; ! 1370: laststyle = '='; ! 1371: lastpo = 's'; ! 1372: should_print = 1; ! 1373: continue; ! 1374: } ! 1375: if (type == NUMB) ! 1376: value = addr; ! 1377: if (value > fs->fs_ncg - 1) { ! 1378: printf("maximum super block is "); ! 1379: print(fs->fs_ncg - 1, 8, -8, 0); ! 1380: printf("\n"); ! 1381: error++; ! 1382: continue; ! 1383: } ! 1384: type = objsz = SB; ! 1385: cur_cgrp = value; ! 1386: addr = cgsblock(fs, cur_cgrp) << FRGSHIFT; ! 1387: continue; ! 1388: } ! 1389: if (match("sz", 2)) { /* file size */ ! 1390: acting_on_inode = 1; ! 1391: should_print = 1; ! 1392: addr = (long) ! 1393: &((struct dinode *)cur_ino)->di_size; ! 1394: value = get(LONG); ! 1395: type = NULL; ! 1396: continue; ! 1397: } ! 1398: goto bad_syntax; ! 1399: ! 1400: case 'u': ! 1401: if (colon) ! 1402: colon = 0; ! 1403: else ! 1404: goto no_colon; ! 1405: if (match("uid", 1)) { /* user id */ ! 1406: acting_on_inode = 1; ! 1407: should_print = 1; ! 1408: addr = (long) ! 1409: &((struct dinode *)cur_ino)->di_uid; ! 1410: value = get(SHORT); ! 1411: type = NULL; ! 1412: continue; ! 1413: } ! 1414: goto bad_syntax; ! 1415: ! 1416: case 'F': /* buffer status (internal use only) */ ! 1417: if (colon) ! 1418: colon = 0; ! 1419: else ! 1420: goto no_colon; ! 1421: for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd) ! 1422: printf("%8x %d\n",bp->blkno,bp->valid); ! 1423: printf("\n"); ! 1424: printf("# commands\t\t%d\n", commands); ! 1425: printf("# read requests\t\t%d\n", read_requests); ! 1426: printf("# actual disk reads\t%d\n", actual_disk_reads); ! 1427: continue; ! 1428: no_colon: ! 1429: printf("a colon should precede a command\n"); ! 1430: error++; ! 1431: continue; ! 1432: bad_syntax: ! 1433: printf("more letters needed to distinguish command\n"); ! 1434: error++; ! 1435: continue; ! 1436: } ! 1437: } ! 1438: } ! 1439: ! 1440: /* ! 1441: * getachar - get next character from input buffer. ! 1442: */ ! 1443: char ! 1444: getachar() ! 1445: { ! 1446: return(input_buffer[input_pointer++]); ! 1447: } ! 1448: ! 1449: /* ! 1450: * ungetachar - return character to input buffer. ! 1451: */ ! 1452: ungetachar(c) ! 1453: register char c; ! 1454: { ! 1455: if (input_pointer == 0) { ! 1456: printf("internal problem maintaining input buffer\n"); ! 1457: error++; ! 1458: return; ! 1459: } ! 1460: input_buffer[--input_pointer] = c; ! 1461: } ! 1462: ! 1463: /* ! 1464: * getnextinput - display the prompt and read an input line. ! 1465: * An input line is up to 128 characters terminated by the newline ! 1466: * character. Handle overflow, shell escape, and eof. ! 1467: */ ! 1468: getnextinput() ! 1469: { ! 1470: register int i; ! 1471: register char c; ! 1472: register short pid, rpid; ! 1473: int retcode; ! 1474: ! 1475: newline: ! 1476: i = 0; ! 1477: printf("%s", prompt); ! 1478: ignore_eol: ! 1479: while ((c = getc(stdin)) != '\n' && !(c == '!' && i == 0) && ! 1480: !feof(stdin) && i <= INPUTBUFFER - 2) ! 1481: input_buffer[i++] = c; ! 1482: if (input_buffer[i - 1] == '\\') { ! 1483: input_buffer[i++] = c; ! 1484: goto ignore_eol; ! 1485: } ! 1486: if (feof(stdin)) { ! 1487: printf("\n"); ! 1488: exit(0); ! 1489: } ! 1490: if (c == '!') { ! 1491: if ((pid = fork()) == 0) { ! 1492: execl(_PATH_BSHELL, "sh", "-t", 0); ! 1493: error++; ! 1494: return; ! 1495: } ! 1496: while ((rpid = wait(&retcode)) != pid && rpid != -1) ! 1497: ; ! 1498: printf("!\n"); ! 1499: goto newline; ! 1500: } ! 1501: if (c != '\n') ! 1502: printf("input truncated to 128 characters\n"); ! 1503: input_buffer[i] = '\n'; ! 1504: input_pointer = 0; ! 1505: } ! 1506: ! 1507: /* ! 1508: * eat_spaces - read extraneous spaces. ! 1509: */ ! 1510: eat_spaces() ! 1511: { ! 1512: register char c; ! 1513: ! 1514: while ((c = getachar()) == ' ') ! 1515: ; ! 1516: ungetachar(c); ! 1517: } ! 1518: ! 1519: /* ! 1520: * restore_inode - set up all inode indicators so inum is now ! 1521: * the current inode. ! 1522: */ ! 1523: restore_inode(inum) ! 1524: long inum; ! 1525: { ! 1526: errinum = cur_inum = inum; ! 1527: addr = errino = cur_ino = itob(inum); ! 1528: } ! 1529: ! 1530: /* ! 1531: * match - return false if the input does not match string up to ! 1532: * upto letters. Then proceed to chew up extraneous letters. ! 1533: */ ! 1534: match(string, upto) ! 1535: register char *string; ! 1536: register int upto; ! 1537: { ! 1538: register int i, length = strlen(string) - 1; ! 1539: register char c; ! 1540: int save_upto = upto; ! 1541: ! 1542: while (--upto) { ! 1543: string++; ! 1544: if ((c = getachar()) != *string) { ! 1545: for (i = save_upto - upto; i; i--) { ! 1546: ungetachar(c); ! 1547: c = *--string; ! 1548: } ! 1549: return(0); ! 1550: } ! 1551: length--; ! 1552: } ! 1553: while (length--) { ! 1554: string++; ! 1555: if ((c = getachar()) != *string) { ! 1556: ungetachar(c); ! 1557: return(1); ! 1558: } ! 1559: } ! 1560: return(1); ! 1561: } ! 1562: ! 1563: /* ! 1564: * expr - expression evaluator. Will evaluate expressions from ! 1565: * left to right with no operator precedence. Parentheses may ! 1566: * be used. ! 1567: */ ! 1568: long ! 1569: expr() ! 1570: { ! 1571: register long numb = 0, temp; ! 1572: register char c; ! 1573: ! 1574: numb = term(); ! 1575: for (;;) { ! 1576: if (error) ! 1577: return; ! 1578: c = getachar(); ! 1579: switch (c) { ! 1580: ! 1581: case '+': ! 1582: numb += term(); ! 1583: continue; ! 1584: ! 1585: case '-': ! 1586: numb -= term(); ! 1587: continue; ! 1588: ! 1589: case '*': ! 1590: numb *= term(); ! 1591: continue; ! 1592: ! 1593: case '%': ! 1594: temp = term(); ! 1595: if (!temp) { ! 1596: printf("divide by zero\n"); ! 1597: error++; ! 1598: return; ! 1599: } ! 1600: numb /= temp; ! 1601: continue; ! 1602: ! 1603: case ')': ! 1604: paren--; ! 1605: return(numb); ! 1606: ! 1607: default: ! 1608: ungetachar(c); ! 1609: if (paren && !error) { ! 1610: printf("missing ')'\n"); ! 1611: error++; ! 1612: } ! 1613: return(numb); ! 1614: } ! 1615: } ! 1616: } ! 1617: ! 1618: /* ! 1619: * term - used by expression evaluator to get an operand. ! 1620: */ ! 1621: long ! 1622: term() ! 1623: { ! 1624: register char c; ! 1625: ! 1626: switch (c = getachar()) { ! 1627: ! 1628: default: ! 1629: ungetachar(c); ! 1630: ! 1631: case '+': ! 1632: return(getnumb()); ! 1633: ! 1634: case '-': ! 1635: return(-getnumb()); ! 1636: ! 1637: case '(': ! 1638: paren++; ! 1639: return(expr()); ! 1640: } ! 1641: } ! 1642: ! 1643: /* ! 1644: * getnumb - read a number from the input stream. A leading ! 1645: * zero signifies octal interpretation, a leading '0x' ! 1646: * signifies hexadecimal, and a leading '0t' signifies ! 1647: * decimal. If the first character is a character, ! 1648: * return an error. ! 1649: */ ! 1650: long ! 1651: getnumb() ! 1652: { ! 1653: ! 1654: register char c, savec; ! 1655: long number = 0, tbase, num; ! 1656: extern short error; ! 1657: ! 1658: c = getachar(); ! 1659: if (!digit(c)) { ! 1660: error++; ! 1661: ungetachar(c); ! 1662: return(-1); ! 1663: } ! 1664: if (c == '0') { ! 1665: tbase = OCTAL; ! 1666: if ((c = getachar()) == 'x') ! 1667: tbase = HEX; ! 1668: else if (c == 't') ! 1669: tbase = DECIMAL; ! 1670: else ungetachar(c); ! 1671: } else { ! 1672: tbase = base; ! 1673: ungetachar(c); ! 1674: } ! 1675: for (;;) { ! 1676: num = tbase; ! 1677: c = savec = getachar(); ! 1678: if (HEXLETTER(c)) ! 1679: c = uppertolower(c); ! 1680: switch (tbase) { ! 1681: case HEX: ! 1682: if (hexletter(c)) { ! 1683: num = hextodigit(c); ! 1684: break; ! 1685: } ! 1686: case DECIMAL: ! 1687: if (digit(c)) ! 1688: num = numtodigit(c); ! 1689: break; ! 1690: case OCTAL: ! 1691: if (octaldigit(c)) ! 1692: num = numtodigit(c); ! 1693: } ! 1694: if (num == tbase) ! 1695: break; ! 1696: number = number * tbase + num; ! 1697: } ! 1698: ungetachar(savec); ! 1699: return(number); ! 1700: } ! 1701: ! 1702: /* ! 1703: * find - the syntax is almost identical to the unix command. ! 1704: * find dir [-name pattern] [-inum number] ! 1705: * Note: only one of -name or -inum may be used at a time. ! 1706: * Also, the -print is not needed (implied). ! 1707: */ ! 1708: find() ! 1709: { ! 1710: register struct filenames *fn; ! 1711: register char c; ! 1712: long temp; ! 1713: short mode; ! 1714: ! 1715: eat_spaces(); ! 1716: temp = cur_inum; ! 1717: top = filenames - 1; ! 1718: doing_cd = 1; ! 1719: parse(); ! 1720: doing_cd = 0; ! 1721: if (nfiles != 1) { ! 1722: restore_inode(temp); ! 1723: if (!error) { ! 1724: print_path(input_path, input_pathp); ! 1725: if (nfiles == 0) ! 1726: printf(" not found\n"); ! 1727: else ! 1728: printf(" ambiguous\n"); ! 1729: error++; ! 1730: return; ! 1731: } ! 1732: } ! 1733: restore_inode(filenames->ino); ! 1734: freemem(filenames, nfiles); ! 1735: nfiles = 0; ! 1736: top = filenames - 1; ! 1737: if ((mode = icheck(addr)) == 0) ! 1738: return; ! 1739: if ((mode & IFMT) != IFDIR) { ! 1740: print_path(input_path, input_pathp); ! 1741: printf(" not a directory\n"); ! 1742: error++; ! 1743: return; ! 1744: } ! 1745: eat_spaces(); ! 1746: if ((c = getachar()) != '-') { ! 1747: printf("missing '-'\n"); ! 1748: error++; ! 1749: return; ! 1750: } ! 1751: find_by_name = find_by_inode = 0; ! 1752: c = getachar(); ! 1753: if (match("name", 4)) { ! 1754: eat_spaces(); ! 1755: find_by_name = 1; ! 1756: } else if (match("inum", 4)) { ! 1757: eat_spaces(); ! 1758: find_ino = expr(); ! 1759: if (error) ! 1760: return; ! 1761: while ((c = getachar()) != '\n') ! 1762: ; ! 1763: ungetachar(c); ! 1764: find_by_inode = 1; ! 1765: } else { ! 1766: printf("use -name or -inum with find\n"); ! 1767: error++; ! 1768: return; ! 1769: } ! 1770: doing_find = 1; ! 1771: parse(); ! 1772: doing_find = 0; ! 1773: if (error) { ! 1774: restore_inode(temp); ! 1775: return; ! 1776: } ! 1777: for (fn = filenames; fn <= top; fn++) { ! 1778: if (fn->find == 0) ! 1779: continue; ! 1780: printf("i#: "); ! 1781: print(fn->ino, 12, -8, 0); ! 1782: print_path(fn->fname, fn->len); ! 1783: printf("\n"); ! 1784: } ! 1785: restore_inode(temp); ! 1786: } ! 1787: ! 1788: /* ! 1789: * ls - do an ls. Should behave exactly as ls(1). ! 1790: * Only -R and -l is supported and -l gives different results. ! 1791: */ ! 1792: ls(fn0, fnlast, level) ! 1793: struct filenames *fn0, *fnlast; ! 1794: short level; ! 1795: { ! 1796: register struct filenames *fn, *fnn; ! 1797: register int i; ! 1798: int fcmp(); ! 1799: ! 1800: fn = fn0; ! 1801: for (;;) { ! 1802: fn0 = fn; ! 1803: if (fn0->len) { ! 1804: cmp_level = level; ! 1805: qsort((char *)fn0, fnlast - fn0 + 1, ! 1806: sizeof (struct filenames), fcmp); ! 1807: } ! 1808: for (fnn = fn, fn++; fn <= fnlast; fnn = fn, fn++) { ! 1809: if (fnn->len != fn->len && level == fnn->len - 1) ! 1810: break; ! 1811: if (fnn->len == 0) ! 1812: continue; ! 1813: if (strcmp(fn->fname[level], fnn->fname[level])) ! 1814: break; ! 1815: } ! 1816: if (fn0->len && level != fn0->len - 1) ! 1817: ls(fn0, fnn, level + 1); ! 1818: else { ! 1819: if (fn0 != filenames) ! 1820: printf("\n"); ! 1821: print_path(fn0->fname, fn0->len - 1); ! 1822: printf(":\n"); ! 1823: if (fn0->len == 0) ! 1824: cmp_level = level; ! 1825: else ! 1826: cmp_level = level + 1; ! 1827: qsort((char *)fn0, fnn - fn0 + 1, ! 1828: sizeof (struct filenames), fcmp); ! 1829: formatf(fn0, fnn); ! 1830: nfiles -= fnn - fn0 + 1; ! 1831: } ! 1832: if (fn > fnlast) ! 1833: return; ! 1834: } ! 1835: } ! 1836: ! 1837: /* ! 1838: * formatf - code lifted from ls. ! 1839: */ ! 1840: formatf(fn0, fnlast) ! 1841: register struct filenames *fn0, *fnlast; ! 1842: { ! 1843: register struct filenames *fn; ! 1844: int width = 0, w, nentry = fnlast - fn0 + 1; ! 1845: int i, j, columns, lines; ! 1846: char *cp; ! 1847: ! 1848: if (long_list) { ! 1849: columns = 1; ! 1850: } else { ! 1851: for (fn = fn0; fn <= fnlast; fn++) { ! 1852: int len = strlen(fn->fname[cmp_level]) + 2; ! 1853: ! 1854: if (len > width) ! 1855: width = len; ! 1856: } ! 1857: width = (width + 8) &~ 7; ! 1858: columns = 80 / width; ! 1859: if (columns == 0) ! 1860: columns = 1; ! 1861: } ! 1862: lines = (nentry + columns - 1) / columns; ! 1863: for (i = 0; i < lines; i++) { ! 1864: for (j = 0; j < columns; j++) { ! 1865: fn = fn0 + j * lines + i; ! 1866: if (long_list) { ! 1867: printf("i#: "); ! 1868: print(fn->ino, 12, -8, 0); ! 1869: } ! 1870: cp = fmtentry(fn); ! 1871: printf("%s", cp); ! 1872: if (fn + lines > fnlast) { ! 1873: printf("\n"); ! 1874: break; ! 1875: } ! 1876: w = strlen(cp); ! 1877: while (w < width) { ! 1878: w = (w + 8) &~ 7; ! 1879: putchar('\t'); ! 1880: } ! 1881: } ! 1882: } ! 1883: } ! 1884: ! 1885: /* ! 1886: * fmtentry - code lifted from ls. ! 1887: */ ! 1888: char * ! 1889: fmtentry(fn) ! 1890: register struct filenames *fn; ! 1891: { ! 1892: static char fmtres[BUFSIZ]; ! 1893: register struct dinode *ip; ! 1894: register char *cptr, *cp, *dp; ! 1895: ! 1896: dp = &fmtres[0]; ! 1897: for (cp = fn->fname[cmp_level]; *cp; cp++) { ! 1898: if (*cp < ' ' || *cp >= 0177) ! 1899: *dp++ = '?'; ! 1900: else ! 1901: *dp++ = *cp; ! 1902: } ! 1903: addr = itob(fn->ino); ! 1904: if ((cptr = getblk(addr)) == 0) ! 1905: return(NULL); ! 1906: cptr += blkoff(fs, addr); ! 1907: ip = (struct dinode *)cptr; ! 1908: switch (ip->di_mode & IFMT) { ! 1909: case IFDIR: ! 1910: *dp++ = '/'; ! 1911: break; ! 1912: case IFLNK: ! 1913: *dp++ = '@'; ! 1914: break; ! 1915: case IFSOCK: ! 1916: *dp++ = '='; ! 1917: break; ! 1918: #ifdef IFIFO ! 1919: case IFIFO: ! 1920: *dp++ = 'p'; ! 1921: break; ! 1922: #endif ! 1923: case IFCHR: ! 1924: case IFBLK: ! 1925: case IFREG: ! 1926: if (ip->di_mode & 0111) ! 1927: *dp++ = '*'; ! 1928: else ! 1929: *dp++ = ' '; ! 1930: break; ! 1931: default: ! 1932: *dp++ = '?'; ! 1933: ! 1934: } ! 1935: *dp++ = 0; ! 1936: return (fmtres); ! 1937: } ! 1938: ! 1939: /* ! 1940: * fcmp - routine used by qsort. Will sort first by name, then ! 1941: * then by pathname length if names are equal. Uses global ! 1942: * cmp_level to tell what component of the path name we are comparing. ! 1943: */ ! 1944: fcmp(f1, f2) ! 1945: register struct filenames *f1, *f2; ! 1946: { ! 1947: int value; ! 1948: ! 1949: if ((value = strcmp(f1->fname[cmp_level], f2->fname[cmp_level]))) ! 1950: return(value); ! 1951: return (f1->len - f2->len); ! 1952: } ! 1953: ! 1954: /* ! 1955: * ffcmp - routine used by qsort. Sort only by pathname length. ! 1956: */ ! 1957: ffcmp(f1, f2) ! 1958: register struct filenames *f1, *f2; ! 1959: { ! 1960: return (f1->len - f2->len); ! 1961: } ! 1962: ! 1963: /* ! 1964: * parse - set up the call to follow_path. ! 1965: */ ! 1966: parse() ! 1967: { ! 1968: register int i, j; ! 1969: char c; ! 1970: ! 1971: stack_pathp = input_pathp = -1; ! 1972: if ((c = getachar()) == '/') { ! 1973: while ((c = getachar()) == '/') ! 1974: ; ! 1975: ungetachar(c); ! 1976: cur_inum = 2; ! 1977: if ((c = getachar()) == '\n') { ! 1978: ungetachar('\n'); ! 1979: if (doing_cd) { ! 1980: top++; ! 1981: top->ino = 2; ! 1982: top->len = -1; ! 1983: nfiles = 1; ! 1984: return; ! 1985: } ! 1986: } else ! 1987: ungetachar(c); ! 1988: } else { ! 1989: ungetachar(c); ! 1990: stack_pathp = current_pathp; ! 1991: if (!doing_find) ! 1992: input_pathp = current_pathp; ! 1993: for (i = 0; i <= current_pathp; i++) { ! 1994: if (!doing_find) ! 1995: strcpy(input_path[i], current_path[i]); ! 1996: strcpy(stack_path[i], current_path[i]); ! 1997: } ! 1998: } ! 1999: getname(); ! 2000: follow_path(stack_pathp + 1, cur_inum); ! 2001: } ! 2002: ! 2003: /* ! 2004: * follow_path - called by cd, find, and ls. ! 2005: * input_path holds the name typed by the user. ! 2006: * stack_path holds the name at the current depth. ! 2007: */ ! 2008: follow_path(level, inum) ! 2009: long level, inum; ! 2010: { ! 2011: register struct direct *dirp; ! 2012: register char **ccptr, *cptr, c; ! 2013: register int i; ! 2014: struct filenames *tos, *bos, *fn, *fnn, *fnnn; ! 2015: long block; ! 2016: short mode; ! 2017: ! 2018: tos = top + 1; ! 2019: restore_inode(inum); ! 2020: if ((mode = icheck(addr)) == 0) ! 2021: return; ! 2022: if ((mode & IFMT) != IFDIR) ! 2023: return; ! 2024: block = cur_bytes = 0; ! 2025: while (cur_bytes < filesize) { ! 2026: if (block == 0 || bcomp(addr)) { ! 2027: error = 0; ! 2028: if ((addr = (bmap(block++) << FRGSHIFT)) == 0) ! 2029: break; ! 2030: if ((cptr = getblk(addr)) == 0) ! 2031: break; ! 2032: cptr += blkoff(fs, addr); ! 2033: } ! 2034: dirp = (struct direct *)cptr; ! 2035: if (dirp->d_ino) { ! 2036: if (level > input_pathp || doing_find || ! 2037: compare(input_path[level], &dirp->d_name[0], 1)) { ! 2038: if (++top - filenames >= MAXFILES) { ! 2039: printf("too many files\n"); ! 2040: error++; ! 2041: return; ! 2042: } ! 2043: top->fname = (char **)calloc(FIRST_DEPTH, sizeof (char **)); ! 2044: top->flag = 0; ! 2045: if (top->fname == 0) { ! 2046: printf("out of memory\n"); ! 2047: error++; ! 2048: return; ! 2049: } ! 2050: nfiles++; ! 2051: top->ino = dirp->d_ino; ! 2052: top->len = stack_pathp; ! 2053: top->find = 0; ! 2054: if (doing_find) { ! 2055: if (find_by_name) { ! 2056: if (compare(input_path[0], &dirp->d_name[0], 1)) ! 2057: top->find = 1; ! 2058: } else if (find_by_inode) ! 2059: if (find_ino == dirp->d_ino) ! 2060: top->find = 1; ! 2061: } ! 2062: if (top->len + 1 >= FIRST_DEPTH && top->flag == 0) { ! 2063: ccptr = (char **)calloc(SECOND_DEPTH, sizeof (char **)); ! 2064: if (ccptr == 0) { ! 2065: printf("out of memory\n"); ! 2066: error++; ! 2067: return; ! 2068: } ! 2069: for (i = 0; i < FIRST_DEPTH; i++) ! 2070: ccptr[i] = top->fname[i]; ! 2071: free((char *)top->fname); ! 2072: top->fname = ccptr; ! 2073: top->flag = 1; ! 2074: } ! 2075: if (top->len >= SECOND_DEPTH) { ! 2076: printf("maximum depth exceeded, try to cd lower\n"); ! 2077: error++; ! 2078: return; ! 2079: } ! 2080: /* ! 2081: * Copy current depth. ! 2082: */ ! 2083: for (i = 0; i <= stack_pathp; i++) { ! 2084: top->fname[i]=calloc(1, strlen(stack_path[i])+1); ! 2085: if (top->fname[i] == 0) { ! 2086: printf("out of memory\n"); ! 2087: error++; ! 2088: return; ! 2089: } ! 2090: strcpy(top->fname[i], stack_path[i]); ! 2091: } ! 2092: /* ! 2093: * Check for '.' or '..' typed. ! 2094: */ ! 2095: if ((level <= input_pathp) && ! 2096: (strcmp(input_path[level], ".") == 0 || ! 2097: strcmp(input_path[level], "..") == 0)) { ! 2098: if (strcmp(input_path[level],"..") == 0 && ! 2099: top->len >= 0) { ! 2100: free(top->fname[top->len]); ! 2101: top->len -= 1; ! 2102: } ! 2103: } else { ! 2104: /* ! 2105: * Check for duplicates. ! 2106: */ ! 2107: if (!doing_cd && !doing_find) { ! 2108: for (fn = filenames; fn < top; fn++) { ! 2109: if (fn->ino == dirp->d_ino && ! 2110: fn->len == stack_pathp + 1) { ! 2111: for (i = 0; i < fn->len; i++) ! 2112: if (strcmp(fn->fname[i], stack_path[i])) ! 2113: break; ! 2114: if (i != fn->len || ! 2115: strcmp(fn->fname[i], dirp->d_name)) ! 2116: continue; ! 2117: freemem(top, 1); ! 2118: if (top == filenames) ! 2119: top = NULL; ! 2120: else ! 2121: top--; ! 2122: nfiles--; ! 2123: goto duplicate; ! 2124: } ! 2125: } ! 2126: } ! 2127: top->len += 1; ! 2128: top->fname[top->len] = calloc(1, ! 2129: strlen(&dirp->d_name[0])+1); ! 2130: if (top->fname[top->len] == 0) { ! 2131: printf("out of memory\n"); ! 2132: error++; ! 2133: return; ! 2134: } ! 2135: strcpy(top->fname[top->len], &dirp->d_name[0]); ! 2136: } ! 2137: } ! 2138: } ! 2139: duplicate: ! 2140: addr += dirp->d_reclen; ! 2141: cptr += dirp->d_reclen; ! 2142: cur_bytes += dirp->d_reclen; ! 2143: } ! 2144: if (top < filenames) ! 2145: return; ! 2146: if ((doing_cd && level == input_pathp) || ! 2147: (!recursive && !doing_find && level > input_pathp)) ! 2148: return; ! 2149: bos = top; ! 2150: /* ! 2151: * Check newly added entries to determine if further expansion ! 2152: * is required. ! 2153: */ ! 2154: for (fn = tos; fn <= bos; fn++) { ! 2155: /* ! 2156: * Avoid '.' and '..' if beyond input. ! 2157: */ ! 2158: if ((recursive || doing_find) && (level > input_pathp) && ! 2159: (strcmp(fn->fname[fn->len], ".") == 0 || ! 2160: strcmp(fn->fname[fn->len], "..") == 0)) ! 2161: continue; ! 2162: restore_inode(fn->ino); ! 2163: if ((mode = icheck(cur_ino)) == 0) ! 2164: return; ! 2165: if ((mode & IFMT) == IFDIR || level < input_pathp) { ! 2166: /* ! 2167: * Set up current depth, remove current entry and ! 2168: * continue recursion. ! 2169: */ ! 2170: for (i = 0; i <= fn->len; i++) ! 2171: strcpy(stack_path[i], fn->fname[i]); ! 2172: stack_pathp = fn->len; ! 2173: if (!doing_find && ! 2174: (!recursive || (recursive && level <= input_pathp))) { ! 2175: /* ! 2176: * Remove current entry by moving others up. ! 2177: */ ! 2178: freemem(fn, 1); ! 2179: fnn = fn; ! 2180: for (fnnn = fnn, fnn++; fnn <= top; fnnn = fnn, fnn++) { ! 2181: fnnn->ino = fnn->ino; ! 2182: fnnn->len = fnn->len; ! 2183: if (fnnn->len + 1 < FIRST_DEPTH) { ! 2184: fnnn->fname = (char **)calloc(FIRST_DEPTH, ! 2185: sizeof (char **)); ! 2186: fnnn->flag = 0; ! 2187: } else if (fnnn->len < SECOND_DEPTH) { ! 2188: fnnn->fname = (char **)calloc(SECOND_DEPTH, ! 2189: sizeof (char **)); ! 2190: fnnn->flag = 1; ! 2191: } else { ! 2192: printf("maximum depth exceeded, "); ! 2193: printf("try to cd lower\n"); ! 2194: error++; ! 2195: return; ! 2196: } ! 2197: for (i = 0; i <= fnn->len; i++) ! 2198: fnnn->fname[i] = fnn->fname[i]; ! 2199: } ! 2200: if (fn == tos) ! 2201: fn--; ! 2202: top--; ! 2203: bos--; ! 2204: nfiles--; ! 2205: } ! 2206: follow_path(level + 1, cur_inum); ! 2207: if (error) ! 2208: return; ! 2209: } ! 2210: } ! 2211: } ! 2212: ! 2213: /* ! 2214: * getname - break up the pathname entered by the user into components. ! 2215: */ ! 2216: getname() ! 2217: { ! 2218: register int i; ! 2219: char c; ! 2220: ! 2221: if ((c = getachar()) == '\n') { ! 2222: ungetachar(c); ! 2223: return; ! 2224: } ! 2225: ungetachar(c); ! 2226: input_pathp++; ! 2227: clear: ! 2228: for (i = 0; i < MAXNAMLEN; i++) ! 2229: input_path[input_pathp][i] = '\0'; ! 2230: for (;;) { ! 2231: c = getachar(); ! 2232: if (c == '\\') { ! 2233: if (strlen(input_path[input_pathp]) + 1 >= MAXNAMLEN) { ! 2234: printf("maximum name length exceeded, "); ! 2235: printf("truncating\n"); ! 2236: return; ! 2237: } ! 2238: input_path[input_pathp][strlen(input_path[input_pathp])] = c; ! 2239: input_path[input_pathp][strlen(input_path[input_pathp])] = ! 2240: getachar(); ! 2241: continue; ! 2242: } ! 2243: if (c == ' ' || c == '\n') { ! 2244: ungetachar(c); ! 2245: return; ! 2246: } ! 2247: if (!doing_find && c == '/') { ! 2248: if (++input_pathp >= MAXPATHLEN) { ! 2249: printf("maximum path length exceeded, "); ! 2250: printf("truncating\n"); ! 2251: input_pathp--; ! 2252: return; ! 2253: } ! 2254: goto clear; ! 2255: } ! 2256: if (strlen(input_path[input_pathp]) >= MAXNAMLEN) { ! 2257: printf("maximum name length exceeded, truncating\n"); ! 2258: return; ! 2259: } ! 2260: input_path[input_pathp][strlen(input_path[input_pathp])] = c; ! 2261: } ! 2262: } ! 2263: ! 2264: /* ! 2265: * compare - check if a filename matches the pattern entered by the user. ! 2266: * Handles '*', '?', and '[]'. ! 2267: */ ! 2268: compare(s1, s2, at_start) ! 2269: char *s1, *s2; ! 2270: short at_start; ! 2271: { ! 2272: register char c, *s; ! 2273: ! 2274: s = s2; ! 2275: while (c = *s1) { ! 2276: if (c == '*') { ! 2277: if (at_start && s == s2 && !letter(*s2) && !digit(*s2)) ! 2278: return(0); ! 2279: if (*++s1 == 0) ! 2280: return(1); ! 2281: while (*s2) { ! 2282: if (compare(s1, s2, 0)) ! 2283: return(1); ! 2284: if (error) ! 2285: return(0); ! 2286: s2++; ! 2287: } ! 2288: } ! 2289: if (*s2 == 0) ! 2290: return(0); ! 2291: if (c == '\\') { ! 2292: s1++; ! 2293: goto compare_chars; ! 2294: } ! 2295: if (c == '?') { ! 2296: if (at_start && s == s2 && !letter(*s2) && !digit(*s2)) ! 2297: return(0); ! 2298: s1++; ! 2299: s2++; ! 2300: continue; ! 2301: } ! 2302: if (c == '[') { ! 2303: s1++; ! 2304: if (*s2 >= *s1++) { ! 2305: if (*s1++ != '-') { ! 2306: printf("missing '-'\n"); ! 2307: error++; ! 2308: return(0); ! 2309: } ! 2310: if (*s2 <= *s1++) { ! 2311: if (*s1++ != ']') { ! 2312: printf("missing ']'"); ! 2313: error++; ! 2314: return(0); ! 2315: } ! 2316: s2++; ! 2317: continue; ! 2318: } ! 2319: } ! 2320: } ! 2321: compare_chars: ! 2322: if (*s1++ == *s2++) ! 2323: continue; ! 2324: else ! 2325: return(0); ! 2326: } ! 2327: if (*s1 == *s2) ! 2328: return(1); ! 2329: return(0); ! 2330: } ! 2331: ! 2332: /* ! 2333: * freemem - free the memory allocated to the filenames structure. ! 2334: */ ! 2335: freemem(p, numb) ! 2336: struct filenames *p; ! 2337: int numb; ! 2338: { ! 2339: register int i, j; ! 2340: ! 2341: if (numb == 0) ! 2342: return; ! 2343: for (i = 0; i < numb; i++, p++) { ! 2344: for (j = 0; j <= p->len; j++) ! 2345: free(p->fname[j]); ! 2346: free((char *)p->fname); ! 2347: } ! 2348: } ! 2349: ! 2350: /* ! 2351: * print_path - print the pathname held in p. ! 2352: */ ! 2353: print_path(p, pntr) ! 2354: char *p[]; ! 2355: short pntr; ! 2356: { ! 2357: register int i; ! 2358: ! 2359: printf("/"); ! 2360: if (pntr >= 0) { ! 2361: for (i = 0; i < pntr; i++) ! 2362: printf("%s/", p[i]); ! 2363: printf("%s", p[pntr]); ! 2364: } ! 2365: } ! 2366: ! 2367: /* ! 2368: * fill - fill a section with a value or string. ! 2369: * addr,count:fill=[value, "string"]. ! 2370: */ ! 2371: fill() ! 2372: { ! 2373: register char *cptr; ! 2374: register int i; ! 2375: short eof_flag, end = 0, eof = 0; ! 2376: long temp, tcount, taddr; ! 2377: ! 2378: if (!wrtflag) { ! 2379: printf("not opened for write '-w'\n"); ! 2380: error++; ! 2381: return; ! 2382: } ! 2383: temp = expr(); ! 2384: if (error) ! 2385: return; ! 2386: if ((cptr = getblk(addr)) == 0) ! 2387: return; ! 2388: if (type == NUMB) ! 2389: eof_flag = 0; ! 2390: else ! 2391: eof_flag = 1; ! 2392: taddr = addr; ! 2393: switch (objsz) { ! 2394: case LONG: ! 2395: addr &= ~(LONG - 1); ! 2396: break; ! 2397: case SHORT: ! 2398: addr &= ~(SHORT - 1); ! 2399: temp &= 0177777L; ! 2400: break; ! 2401: case CHAR: ! 2402: temp &= 0377; ! 2403: } ! 2404: cur_bytes -= taddr - addr; ! 2405: cptr += blkoff(fs, addr); ! 2406: tcount = check_addr(eof_flag, &end, &eof, 0); ! 2407: for (i = 0; i < tcount; i++) { ! 2408: switch (objsz) { ! 2409: case LONG: ! 2410: *(long *)cptr = temp; ! 2411: break; ! 2412: case SHORT: ! 2413: *(short *)cptr = temp; ! 2414: break; ! 2415: case CHAR: ! 2416: *cptr = temp; ! 2417: } ! 2418: cptr += objsz; ! 2419: } ! 2420: addr += (tcount - 1) * objsz; ! 2421: cur_bytes += (tcount - 1) * objsz; ! 2422: put(temp, objsz); ! 2423: if (eof) { ! 2424: printf("end of file\n"); ! 2425: error++; ! 2426: } else if (end) { ! 2427: printf("end of block\n"); ! 2428: error++; ! 2429: } ! 2430: } ! 2431: ! 2432: /* ! 2433: * get - read a byte, short or long from the file system. ! 2434: * The entire block containing the desired item is read ! 2435: * and the appropriate data is extracted and returned. ! 2436: */ ! 2437: long ! 2438: get(lngth) ! 2439: short lngth; ! 2440: { ! 2441: ! 2442: register char *bptr; ! 2443: long temp = addr; ! 2444: ! 2445: objsz = lngth; ! 2446: if (objsz == INODE || objsz == SHORT) ! 2447: temp &= ~(SHORT - 1); ! 2448: else if (objsz == DIRECTORY || objsz == LONG) ! 2449: temp &= ~(LONG - 1); ! 2450: if ((bptr = getblk(temp)) == 0) ! 2451: return(-1); ! 2452: bptr += blkoff(fs, temp); ! 2453: switch (objsz) { ! 2454: case CHAR: ! 2455: return((long)*bptr); ! 2456: case SHORT: ! 2457: case INODE: ! 2458: return((long)(*(short *)bptr)); ! 2459: case LONG: ! 2460: case DIRECTORY: ! 2461: return(*(long *)bptr); ! 2462: } ! 2463: return(0); ! 2464: } ! 2465: ! 2466: /* ! 2467: * cgrp_check - make sure that we don't bump the cylinder group ! 2468: * beyond the total number of cylinder groups or before the start. ! 2469: */ ! 2470: cgrp_check(cgrp) ! 2471: long cgrp; ! 2472: { ! 2473: if (cgrp < 0) { ! 2474: if (objsz == CGRP) ! 2475: printf("beginning of cylinder groups\n"); ! 2476: else ! 2477: printf("beginning of super blocks\n"); ! 2478: error++; ! 2479: return(0); ! 2480: } ! 2481: if (cgrp >= fs->fs_ncg) { ! 2482: if (objsz == CGRP) ! 2483: printf("end of cylinder groups\n"); ! 2484: else ! 2485: printf("end of super blocks\n"); ! 2486: error++; ! 2487: return(0); ! 2488: } ! 2489: if (objsz == CGRP) ! 2490: return(cgtod(fs, cgrp) << FRGSHIFT); ! 2491: else ! 2492: return(cgsblock(fs, cgrp) << FRGSHIFT); ! 2493: } ! 2494: ! 2495: /* ! 2496: * icheck - make sure we can read the block containing the inode ! 2497: * and determine the filesize (0 if inode not allocated). Return ! 2498: * 0 if error otherwise return the mode. ! 2499: */ ! 2500: icheck(address) ! 2501: long address; ! 2502: { ! 2503: register char *cptr; ! 2504: register struct dinode *ip; ! 2505: ! 2506: if ((cptr = getblk(address)) == 0) ! 2507: return(0); ! 2508: cptr += blkoff(fs, address); ! 2509: ip = (struct dinode *)cptr; ! 2510: if ((ip->di_mode & IFMT) == 0) { ! 2511: if (!override) { ! 2512: printf("inode not allocated\n"); ! 2513: error++; ! 2514: return(0); ! 2515: } ! 2516: blocksize = filesize = 0; ! 2517: } else { ! 2518: trapped++; ! 2519: filesize = ip->di_size; ! 2520: blocksize = filesize * 2; ! 2521: } ! 2522: return(ip->di_mode); ! 2523: } ! 2524: ! 2525: /* ! 2526: * getdirslot - get the address of the directory slot desired. ! 2527: */ ! 2528: getdirslot(slot) ! 2529: short slot; ! 2530: { ! 2531: register char *cptr; ! 2532: register struct direct *dirp; ! 2533: register short i; ! 2534: char *string = &scratch[0]; ! 2535: short bod = 0, mode, temp; ! 2536: ! 2537: if (slot < 0) { ! 2538: slot = 0; ! 2539: bod++; ! 2540: } ! 2541: if (type != DIRECTORY) { ! 2542: if (type == BLOCK) ! 2543: string = "block"; ! 2544: else ! 2545: string = "fragment"; ! 2546: addr = bod_addr; ! 2547: if ((cptr = getblk(addr)) == 0) ! 2548: return(0); ! 2549: cptr += blkoff(fs, addr); ! 2550: cur_bytes = 0; ! 2551: dirp = (struct direct *)cptr; ! 2552: for (dirslot = 0; dirslot < slot; dirslot++) { ! 2553: dirp = (struct direct *)cptr; ! 2554: if (blocksize > filesize) { ! 2555: if (cur_bytes + dirp->d_reclen >= filesize) { ! 2556: printf("end of file\n"); ! 2557: erraddr = addr; ! 2558: errcur_bytes = cur_bytes; ! 2559: stringsize = STRINGSIZE(dirp); ! 2560: error++; ! 2561: return(addr); ! 2562: } ! 2563: } else { ! 2564: if (cur_bytes + dirp->d_reclen >= blocksize) { ! 2565: printf("end of %s\n", string); ! 2566: erraddr = addr; ! 2567: errcur_bytes = cur_bytes; ! 2568: stringsize = STRINGSIZE(dirp); ! 2569: error++; ! 2570: return(addr); ! 2571: } ! 2572: } ! 2573: cptr += dirp->d_reclen; ! 2574: addr += dirp->d_reclen; ! 2575: cur_bytes += dirp->d_reclen; ! 2576: } ! 2577: if (bod) { ! 2578: if (blocksize > filesize) ! 2579: printf("beginning of file\n"); ! 2580: else ! 2581: printf("beginning of %s\n", string); ! 2582: erraddr = addr; ! 2583: errcur_bytes = cur_bytes; ! 2584: error++; ! 2585: } ! 2586: stringsize = STRINGSIZE(dirp); ! 2587: return(addr); ! 2588: } else { ! 2589: addr = cur_ino; ! 2590: if ((mode = icheck(addr)) == 0) ! 2591: return(0); ! 2592: if (!override && (mode & IFDIR) == 0) { ! 2593: printf("inode is not a directory\n"); ! 2594: error++; ! 2595: return(0); ! 2596: } ! 2597: temp = slot; ! 2598: i = cur_bytes = 0; ! 2599: for (;;) { ! 2600: if (i == 0 || bcomp(addr)) { ! 2601: error = 0; ! 2602: if ((addr=(bmap(i++) << FRGSHIFT)) == 0) ! 2603: break; ! 2604: if ((cptr = getblk(addr)) == 0) ! 2605: break; ! 2606: cptr += blkoff(fs, addr); ! 2607: } ! 2608: dirp = (struct direct *)cptr; ! 2609: value = dirp->d_ino; ! 2610: if (!temp--) ! 2611: break; ! 2612: if (cur_bytes + dirp->d_reclen >= filesize) { ! 2613: printf("end of file\n"); ! 2614: dirslot = slot - temp - 1; ! 2615: objsz = DIRECTORY; ! 2616: erraddr = addr; ! 2617: errcur_bytes = cur_bytes; ! 2618: stringsize = STRINGSIZE(dirp); ! 2619: error++; ! 2620: return(addr); ! 2621: } ! 2622: addr += dirp->d_reclen; ! 2623: cptr += dirp->d_reclen; ! 2624: cur_bytes += dirp->d_reclen; ! 2625: } ! 2626: dirslot = slot; ! 2627: objsz = DIRECTORY; ! 2628: if (bod) { ! 2629: printf("beginning of file\n"); ! 2630: erraddr = addr; ! 2631: errcur_bytes = cur_bytes; ! 2632: error++; ! 2633: } ! 2634: stringsize = STRINGSIZE(dirp); ! 2635: return(addr); ! 2636: } ! 2637: } ! 2638: ! 2639: /* ! 2640: * putf - print a byte as an ascii character if possible. ! 2641: * The exceptions are tabs, newlines, backslashes ! 2642: * and nulls which are printed as the standard C ! 2643: * language escapes. Characters which are not ! 2644: * recognized are printed as \?. ! 2645: */ ! 2646: putf(c) ! 2647: register char c; ! 2648: { ! 2649: ! 2650: if (c<=037 || c>=0177 || c=='\\') { ! 2651: printf("\\"); ! 2652: switch (c) { ! 2653: case '\\': ! 2654: printf("\\"); ! 2655: break; ! 2656: case '\t': ! 2657: printf("t"); ! 2658: break; ! 2659: case '\n': ! 2660: printf("n"); ! 2661: break; ! 2662: case '\0': ! 2663: printf("0"); ! 2664: break; ! 2665: default: ! 2666: printf("?"); ! 2667: } ! 2668: } ! 2669: else { ! 2670: printf("%c", c); ! 2671: printf(" "); ! 2672: } ! 2673: } ! 2674: ! 2675: /* ! 2676: * put - write an item into the buffer for the current address ! 2677: * block. The value is checked to make sure that it will ! 2678: * fit in the size given without truncation. If successful, ! 2679: * the entire block is written back to the file system. ! 2680: */ ! 2681: put(item,lngth) ! 2682: long item; ! 2683: short lngth; ! 2684: { ! 2685: ! 2686: register char *bptr, *sbptr; ! 2687: register long *vptr; ! 2688: long s_err,nbytes; ! 2689: long olditem; ! 2690: ! 2691: if (!wrtflag) { ! 2692: printf("not opened for write '-w'\n"); ! 2693: error++; ! 2694: return; ! 2695: } ! 2696: objsz = lngth; ! 2697: if ((sbptr = getblk(addr)) == 0) ! 2698: return; ! 2699: bptr = sbptr + blkoff(fs, addr); ! 2700: switch (objsz) { ! 2701: case LONG: ! 2702: case DIRECTORY: ! 2703: olditem = *(long *)bptr; ! 2704: *(long *)bptr = item; ! 2705: break; ! 2706: case SHORT: ! 2707: case INODE: ! 2708: olditem = (long)*(short *)bptr; ! 2709: item &= 0177777L; ! 2710: *(short *)bptr = item; ! 2711: break; ! 2712: case CHAR: ! 2713: olditem = (long)*bptr; ! 2714: item &= 0377; ! 2715: *bptr = lobyte(loword(item)); ! 2716: break; ! 2717: default: ! 2718: error++; ! 2719: return; ! 2720: } ! 2721: if ((s_err = lseek(fd, addr & fs->fs_bmask, 0)) == -1) { ! 2722: error++; ! 2723: printf("seek error : %x\n",addr); ! 2724: return(0); ! 2725: } ! 2726: if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) { ! 2727: error++; ! 2728: printf("write error : addr = %x\n",addr); ! 2729: printf(" : s_err = %x\n",s_err); ! 2730: printf(" : nbytes = %x\n",nbytes); ! 2731: return(0); ! 2732: } ! 2733: if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) { ! 2734: index(base); ! 2735: print(olditem, 8, -8, 0); ! 2736: printf("\t=\t"); ! 2737: print(item, 8, -8, 0); ! 2738: printf("\n"); ! 2739: } else { ! 2740: if (objsz == DIRECTORY) { ! 2741: addr = cur_dir; ! 2742: fprnt('?', 'd'); ! 2743: } else { ! 2744: addr = cur_ino; ! 2745: objsz = INODE; ! 2746: fprnt('?', 'i'); ! 2747: } ! 2748: } ! 2749: return; ! 2750: } ! 2751: ! 2752: /* ! 2753: * getblk - check if the desired block is in the file system. ! 2754: * Search the incore buffers to see if the block is already ! 2755: * available. If successful, unlink the buffer control block ! 2756: * from its position in the buffer list and re-insert it at ! 2757: * the head of the list. If failure, use the last buffer ! 2758: * in the list for the desired block. Again, this control ! 2759: * block is placed at the head of the list. This process ! 2760: * will leave commonly requested blocks in the in-core buffers. ! 2761: * Finally, a pointer to the buffer is returned. ! 2762: */ ! 2763: char * ! 2764: getblk(address) ! 2765: long address; ! 2766: { ! 2767: ! 2768: register struct buf *bp; ! 2769: long s_err, nbytes; ! 2770: unsigned long block; ! 2771: ! 2772: read_requests++; ! 2773: block = lblkno(fs, address); ! 2774: if (block >= fragstoblks(fs, fs->fs_size)) { ! 2775: printf("block exceeds maximum block in file system\n"); ! 2776: error++; ! 2777: return(0); ! 2778: } ! 2779: for (bp=bhdr.fwd; bp!= &bhdr; bp=bp->fwd) ! 2780: if (bp->valid && bp->blkno==block) ! 2781: goto xit; ! 2782: actual_disk_reads++; ! 2783: bp = bhdr.back; ! 2784: bp->blkno = block; ! 2785: bp->valid = 0; ! 2786: if ((s_err = lseek(fd, address & fs->fs_bmask, 0)) == -1) { ! 2787: error++; ! 2788: printf("seek error : %x\n",address); ! 2789: return(0); ! 2790: } ! 2791: if ((nbytes = read(fd, bp->blkaddr, BLKSIZE)) != BLKSIZE) { ! 2792: error++; ! 2793: printf("read error : addr = %x\n",address); ! 2794: printf(" : s_err = %x\n",s_err); ! 2795: printf(" : nbytes = %x\n",nbytes); ! 2796: return(0); ! 2797: } ! 2798: bp->valid++; ! 2799: xit: bp->back->fwd = bp->fwd; ! 2800: bp->fwd->back = bp->back; ! 2801: insert(bp); ! 2802: return(bp->blkaddr); ! 2803: } ! 2804: ! 2805: /* ! 2806: * insert - place the designated buffer control block ! 2807: * at the head of the linked list of buffers. ! 2808: */ ! 2809: insert(bp) ! 2810: register struct buf *bp; ! 2811: { ! 2812: ! 2813: bp->back = &bhdr; ! 2814: bp->fwd = bhdr.fwd; ! 2815: bhdr.fwd->back = bp; ! 2816: bhdr.fwd = bp; ! 2817: } ! 2818: ! 2819: /* ! 2820: * err - called on interrupts. Set the current address ! 2821: * back to the last address stored in erraddr. Reset all ! 2822: * appropriate flags. A reset call is made to return ! 2823: * to the main loop; ! 2824: */ ! 2825: err() ! 2826: { ! 2827: freemem(filenames, nfiles); ! 2828: nfiles = 0; ! 2829: signal(2,err); ! 2830: addr = erraddr; ! 2831: cur_ino = errino; ! 2832: cur_inum = errinum; ! 2833: cur_bytes = errcur_bytes; ! 2834: error = 0; ! 2835: c_count = 0; ! 2836: printf("\n?\n"); ! 2837: fseek(stdin, 0L, 2); ! 2838: longjmp(env,0); ! 2839: } ! 2840: ! 2841: /* ! 2842: * devcheck - check that the given mode represents a ! 2843: * special device. The IFCHR bit is on for both ! 2844: * character and block devices. ! 2845: */ ! 2846: devcheck(md) ! 2847: register short md; ! 2848: { ! 2849: if (override) ! 2850: return(0); ! 2851: if (md & IFCHR) ! 2852: return(0); ! 2853: printf("not character or block device\n"); ! 2854: error++; ! 2855: return(1); ! 2856: } ! 2857: ! 2858: /* ! 2859: * nullblk - return error if address is zero. This is done ! 2860: * to prevent block 0 from being used as an indirect block ! 2861: * for a large file or as a data block for a small file. ! 2862: */ ! 2863: nullblk(bn) ! 2864: long bn; ! 2865: { ! 2866: if (bn != 0) ! 2867: return(0); ! 2868: printf("non existent block\n"); ! 2869: error++; ! 2870: return(1); ! 2871: } ! 2872: ! 2873: /* ! 2874: * puta - put ascii characters into a buffer. The string ! 2875: * terminates with a quote or newline. The leading quote, ! 2876: * which is optional for directory names, was stripped off ! 2877: * by the assignment case in the main loop. ! 2878: */ ! 2879: puta() ! 2880: { ! 2881: register char *cptr, c; ! 2882: register int i; ! 2883: char *sbptr; ! 2884: short terror = 0; ! 2885: long maxchars, s_err, nbytes, temp; ! 2886: long taddr = addr, tcount = 0, item, olditem = 0; ! 2887: ! 2888: if (!wrtflag) { ! 2889: printf("not opened for write '-w'\n"); ! 2890: error++; ! 2891: return; ! 2892: } ! 2893: if ((sbptr = getblk(addr)) == 0) ! 2894: return; ! 2895: cptr = sbptr + blkoff(fs, addr); ! 2896: if (objsz == DIRECTORY) { ! 2897: if (acting_on_directory) ! 2898: maxchars = stringsize - 1; ! 2899: else ! 2900: maxchars = LONG; ! 2901: } else if (objsz == INODE) ! 2902: maxchars = objsz - (addr - cur_ino); ! 2903: else ! 2904: maxchars = min(blocksize - cur_bytes, filesize - cur_bytes); ! 2905: while ((c = getachar()) != '"') { ! 2906: if (tcount >= maxchars) { ! 2907: printf("string too long\n"); ! 2908: if (objsz == DIRECTORY) ! 2909: addr = cur_dir; ! 2910: else if (acting_on_inode || objsz == INODE) ! 2911: addr = cur_ino; ! 2912: else ! 2913: addr = taddr; ! 2914: erraddr = addr; ! 2915: errcur_bytes = cur_bytes; ! 2916: terror++; ! 2917: break; ! 2918: } ! 2919: tcount++; ! 2920: if (c == '\n') { ! 2921: ungetachar(c); ! 2922: break; ! 2923: } ! 2924: temp = (long)*cptr; ! 2925: olditem <<= BITSPERCHAR; ! 2926: olditem += temp & 0xff; ! 2927: if (c == '\\') { ! 2928: switch (c = getachar()) { ! 2929: case 't': ! 2930: *cptr++ = '\t'; ! 2931: break; ! 2932: case 'n': ! 2933: *cptr++ = '\n'; ! 2934: break; ! 2935: case '0': ! 2936: *cptr++ = '\0'; ! 2937: break; ! 2938: default: ! 2939: *cptr++ = c; ! 2940: break; ! 2941: } ! 2942: } ! 2943: else ! 2944: *cptr++ = c; ! 2945: } ! 2946: if (objsz == DIRECTORY && acting_on_directory) ! 2947: for (i = tcount; i <= maxchars; i++) ! 2948: *cptr++ = '\0'; ! 2949: if ((s_err = lseek(fd, addr & fs->fs_bmask, 0)) == -1) { ! 2950: error++; ! 2951: printf("seek error : %x\n",addr); ! 2952: return(0); ! 2953: } ! 2954: if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) { ! 2955: error++; ! 2956: printf("write error : addr = %x\n",addr); ! 2957: printf(" : s_err = %x\n",s_err); ! 2958: printf(" : nbytes = %x\n",nbytes); ! 2959: return(0); ! 2960: } ! 2961: if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) { ! 2962: addr += tcount; ! 2963: cur_bytes += tcount; ! 2964: taddr = addr; ! 2965: if (objsz != CHAR) { ! 2966: addr &= ~(objsz - 1); ! 2967: cur_bytes -= taddr - addr; ! 2968: } ! 2969: if (addr == taddr) { ! 2970: addr -= objsz; ! 2971: taddr = addr; ! 2972: } ! 2973: tcount = LONG - (taddr - addr); ! 2974: index(base); ! 2975: if ((cptr = getblk(addr)) == 0) ! 2976: return; ! 2977: cptr += blkoff(fs, addr); ! 2978: switch (objsz) { ! 2979: case LONG: ! 2980: item = *(long *)cptr; ! 2981: if (tcount < LONG) { ! 2982: olditem <<= tcount * BITSPERCHAR; ! 2983: temp = 1; ! 2984: for (i = 0; i < (tcount*BITSPERCHAR); i++) ! 2985: temp <<= 1; ! 2986: olditem += item & (temp - 1); ! 2987: } ! 2988: break; ! 2989: case SHORT: ! 2990: item = (long)*(short *)cptr; ! 2991: if (tcount < SHORT) { ! 2992: olditem <<= tcount * BITSPERCHAR; ! 2993: temp = 1; ! 2994: for (i = 0; i < (tcount * BITSPERCHAR); i++) ! 2995: temp <<= 1; ! 2996: olditem += item & (temp - 1); ! 2997: } ! 2998: olditem &= 0177777L; ! 2999: break; ! 3000: case CHAR: ! 3001: item = (long)*cptr; ! 3002: olditem &= 0377; ! 3003: } ! 3004: print(olditem, 8, -8, 0); ! 3005: printf("\t=\t"); ! 3006: print(item, 8, -8, 0); ! 3007: printf("\n"); ! 3008: } else { ! 3009: if (objsz == DIRECTORY) { ! 3010: addr = cur_dir; ! 3011: fprnt('?', 'd'); ! 3012: } else { ! 3013: addr = cur_ino; ! 3014: objsz = INODE; ! 3015: fprnt('?', 'i'); ! 3016: } ! 3017: } ! 3018: if (terror) ! 3019: error++; ! 3020: } ! 3021: ! 3022: /* ! 3023: * fprnt - print data. 'count' elements are printed where '*' will ! 3024: * print an entire blocks worth or up to the eof, whichever ! 3025: * occurs first. An error will occur if crossing a block boundary ! 3026: * is attempted since consecutive blocks don't usually have ! 3027: * meaning. Current print types: ! 3028: * / b - print as bytes (base sensitive) ! 3029: * c - print as characters ! 3030: * o O - print as octal shorts (longs) ! 3031: * d D - print as decimal shorts (longs) ! 3032: * x X - print as hexadecimal shorts (longs) ! 3033: * ? c - print as cylinder groups ! 3034: * d - print as directories ! 3035: * i - print as inodes ! 3036: * s - print as super blocks ! 3037: */ ! 3038: fprnt(style, po) ! 3039: register char style, po; ! 3040: { ! 3041: register int i; ! 3042: register struct fs *sb; ! 3043: register struct cg *cg; ! 3044: register struct direct *dirp; ! 3045: register struct dinode *ip; ! 3046: int tbase; ! 3047: char c, *cptr, *p; ! 3048: long tinode, tcount, temp, taddr; ! 3049: short offset, mode, end = 0, eof = 0, eof_flag; ! 3050: unsigned short *sptr; ! 3051: unsigned long *lptr; ! 3052: ! 3053: laststyle = style; ! 3054: lastpo = po; ! 3055: should_print = 0; ! 3056: if (count != 1) { ! 3057: if (clear) { ! 3058: count = 1; ! 3059: star = 0; ! 3060: clear = 0; ! 3061: } else ! 3062: clear = 1; ! 3063: } ! 3064: tcount = count; ! 3065: offset = blkoff(fs, addr); ! 3066: ! 3067: if (style == '/') { ! 3068: if (type == NUMB) ! 3069: eof_flag = 0; ! 3070: else ! 3071: eof_flag = 1; ! 3072: switch (po) { ! 3073: ! 3074: case 'c': /* print as characters */ ! 3075: case 'b': /* or bytes */ ! 3076: if ((cptr = getblk(addr)) == 0) ! 3077: return; ! 3078: cptr += offset; ! 3079: objsz = CHAR; ! 3080: tcount = check_addr(eof_flag, &end, &eof, 0); ! 3081: if (tcount) { ! 3082: for (i=0; tcount--; i++) { ! 3083: if (i % 16 == 0) { ! 3084: if (i) ! 3085: printf("\n"); ! 3086: index(base); ! 3087: } ! 3088: if (po == 'c') { ! 3089: putf(*cptr++); ! 3090: if ((i + 1) % 16) ! 3091: printf(" "); ! 3092: } else { ! 3093: if ((i + 1) % 16 == 0) ! 3094: print(*cptr++ & 0377, ! 3095: 2,-2,0); ! 3096: else ! 3097: print(*cptr++ & 0377, ! 3098: 4,-2,0); ! 3099: } ! 3100: addr += CHAR; ! 3101: cur_bytes += CHAR; ! 3102: } ! 3103: printf("\n"); ! 3104: } ! 3105: addr -= CHAR; ! 3106: erraddr = addr; ! 3107: cur_bytes -= CHAR; ! 3108: errcur_bytes = cur_bytes; ! 3109: if (eof) { ! 3110: printf("end of file\n"); ! 3111: error++; ! 3112: } else if (end) { ! 3113: if (type == BLOCK) ! 3114: printf("end of block\n"); ! 3115: else ! 3116: printf("end of fragment\n"); ! 3117: error++; ! 3118: } ! 3119: return; ! 3120: ! 3121: case 'o': /* print as octal shorts */ ! 3122: tbase = OCTAL; ! 3123: goto otx; ! 3124: case 'd': /* print as decimal shorts */ ! 3125: tbase = DECIMAL; ! 3126: goto otx; ! 3127: case 'x': /* print as hex shorts */ ! 3128: tbase = HEX; ! 3129: otx: ! 3130: if ((cptr = getblk(addr)) == 0) ! 3131: return; ! 3132: taddr = addr; ! 3133: addr &= ~(SHORT - 1); ! 3134: cur_bytes -= taddr - addr; ! 3135: cptr += blkoff(fs, addr); ! 3136: sptr = (unsigned short *)cptr; ! 3137: objsz = SHORT; ! 3138: tcount = check_addr(eof_flag, &end, &eof, 0); ! 3139: if (tcount) { ! 3140: for (i=0; tcount--; i++) { ! 3141: sptr = (unsigned short *) ! 3142: print_check(sptr, &tcount, tbase, i); ! 3143: switch (po) { ! 3144: case 'o': ! 3145: printf("%06o ",*sptr++); ! 3146: break; ! 3147: case 'd': ! 3148: printf("%05d ",*sptr++); ! 3149: break; ! 3150: case 'x': ! 3151: printf("%04x ",*sptr++); ! 3152: } ! 3153: addr += SHORT; ! 3154: cur_bytes += SHORT; ! 3155: } ! 3156: printf("\n"); ! 3157: } ! 3158: addr -= SHORT; ! 3159: erraddr = addr; ! 3160: cur_bytes -= SHORT; ! 3161: errcur_bytes = cur_bytes; ! 3162: if (eof) { ! 3163: printf("end of file\n"); ! 3164: error++; ! 3165: } else if (end) { ! 3166: if (type == BLOCK) ! 3167: printf("end of block\n"); ! 3168: else ! 3169: printf("end of fragment\n"); ! 3170: error++; ! 3171: } ! 3172: return; ! 3173: ! 3174: case 'O': /* print as octal longs */ ! 3175: tbase = OCTAL; ! 3176: goto OTX; ! 3177: case 'D': /* print as decimal longs */ ! 3178: tbase = DECIMAL; ! 3179: goto OTX; ! 3180: case 'X': /* print as hex longs */ ! 3181: tbase = HEX; ! 3182: OTX: ! 3183: if ((cptr = getblk(addr)) == 0) ! 3184: return; ! 3185: taddr = addr; ! 3186: addr &= ~(LONG - 1); ! 3187: cur_bytes -= taddr - addr; ! 3188: cptr += blkoff(fs, addr); ! 3189: lptr = (unsigned long *)cptr; ! 3190: objsz = LONG; ! 3191: tcount = check_addr(eof_flag, &end, &eof, 0); ! 3192: if (tcount) { ! 3193: for (i=0; tcount--; i++) { ! 3194: lptr = ! 3195: print_check(lptr, &tcount, tbase, i); ! 3196: switch (po) { ! 3197: case 'O': ! 3198: printf("%011o ",*lptr++); ! 3199: break; ! 3200: case 'D': ! 3201: printf("%010u ",*lptr++); ! 3202: break; ! 3203: case 'X': ! 3204: printf("%08x ",*lptr++); ! 3205: } ! 3206: addr += LONG; ! 3207: cur_bytes += LONG; ! 3208: } ! 3209: printf("\n"); ! 3210: } ! 3211: addr -= LONG; ! 3212: erraddr = addr; ! 3213: cur_bytes -= LONG; ! 3214: errcur_bytes = cur_bytes; ! 3215: if (eof) { ! 3216: printf("end of file\n"); ! 3217: error++; ! 3218: } else if (end) { ! 3219: if (type == BLOCK) ! 3220: printf("end of block\n"); ! 3221: else ! 3222: printf("end of fragment\n"); ! 3223: error++; ! 3224: } ! 3225: return; ! 3226: ! 3227: default: ! 3228: error++; ! 3229: printf("no such print option\n"); ! 3230: return; ! 3231: } ! 3232: } else ! 3233: switch (po) { ! 3234: ! 3235: case 'c': /* print as cylinder group */ ! 3236: if (type != NUMB) ! 3237: if (cur_cgrp + count > fs->fs_ncg) { ! 3238: tcount = fs->fs_ncg - cur_cgrp; ! 3239: if (!star) ! 3240: end++; ! 3241: } ! 3242: addr &= ~(LONG - 1); ! 3243: for (; tcount--;) { ! 3244: erraddr = addr; ! 3245: errcur_bytes = cur_bytes; ! 3246: if (type != NUMB) { ! 3247: addr = cgtod(fs, cur_cgrp) ! 3248: << FRGSHIFT; ! 3249: cur_cgrp++; ! 3250: } ! 3251: if ((cptr = getblk(addr)) == 0) { ! 3252: if (cur_cgrp) ! 3253: cur_cgrp--; ! 3254: return; ! 3255: } ! 3256: cptr += blkoff(fs, addr); ! 3257: cg = (struct cg *)cptr; ! 3258: if (type == NUMB) { ! 3259: cur_cgrp = cg->cg_cgx + 1; ! 3260: type = objsz = CGRP; ! 3261: if (cur_cgrp + count - 1 > fs->fs_ncg) { ! 3262: tcount = fs->fs_ncg - cur_cgrp; ! 3263: if (!star) ! 3264: end++; ! 3265: } ! 3266: } ! 3267: if (!override && !cg_chkmagic(cg)) { ! 3268: printf("invalid cylinder group "); ! 3269: printf("magic word\n"); ! 3270: if (cur_cgrp) ! 3271: cur_cgrp--; ! 3272: error++; ! 3273: return; ! 3274: } ! 3275: printcg(cg); ! 3276: if (tcount) ! 3277: printf("\n"); ! 3278: } ! 3279: cur_cgrp--; ! 3280: if (end) { ! 3281: printf("end of cylinder groups\n"); ! 3282: error++; ! 3283: } ! 3284: return; ! 3285: ! 3286: case 'd': /* print as directories */ ! 3287: if ((cptr = getblk(addr)) == 0) ! 3288: return; ! 3289: if (type == NUMB) { ! 3290: if (fragoff(fs, addr)) { ! 3291: printf("address must be at the "); ! 3292: printf("beginning of a fragment\n"); ! 3293: error++; ! 3294: return; ! 3295: } ! 3296: bod_addr = addr; ! 3297: type = FRAGMENT; ! 3298: dirslot = 0; ! 3299: cur_bytes = 0; ! 3300: blocksize = FRGSIZE; ! 3301: filesize = FRGSIZE * 2; ! 3302: } ! 3303: cptr += offset; ! 3304: objsz = DIRECTORY; ! 3305: while (tcount-- && cur_bytes < filesize && ! 3306: cur_bytes < blocksize && !bcomp(addr)) { ! 3307: dirp = (struct direct *)cptr; ! 3308: tinode = dirp->d_ino; ! 3309: printf("i#: "); ! 3310: if (tinode == 0) ! 3311: printf("free\t"); ! 3312: else ! 3313: print(tinode, 12, -8, 0); ! 3314: printf("%s\n",&dirp->d_name[0]); ! 3315: erraddr = addr; ! 3316: errcur_bytes = cur_bytes; ! 3317: addr += dirp->d_reclen; ! 3318: cptr += dirp->d_reclen; ! 3319: cur_bytes += dirp->d_reclen; ! 3320: dirslot++; ! 3321: } ! 3322: addr = erraddr; ! 3323: cur_dir = addr; ! 3324: cur_bytes = errcur_bytes; ! 3325: stringsize = STRINGSIZE(dirp); ! 3326: dirslot--; ! 3327: if (tcount >= 0 && !star) { ! 3328: switch (type) { ! 3329: case FRAGMENT: ! 3330: printf("end of fragment\n"); ! 3331: break; ! 3332: case BLOCK: ! 3333: printf("end of block\n"); ! 3334: break; ! 3335: default: ! 3336: printf("end of directory\n"); ! 3337: } ! 3338: error++; ! 3339: } else ! 3340: error = 0; ! 3341: return; ! 3342: ! 3343: case 'i': /* print as inodes */ ! 3344: if ((ip = (struct dinode *)getblk(addr)) == 0) ! 3345: return; ! 3346: for (i=1; i < fs->fs_ncg; i++) ! 3347: if (addr < (cgimin(fs,i) << FRGSHIFT)) ! 3348: break; ! 3349: i--; ! 3350: offset /= INODE; ! 3351: temp = (addr - (cgimin(fs,i) << FRGSHIFT)) >> FRGSHIFT; ! 3352: temp = (i * fs->fs_ipg) + fragstoblks(fs,temp) * ! 3353: INOPB(fs) + offset; ! 3354: if (count + offset > INOPB(fs)) { ! 3355: tcount = INOPB(fs) - offset; ! 3356: if (!star) ! 3357: end++; ! 3358: } ! 3359: objsz = INODE; ! 3360: ip += offset; ! 3361: for (i=0; tcount--; ip++, temp++) { ! 3362: if ((mode = icheck(addr)) == 0) ! 3363: if (!override) ! 3364: continue; ! 3365: p = " ugtrwxrwxrwx"; ! 3366: ! 3367: switch (mode & IFMT) { ! 3368: case IFDIR: ! 3369: c = 'd'; ! 3370: break; ! 3371: case IFCHR: ! 3372: c = 'c'; ! 3373: break; ! 3374: case IFBLK: ! 3375: c = 'b'; ! 3376: break; ! 3377: case IFREG: ! 3378: c = '-'; ! 3379: break; ! 3380: case IFLNK: ! 3381: c = 'l'; ! 3382: break; ! 3383: case IFSOCK: ! 3384: c = 's'; ! 3385: break; ! 3386: default: ! 3387: c = '?'; ! 3388: if (!override) ! 3389: goto empty; ! 3390: ! 3391: } ! 3392: printf("i#: "); ! 3393: print(temp,12,-8,0); ! 3394: printf(" md: "); ! 3395: printf("%c", c); ! 3396: for (mode = mode << 4; *++p; mode = mode << 1) { ! 3397: if (mode & IFREG) ! 3398: printf("%c", *p); ! 3399: else ! 3400: printf("-"); ! 3401: } ! 3402: printf(" uid: "); ! 3403: print(ip->di_uid,8,-4,0); ! 3404: printf(" gid: "); ! 3405: print(ip->di_gid,8,-4,0); ! 3406: printf("\n"); ! 3407: printf("ln: "); ! 3408: print(ip->di_nlink,8,-4,0); ! 3409: printf(" bs: "); ! 3410: print(ip->di_blocks,12,-8,0); ! 3411: printf(" sz : "); ! 3412: print(ip->di_size,12,-8,0); ! 3413: printf("\n"); ! 3414: if (ip->di_mode & IFCHR) { ! 3415: printf("maj: "); ! 3416: print(ip->di_db[1] & 0377,4,-2,0); ! 3417: printf(" min: "); ! 3418: print(ip->di_db[0] & 0377,4,-2,0); ! 3419: printf("\n"); ! 3420: } else { ! 3421: for (i = 0; i < NDADDR; ) { ! 3422: if (ip->di_db[i] == 0) ! 3423: break; ! 3424: printf("db#%x: ",i); ! 3425: print(ip->di_db[i],11,-8,0); ! 3426: if (++i % 4 == 0) ! 3427: printf("\n"); ! 3428: else ! 3429: printf(" "); ! 3430: } ! 3431: if (i % 4) ! 3432: printf("\n"); ! 3433: for (i = 0; i < NIADDR; i++) { ! 3434: if (ip->di_ib[i] == 0) ! 3435: break; ! 3436: printf("ib#%x: ",i); ! 3437: print(ip->di_ib[i],11,-8,0); ! 3438: printf(" "); ! 3439: } ! 3440: if (i) ! 3441: printf("\n"); ! 3442: } ! 3443: if (count == 1) { ! 3444: printf("\taccessed: %s", ! 3445: ctime(&ip->di_atime)); ! 3446: printf("\tmodified: %s", ! 3447: ctime(&ip->di_mtime)); ! 3448: printf("\tcreated : %s", ! 3449: ctime(&ip->di_ctime)); ! 3450: } ! 3451: if (tcount) ! 3452: printf("\n"); ! 3453: empty: ! 3454: if (c == '?' && !override) { ! 3455: printf("i#: "); ! 3456: print(temp, 12, -8, 0); ! 3457: printf(" is unallocated\n"); ! 3458: if (count != 1) ! 3459: printf("\n"); ! 3460: } ! 3461: cur_ino = erraddr = addr; ! 3462: errcur_bytes = cur_bytes; ! 3463: cur_inum++; ! 3464: addr = addr + INODE; ! 3465: } ! 3466: addr = erraddr; ! 3467: cur_bytes = errcur_bytes; ! 3468: cur_inum--; ! 3469: if (end) { ! 3470: printf("end of block\n"); ! 3471: error++; ! 3472: } ! 3473: return; ! 3474: ! 3475: case 's': /* print as super block */ ! 3476: if (cur_cgrp == -1) { ! 3477: addr = SBLOCK * DEV_BSIZE; ! 3478: type = NUMB; ! 3479: } ! 3480: addr &= ~(LONG - 1); ! 3481: if (type != NUMB) ! 3482: if (cur_cgrp + count > fs->fs_ncg) { ! 3483: tcount = fs->fs_ncg - cur_cgrp; ! 3484: if (!star) ! 3485: end++; ! 3486: } ! 3487: for (; tcount--;) { ! 3488: erraddr = addr; ! 3489: cur_bytes = errcur_bytes; ! 3490: if (type != NUMB) { ! 3491: addr = cgsblock(fs, cur_cgrp) ! 3492: << FRGSHIFT; ! 3493: cur_cgrp++; ! 3494: } ! 3495: if ((cptr = getblk(addr)) == 0) { ! 3496: if (cur_cgrp) ! 3497: cur_cgrp--; ! 3498: return; ! 3499: } ! 3500: cptr += blkoff(fs, addr); ! 3501: sb = (struct fs *)cptr; ! 3502: if (type == NUMB) { ! 3503: for (i = 0; i < fs->fs_ncg; i++) ! 3504: if (addr == cgsblock(fs, i) << ! 3505: FRGSHIFT) ! 3506: break; ! 3507: if (i == fs->fs_ncg) ! 3508: cur_cgrp = 0; ! 3509: else ! 3510: cur_cgrp = i + 1; ! 3511: type = objsz = SB; ! 3512: if (cur_cgrp + count - 1 > fs->fs_ncg) { ! 3513: tcount = fs->fs_ncg - cur_cgrp; ! 3514: if (!star) ! 3515: end++; ! 3516: } ! 3517: } ! 3518: if (sb->fs_magic != FS_MAGIC) { ! 3519: cur_cgrp = 0; ! 3520: if (!override) { ! 3521: printf("invalid super block "); ! 3522: printf("magic word\n"); ! 3523: cur_cgrp--; ! 3524: error++; ! 3525: return; ! 3526: } ! 3527: } ! 3528: if (cur_cgrp == 0) ! 3529: printf("\tsuper block:\n"); ! 3530: else { ! 3531: printf("\tsuper block in cylinder "); ! 3532: printf("group "); ! 3533: print(cur_cgrp - 1, 0, 0, 0); ! 3534: printf(":\n"); ! 3535: } ! 3536: printsb(sb); ! 3537: if (tcount) ! 3538: printf("\n"); ! 3539: } ! 3540: cur_cgrp--; ! 3541: if (end) { ! 3542: printf("end of super blocks\n"); ! 3543: error++; ! 3544: } ! 3545: return; ! 3546: default: ! 3547: error++; ! 3548: printf("no such print option\n"); ! 3549: return; ! 3550: } ! 3551: } ! 3552: ! 3553: /* ! 3554: * valid_addr - call check_addr to validate the current address. ! 3555: */ ! 3556: valid_addr() ! 3557: { ! 3558: short eof_flag, end = 0, eof = 0; ! 3559: long tcount = count; ! 3560: ! 3561: if (!trapped) ! 3562: return(1); ! 3563: if (cur_bytes < 0) { ! 3564: cur_bytes = 0; ! 3565: if (blocksize > filesize) { ! 3566: printf("beginning of file\n"); ! 3567: } else { ! 3568: if (type == BLOCK) ! 3569: printf("beginning of block\n"); ! 3570: else ! 3571: printf("beginning of fragment\n"); ! 3572: } ! 3573: error++; ! 3574: return(0); ! 3575: } ! 3576: count = 1; ! 3577: check_addr(1, &end, &eof, (filesize < blocksize)); ! 3578: count = tcount; ! 3579: if (eof) { ! 3580: printf("end of file\n"); ! 3581: error++; ! 3582: return(0); ! 3583: } ! 3584: if (end == 2) { ! 3585: if (erraddr > addr) { ! 3586: if (type == BLOCK) ! 3587: printf("beginning of block\n"); ! 3588: else ! 3589: printf("beginning of fragment\n"); ! 3590: error++; ! 3591: return(0); ! 3592: } ! 3593: } ! 3594: if (end) { ! 3595: if (type == BLOCK) ! 3596: printf("end of block\n"); ! 3597: else ! 3598: printf("end of fragment\n"); ! 3599: error++; ! 3600: return(0); ! 3601: } ! 3602: return(1); ! 3603: } ! 3604: ! 3605: /* ! 3606: * check_addr - check if the address crosses the end of block or ! 3607: * end of file. Return the proper count. ! 3608: */ ! 3609: check_addr(eof_flag, end, eof, keep_on) ! 3610: short eof_flag, *end, *eof, keep_on; ! 3611: { ! 3612: long temp, tcount = count, taddr = addr, tcur_bytes = cur_bytes; ! 3613: ! 3614: if (bcomp(addr + count * objsz - 1) || ! 3615: (keep_on && taddr < (bmap(cur_block) << FRGSHIFT))) { ! 3616: error = 0; ! 3617: addr = taddr; ! 3618: cur_bytes = tcur_bytes; ! 3619: if (keep_on) { ! 3620: if (addr < erraddr) { ! 3621: if (cur_bytes < 0) { ! 3622: (*end) = 2; ! 3623: return; ! 3624: } ! 3625: temp = cur_block - lblkno(fs, cur_bytes); ! 3626: cur_block -= temp; ! 3627: if ((addr = bmap(cur_block) << FRGSHIFT) == 0) { ! 3628: cur_block += temp; ! 3629: return; ! 3630: } ! 3631: temp = tcur_bytes - cur_bytes; ! 3632: addr += temp; ! 3633: cur_bytes += temp; ! 3634: return; ! 3635: } else { ! 3636: if (cur_bytes >= filesize) { ! 3637: (*eof)++; ! 3638: return; ! 3639: } ! 3640: temp = lblkno(fs, cur_bytes) - cur_block; ! 3641: cur_block += temp; ! 3642: if ((addr = bmap(cur_block) << FRGSHIFT) == 0) { ! 3643: cur_block -= temp; ! 3644: return; ! 3645: } ! 3646: temp = tcur_bytes - cur_bytes; ! 3647: addr += temp; ! 3648: cur_bytes += temp; ! 3649: return; ! 3650: } ! 3651: } ! 3652: tcount = (blkroundup(fs, addr+1)-addr) / objsz; ! 3653: if (!star) ! 3654: (*end) = 2; ! 3655: } ! 3656: addr = taddr; ! 3657: cur_bytes = tcur_bytes; ! 3658: if (eof_flag) { ! 3659: if (blocksize > filesize) { ! 3660: if (cur_bytes >= filesize) { ! 3661: tcount = 0; ! 3662: (*eof)++; ! 3663: } else if (tcount > (filesize - cur_bytes) / objsz) { ! 3664: tcount = (filesize - cur_bytes) / objsz; ! 3665: if (!star || tcount == 0) ! 3666: (*eof)++; ! 3667: } ! 3668: } else { ! 3669: if (cur_bytes >= blocksize) { ! 3670: tcount = 0; ! 3671: (*end)++; ! 3672: } else if (tcount > (blocksize - cur_bytes) / objsz) { ! 3673: tcount = (blocksize - cur_bytes) / objsz; ! 3674: if (!star || tcount == 0) ! 3675: (*end)++; ! 3676: } ! 3677: } ! 3678: } ! 3679: return(tcount); ! 3680: } ! 3681: ! 3682: /* ! 3683: * print_check - check if the index needs to be printed and delete ! 3684: * rows of zeros from the output. ! 3685: */ ! 3686: unsigned long * ! 3687: print_check(lptr, tcount, tbase, i) ! 3688: unsigned long *lptr; ! 3689: long *tcount; ! 3690: short tbase; ! 3691: register int i; ! 3692: { ! 3693: register int j, k, temp = BYTESPERLINE / objsz; ! 3694: short first_time = 0; ! 3695: unsigned long *tlptr; ! 3696: unsigned short *tsptr, *sptr; ! 3697: ! 3698: sptr = (unsigned short *)lptr; ! 3699: if (i == 0) ! 3700: first_time = 1; ! 3701: if (i % temp == 0) { ! 3702: if (*tcount >= temp - 1) { ! 3703: if (objsz == SHORT) ! 3704: tsptr = sptr; ! 3705: else ! 3706: tlptr = lptr; ! 3707: k = *tcount - 1; ! 3708: for (j = i; k--; j++) ! 3709: if (objsz == SHORT) { ! 3710: if (*tsptr++ != 0) ! 3711: break; ! 3712: } else { ! 3713: if (*tlptr++ != 0) ! 3714: break; ! 3715: } ! 3716: if (j > (i + temp - 1)) { ! 3717: j = (j - i) / temp; ! 3718: while (j-- > 0) { ! 3719: if (objsz == SHORT) ! 3720: sptr += temp; ! 3721: else ! 3722: lptr += temp; ! 3723: *tcount -= temp; ! 3724: i += temp; ! 3725: addr += BYTESPERLINE; ! 3726: cur_bytes += BYTESPERLINE; ! 3727: } ! 3728: if (first_time) ! 3729: printf("*"); ! 3730: else ! 3731: printf("\n*"); ! 3732: } ! 3733: if (i) ! 3734: printf("\n"); ! 3735: index(tbase); ! 3736: } else { ! 3737: if (i) ! 3738: printf("\n"); ! 3739: index(tbase); ! 3740: } ! 3741: } ! 3742: if(objsz == SHORT) ! 3743: return((unsigned long *)sptr); ! 3744: else ! 3745: return(lptr); ! 3746: } ! 3747: ! 3748: /* ! 3749: * index - print a byte index for the printout in base b ! 3750: * with leading zeros. ! 3751: */ ! 3752: index(b) ! 3753: int b; ! 3754: { ! 3755: int tbase = base; ! 3756: ! 3757: base = b; ! 3758: print(addr, 8, 8, 1); ! 3759: printf(":\t"); ! 3760: base = tbase; ! 3761: } ! 3762: ! 3763: /* ! 3764: * print - print out the value to digits places with/without ! 3765: * leading zeros and right/left justified in the current base. ! 3766: */ ! 3767: print(value, fieldsz, digits, lead) ! 3768: int value, fieldsz, digits, lead; ! 3769: { ! 3770: register int i, left = 0; ! 3771: char mode = BASE[base - OCTAL]; ! 3772: char *string = &scratch[0]; ! 3773: ! 3774: if (digits < 0) { ! 3775: left = 1; ! 3776: digits *= -1; ! 3777: } ! 3778: if (base != HEX) ! 3779: if (digits) ! 3780: digits = digits + (digits - 1)/((base >> 1) - 1) + 1; ! 3781: else ! 3782: digits = 1; ! 3783: if (lead) { ! 3784: if (left) ! 3785: sprintf(string, "%%%c%d%d.%d%c", ! 3786: '-', 0, digits, lead, mode); ! 3787: else ! 3788: sprintf(string, "%%%d%d.%d%c", 0, digits, lead, mode); ! 3789: } else { ! 3790: if (left) ! 3791: sprintf(string, "%%%c%d%c", '-', digits, mode); ! 3792: else ! 3793: sprintf(string, "%%%d%c", digits, mode); ! 3794: } ! 3795: printf(string, value); ! 3796: for (i = 0; i < fieldsz - digits; i++) ! 3797: printf(" "); ! 3798: } ! 3799: ! 3800: /* ! 3801: * Print out the contents of a superblock. ! 3802: */ ! 3803: printsb(fs) ! 3804: struct fs *fs; ! 3805: { ! 3806: int c, i, j, k, size; ! 3807: ! 3808: #ifdef FS_42POSTBLFMT ! 3809: if (fs->fs_postblformat == FS_42POSTBLFMT) ! 3810: fs->fs_nrpos = 8; ! 3811: printf("magic\t%x\tformat\t%s\ttime\t%s", fs->fs_magic, ! 3812: fs->fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic", ! 3813: ctime(&fs->fs_time)); ! 3814: #else ! 3815: printf("magic\t%x\ttime\t%s", ! 3816: fs->fs_magic, ctime(&fs->fs_time)); ! 3817: #endif ! 3818: printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", ! 3819: fs->fs_cstotal.cs_nbfree, fs->fs_cstotal.cs_ndir, ! 3820: fs->fs_cstotal.cs_nifree, fs->fs_cstotal.cs_nffree); ! 3821: printf("ncg\t%d\tncyl\t%d\tsize\t%d\tblocks\t%d\n", ! 3822: fs->fs_ncg, fs->fs_ncyl, fs->fs_size, fs->fs_dsize); ! 3823: printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n", ! 3824: fs->fs_bsize, fs->fs_bshift, fs->fs_bmask); ! 3825: printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n", ! 3826: fs->fs_fsize, fs->fs_fshift, fs->fs_fmask); ! 3827: printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n", ! 3828: fs->fs_frag, fs->fs_fragshift, fs->fs_fsbtodb); ! 3829: printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n", ! 3830: fs->fs_cpg, fs->fs_fpg / fs->fs_frag, fs->fs_fpg, fs->fs_ipg); ! 3831: printf("minfree\t%d%%\toptim\t%s\tmaxcontig %d\tmaxbpg\t%d\n", ! 3832: fs->fs_minfree, fs->fs_optim == FS_OPTSPACE ? "space" : "time", ! 3833: fs->fs_maxcontig, fs->fs_maxbpg); ! 3834: #ifdef FS_42POSTBLFMT ! 3835: printf("rotdelay %dms\theadswitch %dus\ttrackseek %dus\trps\t%d\n", ! 3836: fs->fs_rotdelay, fs->fs_headswitch, fs->fs_trkseek, fs->fs_rps); ! 3837: printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n", ! 3838: fs->fs_ntrak, fs->fs_nsect, fs->fs_npsect, fs->fs_spc); ! 3839: printf("trackskew %d\tinterleave %d\n", ! 3840: fs->fs_trackskew, fs->fs_interleave); ! 3841: #else ! 3842: printf("rotdelay %dms\trps\t%d\n", ! 3843: fs->fs_rotdelay, fs->fs_rps); ! 3844: printf("ntrak\t%d\tnsect\t%d\tspc\t%d\n", ! 3845: fs->fs_ntrak, fs->fs_nsect, fs->fs_spc); ! 3846: #endif ! 3847: printf("nindir\t%d\tinopb\t%d\tnspf\t%d\n", ! 3848: fs->fs_nindir, fs->fs_inopb, fs->fs_nspf); ! 3849: printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n", ! 3850: fs->fs_sblkno, fs->fs_cblkno, fs->fs_iblkno, fs->fs_dblkno); ! 3851: printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n", ! 3852: fs->fs_sbsize, fs->fs_cgsize, fs->fs_cgoffset, fs->fs_cgmask); ! 3853: printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n", ! 3854: fs->fs_csaddr, fs->fs_cssize, fs->fs_csshift, fs->fs_csmask); ! 3855: printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\n", ! 3856: fs->fs_cgrotor, fs->fs_fmod, fs->fs_ronly); ! 3857: #ifdef FS_42POSTBLFMT ! 3858: if (fs->fs_cpc != 0) ! 3859: printf("blocks available in each of %d rotational positions", ! 3860: fs->fs_nrpos); ! 3861: else ! 3862: printf("insufficient space to maintain rotational tables\n"); ! 3863: #endif ! 3864: for (c = 0; c < fs->fs_cpc; c++) { ! 3865: printf("\ncylinder number %d:", c); ! 3866: #ifdef FS_42POSTBLFMT ! 3867: for (i = 0; i < fs->fs_nrpos; i++) { ! 3868: if (fs_postbl(fs, c)[i] == -1) ! 3869: continue; ! 3870: printf("\n position %d:\t", i); ! 3871: for (j = fs_postbl(fs, c)[i], k = 1; ; ! 3872: j += fs_rotbl(fs)[j], k++) { ! 3873: printf("%5d", j); ! 3874: if (k % 12 == 0) ! 3875: printf("\n\t\t"); ! 3876: if (fs_rotbl(fs)[j] == 0) ! 3877: break; ! 3878: } ! 3879: } ! 3880: #else ! 3881: for (i = 0; i < NRPOS; i++) { ! 3882: if (fs->fs_postbl[c][i] == -1) ! 3883: continue; ! 3884: printf("\n position %d:\t", i); ! 3885: for (j = fs->fs_postbl[c][i], k = 1; ; ! 3886: j += fs->fs_rotbl[j], k++) { ! 3887: printf("%5d", j); ! 3888: if (k % 12 == 0) ! 3889: printf("\n\t\t"); ! 3890: if (fs->fs_rotbl[j] == 0) ! 3891: break; ! 3892: } ! 3893: } ! 3894: #endif ! 3895: } ! 3896: printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t"); ! 3897: for (i = 0, j = 0; i < fs->fs_cssize; i += fs->fs_bsize, j++) { ! 3898: size = fs->fs_cssize - i < fs->fs_bsize ? ! 3899: fs->fs_cssize - i : fs->fs_bsize; ! 3900: fs->fs_csp[j] = (struct csum *)calloc(1, size); ! 3901: lseek(fd, fsbtodb(fs, (fs->fs_csaddr + j * fs->fs_frag)) * ! 3902: fs->fs_fsize / fsbtodb(fs, 1), 0); ! 3903: if (read(fd, fs->fs_csp[j], size) != size) { ! 3904: for (j--; j >= 0; j--) ! 3905: free(fs->fs_csp[j]); ! 3906: return; ! 3907: } ! 3908: } ! 3909: for (i = 0; i < fs->fs_ncg; i++) { ! 3910: struct csum *cs = &fs->fs_cs(fs, i); ! 3911: if (i && i % 4 == 0) ! 3912: printf("\n\t"); ! 3913: printf("(%d,%d,%d,%d) ", ! 3914: cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree); ! 3915: } ! 3916: for (j--; j >= 0; j--) ! 3917: free(fs->fs_csp[j]); ! 3918: printf("\n"); ! 3919: if (fs->fs_ncyl % fs->fs_cpg) { ! 3920: printf("cylinders in last group %d\n", ! 3921: i = fs->fs_ncyl % fs->fs_cpg); ! 3922: printf("blocks in last group %d\n", ! 3923: i * fs->fs_spc / NSPB(fs)); ! 3924: } ! 3925: } ! 3926: ! 3927: /* ! 3928: * Print out the contents of a cylinder group. ! 3929: */ ! 3930: printcg(cg) ! 3931: struct cg *cg; ! 3932: { ! 3933: int i,j; ! 3934: ! 3935: printf("\ncg %d:\n", cg->cg_cgx); ! 3936: #ifdef FS_42POSTBLFMT ! 3937: printf("magic\t%x\ttell\t%x\ttime\t%s", ! 3938: fs->fs_postblformat == FS_42POSTBLFMT ? ! 3939: ((struct ocg *)cg)->cg_magic : cg->cg_magic, ! 3940: fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1), ! 3941: ctime(&cg->cg_time)); ! 3942: #else ! 3943: printf("magic\t%x\ttell\t%x\ttime\t%s", ! 3944: cg->cg_magic, ! 3945: fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1), ! 3946: ctime(&cg->cg_time)); ! 3947: #endif ! 3948: printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n", ! 3949: cg->cg_cgx, cg->cg_ncyl, cg->cg_niblk, cg->cg_ndblk); ! 3950: printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n", ! 3951: cg->cg_cs.cs_nbfree, cg->cg_cs.cs_ndir, ! 3952: cg->cg_cs.cs_nifree, cg->cg_cs.cs_nffree); ! 3953: printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum", ! 3954: cg->cg_rotor, cg->cg_irotor, cg->cg_frotor); ! 3955: for (i = 1, j = 0; i < fs->fs_frag; i++) { ! 3956: printf("\t%d", cg->cg_frsum[i]); ! 3957: j += i * cg->cg_frsum[i]; ! 3958: } ! 3959: printf("\nsum of frsum: %d\niused:\t", j); ! 3960: pbits(cg_inosused(cg), fs->fs_ipg); ! 3961: printf("free:\t"); ! 3962: pbits(cg_blksfree(cg), fs->fs_fpg); ! 3963: printf("b:\n"); ! 3964: for (i = 0; i < fs->fs_cpg; i++) { ! 3965: if (cg_blktot(cg)[i] == 0) ! 3966: continue; ! 3967: printf(" c%d:\t(%d)\t", i, cg_blktot(cg)[i]); ! 3968: #ifdef FS_42POSTBLFMT ! 3969: for (j = 0; j < fs->fs_nrpos; j++) { ! 3970: if (fs->fs_cpc == 0 || ! 3971: fs_postbl(fs, i % fs->fs_cpc)[j] == -1) ! 3972: continue; ! 3973: printf(" %d", cg_blks(fs, cg, i)[j]); ! 3974: } ! 3975: #else ! 3976: for (j = 0; j < NRPOS; j++) { ! 3977: if (fs->fs_cpc == 0 || ! 3978: fs->fs_postbl[i % fs->fs_cpc][j] == -1) ! 3979: continue; ! 3980: printf(" %d", cg->cg_b[i][j]); ! 3981: } ! 3982: #endif ! 3983: printf("\n"); ! 3984: } ! 3985: } ! 3986: ! 3987: /* ! 3988: * Print out the contents of a bit array. ! 3989: */ ! 3990: pbits(cp, max) ! 3991: register char *cp; ! 3992: int max; ! 3993: { ! 3994: register int i; ! 3995: int count = 0, j; ! 3996: ! 3997: for (i = 0; i < max; i++) ! 3998: if (isset(cp, i)) { ! 3999: if (count) ! 4000: printf(",%s", count % 6 ? " " : "\n\t"); ! 4001: count++; ! 4002: printf("%d", i); ! 4003: j = i; ! 4004: while ((i+1)<max && isset(cp, i+1)) ! 4005: i++; ! 4006: if (i != j) ! 4007: printf("-%d", i); ! 4008: } ! 4009: printf("\n"); ! 4010: } ! 4011: ! 4012: /* ! 4013: * bcomp - used to check for block over/under flows when stepping through ! 4014: * a file system. ! 4015: */ ! 4016: bcomp(addr) ! 4017: long addr; ! 4018: { ! 4019: if (override) ! 4020: return(0); ! 4021: if (lblkno(fs, addr) == (bhdr.fwd)->blkno) ! 4022: return(0); ! 4023: error++; ! 4024: return(1); ! 4025: } ! 4026: ! 4027: /* ! 4028: * bmap - maps the logical block number of a file into ! 4029: * the corresponding physical block on the file ! 4030: * system. ! 4031: */ ! 4032: long ! 4033: bmap(bn) ! 4034: long bn; ! 4035: { ! 4036: register int i, j; ! 4037: register struct dinode *ip; ! 4038: int sh; ! 4039: long nb; ! 4040: ! 4041: ip = (struct dinode *)cur_ino; ! 4042: if (bn < NDADDR) { ! 4043: addr = (long)&ip->di_db[bn]; ! 4044: cur_bytes = bn * BLKSIZE; ! 4045: return(nullblk(nb=get(LONG)) ? 0L : nb); ! 4046: } ! 4047: ! 4048: sh = 1; ! 4049: bn -= NDADDR; ! 4050: for (j = NIADDR; j > 0; j--) { ! 4051: sh *= NINDIR(fs); ! 4052: if (bn < sh) ! 4053: break; ! 4054: bn -= sh; ! 4055: } ! 4056: if (j == 0) { ! 4057: printf("file too big\n"); ! 4058: error++; ! 4059: return(0L); ! 4060: } ! 4061: addr = (long)&ip->di_ib[NIADDR - j]; ! 4062: nb = get(LONG); ! 4063: if (nb == 0) ! 4064: return(0L); ! 4065: for (; j <= NIADDR; j++) { ! 4066: sh /= NINDIR(fs); ! 4067: addr = (nb << FRGSHIFT) + ((bn / sh) % NINDIR(fs)) * LONG; ! 4068: if (nullblk(nb = get(LONG))) ! 4069: return(0L); ! 4070: } ! 4071: return(nb); ! 4072: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.