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