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