134187Smckusick /*
261494Sbostic * Copyright (c) 1988, 1993
361494Sbostic * The Regents of the University of California. All rights reserved.
434187Smckusick *
534187Smckusick * This code is derived from software contributed to Berkeley by
634187Smckusick * Computer Consoles Inc.
734187Smckusick *
866689Sbostic * %sccs.include.proprietary.c%
934187Smckusick */
1034187Smckusick
1134187Smckusick #ifndef lint
1261494Sbostic static char copyright[] =
1361494Sbostic "@(#) Copyright (c) 1988, 1993\n\
1461494Sbostic The Regents of the University of California. All rights reserved.\n";
1534187Smckusick #endif /* not lint */
1634187Smckusick
1734187Smckusick #ifndef lint
18*69260Smckusick static char sccsid[] = "@(#)fsdb.c 8.5 (Berkeley) 05/04/95";
1934187Smckusick #endif /* not lint */
2034187Smckusick
2134197Smckusick /*
2234197Smckusick * fsdb - file system debugger
2334197Smckusick *
2434197Smckusick * usage: fsdb [options] special
2534187Smckusick * options:
2634187Smckusick * -? display usage
2734187Smckusick * -o override some error conditions
2834187Smckusick * -p"string" set prompt to string
2934187Smckusick * -w open for write
3034187Smckusick */
3134187Smckusick
3234187Smckusick #include <sys/param.h>
3336249Smckusick #include <sys/file.h>
3438508Sbostic #include <sys/dir.h>
3553732Smckusick #include <sys/time.h>
3651620Sbostic #include <ufs/ufs/dinode.h>
3751620Sbostic #include <ufs/ffs/fs.h>
3837271Sbostic #include <stdio.h>
3957998Sralph #include <unistd.h>
4057998Sralph #include <stdlib.h>
4137271Sbostic #include <setjmp.h>
4237271Sbostic #include <paths.h>
4336249Smckusick
4434187Smckusick /*
4536249Smckusick * Defines from the 4.3-tahoe file system, for systems with the 4.2 or 4.3
4636249Smckusick * file system.
4736249Smckusick */
4836249Smckusick #ifndef FS_42POSTBLFMT
4936249Smckusick #define cg_blktot(cgp) (((cgp))->cg_btot)
5036249Smckusick #define cg_blks(fs, cgp, cylno) (((cgp))->cg_b[cylno])
5136249Smckusick #define cg_inosused(cgp) (((cgp))->cg_iused)
5236249Smckusick #define cg_blksfree(cgp) (((cgp))->cg_free)
5336249Smckusick #define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
5436249Smckusick #endif
5536249Smckusick
5636249Smckusick /*
5734187Smckusick * Never changing defines.
5834187Smckusick */
5934187Smckusick #define OCTAL 8 /* octal base */
6034187Smckusick #define DECIMAL 10 /* decimal base */
6134187Smckusick #define HEX 16 /* hexadecimal base */
6234187Smckusick
6334187Smckusick /*
6434187Smckusick * Adjustable defines.
6534187Smckusick */
6634187Smckusick #define NBUF 10 /* number of cache buffers */
6734187Smckusick #define PROMPTSIZE 80 /* size of user definable prompt */
6834187Smckusick #define MAXFILES 40000 /* max number of files ls can handle */
6934187Smckusick #define FIRST_DEPTH 10 /* default depth for find and ls */
7034187Smckusick #define SECOND_DEPTH 100 /* second try at depth (maximum) */
7134187Smckusick #define INPUTBUFFER 1040 /* size of input buffer */
7234187Smckusick #define BYTESPERLINE 16 /* bytes per line of /dxo output */
7334187Smckusick #define NREG 36 /* number of save registers */
7434187Smckusick
7534187Smckusick /*
7634187Smckusick * Values dependent on sizes of structs and such.
7734187Smckusick */
7834187Smckusick #define NUMB 3 /* these three are arbitrary, */
7934187Smckusick #define BLOCK 5 /* but must be different from */
8034187Smckusick #define FRAGMENT 7 /* the rest (hence odd). */
8134187Smckusick #define BITSPERCHAR 8 /* couldn't find it anywhere */
8234187Smckusick #define CHAR (sizeof (char))
8334187Smckusick #define SHORT (sizeof (short))
8434187Smckusick #define LONG (sizeof (long))
8534187Smckusick #define INODE (sizeof (struct dinode))
8634187Smckusick #define DIRECTORY (sizeof (struct direct))
8734187Smckusick #define CGRP (sizeof (struct cg))
8834187Smckusick #define SB (sizeof (struct fs))
8934187Smckusick #define BLKSIZE (fs->fs_bsize) /* for clarity */
9034187Smckusick #define FRGSIZE (fs->fs_fsize)
9134187Smckusick #define BLKSHIFT (fs->fs_bshift)
9234187Smckusick #define FRGSHIFT (fs->fs_fshift)
9334187Smckusick
9434187Smckusick /*
9534187Smckusick * Messy macros that would otherwise clutter up such glamorous code.
9634187Smckusick */
9764639Sbostic #define itob(i) ((ino_to_fsba(fs, \
9864639Sbostic (i)) << FRGSHIFT) + ino_to_fsbo(fs, (i)) * INODE)
9934187Smckusick #define min(x, y) ((x) < (y) ? (x) : (y))
10034187Smckusick #define STRINGSIZE(d) ((long)d->d_reclen - \
10134187Smckusick ((long)&d->d_name[0] - (long)&d->d_ino))
10234187Smckusick #define letter(c) ((((c) >= 'a')&&((c) <= 'z')) ||\
10334187Smckusick (((c) >= 'A')&&((c) <= 'Z')))
10434187Smckusick #define digit(c) (((c) >= '0') && ((c) <= '9'))
10534187Smckusick #define HEXLETTER(c) (((c) >= 'A') && ((c) <= 'F'))
10634187Smckusick #define hexletter(c) (((c) >= 'a') && ((c) <= 'f'))
10734187Smckusick #define octaldigit(c) (((c) >= '0') && ((c) <= '7'))
10834187Smckusick #define uppertolower(c) ((c) - 'A' + 'a')
10934187Smckusick #define hextodigit(c) ((c) - 'a' + 10)
11034187Smckusick #define numtodigit(c) ((c) - '0')
11134187Smckusick #define loword(X) (((ushort *)&X)[1])
11234187Smckusick #define lobyte(X) (((unsigned char *)&X)[1])
11334187Smckusick
11434187Smckusick /*
11534187Smckusick * buffer cache structure.
11634187Smckusick */
11734187Smckusick struct buf {
11834187Smckusick struct buf *fwd;
11934187Smckusick struct buf *back;
12034187Smckusick char *blkaddr;
12134187Smckusick short valid;
12234187Smckusick long blkno;
12334187Smckusick } buf[NBUF], bhdr;
12434187Smckusick
12534187Smckusick /*
12634187Smckusick * used to hold save registers (see '<' and '>').
12734187Smckusick */
12834187Smckusick struct save_registers {
12934187Smckusick long sv_addr;
13034187Smckusick long sv_value;
13134187Smckusick long sv_objsz;
13234187Smckusick } regs[NREG];
13334187Smckusick
13434187Smckusick /*
13534187Smckusick * cd, find, and ls use this to hold filenames. Each filename is broken
13634187Smckusick * up by a slash. In other words, /usr/src/adm would have a len field
13734187Smckusick * of 2 (starting from 0), and filenames->fname[0-2] would hold usr,
13834187Smckusick * src, and adm components of the pathname.
13934187Smckusick */
14034187Smckusick struct filenames {
14134187Smckusick long ino; /* inode */
14234187Smckusick long len; /* number of components */
14334187Smckusick char flag; /* flag if using SECOND_DEPTH allocator */
14434187Smckusick char find; /* flag if found by find */
14534187Smckusick char **fname; /* hold components of pathname */
14634187Smckusick } *filenames, *top;
14734187Smckusick
14834187Smckusick struct fs filesystem, *fs; /* super block */
14934187Smckusick
15034187Smckusick /*
15134187Smckusick * Global data.
15234187Smckusick */
15334187Smckusick char *input_path[MAXPATHLEN];
15434187Smckusick char *stack_path[MAXPATHLEN];
15534187Smckusick char *current_path[MAXPATHLEN];
15634187Smckusick char input_buffer[INPUTBUFFER];
15734187Smckusick char *prompt;
15834187Smckusick char *buffers;
15934187Smckusick char scratch[64];
16034187Smckusick char BASE[] = "o u x";
16134187Smckusick char PROMPT[PROMPTSIZE] = "> ";
16234187Smckusick char laststyle = '/';
16334187Smckusick char lastpo = 'x';
16434187Smckusick short input_pointer;
16534187Smckusick short current_pathp;
16634187Smckusick short stack_pathp;
16734187Smckusick short input_pathp;
16834187Smckusick short cmp_level;
16934187Smckusick short nfiles;
17034187Smckusick short type = NUMB;
17134187Smckusick short dirslot;
17234187Smckusick short fd;
17334187Smckusick short c_count;
17434187Smckusick short error;
17534187Smckusick short paren;
17634187Smckusick short trapped;
17734187Smckusick short doing_cd;
17834187Smckusick short doing_find;
17934187Smckusick short find_by_name;
18034187Smckusick short find_by_inode;
18134187Smckusick short long_list;
18234187Smckusick short recursive;
18334187Smckusick short objsz = SHORT;
18434187Smckusick short override = 0;
18534187Smckusick short wrtflag;
18634187Smckusick short base = HEX;
18734187Smckusick short acting_on_inode;
18834187Smckusick short acting_on_directory;
18934187Smckusick short should_print = 1;
19034187Smckusick short clear;
19134187Smckusick short star;
19234187Smckusick long addr;
19334187Smckusick long bod_addr;
19434187Smckusick long value;
19534187Smckusick long erraddr;
19634187Smckusick long errcur_bytes;
19734187Smckusick long errino;
19834187Smckusick long errinum;
19934187Smckusick long cur_cgrp;
20034187Smckusick long cur_ino;
20134187Smckusick long cur_inum;
20234187Smckusick long cur_dir;
20334187Smckusick long cur_block;
20434187Smckusick long cur_bytes;
20534187Smckusick long find_ino;
20634187Smckusick long filesize;
20734187Smckusick long blocksize;
20834187Smckusick long stringsize;
20934187Smckusick long count = 1;
21034187Smckusick long commands;
21134187Smckusick long read_requests;
21234187Smckusick long actual_disk_reads;
21334187Smckusick jmp_buf env;
21434187Smckusick
21534187Smckusick char getachar();
21634187Smckusick char *getblk(), *fmtentry();
21746706Sbostic void err();
21834187Smckusick long get(), bmap(), expr(), term(), getnumb();
21934187Smckusick unsigned long *print_check();
22034187Smckusick
22134187Smckusick /*
22234187Smckusick * main - lines are read up to the unprotected ('\') newline and
22334187Smckusick * held in an input buffer. Characters may be read from the
22434187Smckusick * input buffer using getachar() and unread using ungetachar().
22534187Smckusick * Reading the whole line ahead allows the use of debuggers
22634187Smckusick * which would otherwise be impossible since the debugger
22734187Smckusick * and fsdb could not share stdin.
22834187Smckusick */
22934187Smckusick
main(argc,argv)23057998Sralph main(argc, argv)
23134187Smckusick short argc;
23234187Smckusick char **argv;
23334187Smckusick {
23434187Smckusick register char c, *cptr;
23534187Smckusick register short i, j, *iptr;
23634187Smckusick register struct direct *dirp;
23734187Smckusick register struct buf *bp;
23834187Smckusick struct filenames *fn;
23934187Smckusick char *progname;
24034187Smckusick short colon, mode;
24134187Smckusick long temp;
24234187Smckusick unsigned block;
24334187Smckusick int ffcmp();
24434187Smckusick
24534187Smckusick setbuf(stdin, NULL);
24634187Smckusick
24734187Smckusick progname = argv[0];
24834187Smckusick prompt = &PROMPT[0];
24934187Smckusick /*
25034187Smckusick * Parse options.
25134187Smckusick */
25234187Smckusick while (argc>1 && argv[1][0] == '-') {
25334187Smckusick if (strcmp("-?", argv[1]) == 0)
25434187Smckusick goto usage;
25534187Smckusick if (strcmp("-o", argv[1]) == 0) {
25634187Smckusick printf("error checking off\n");
25734187Smckusick override = 1;
25834187Smckusick argc--; argv++;
25934187Smckusick continue;
26034187Smckusick }
26157998Sralph if (strncmp("-p", argv[1], 2) == 0) {
26234187Smckusick prompt = &argv[1][2];
26334187Smckusick argc--; argv++;
26434187Smckusick continue;
26534187Smckusick }
26634187Smckusick if (strcmp("-w", argv[1]) == 0) {
26734187Smckusick wrtflag = 2; /* suitable for open */
26834187Smckusick argc--; argv++;
26934187Smckusick continue;
27034187Smckusick }
27134187Smckusick }
27257998Sralph if (argc != 2) {
27334187Smckusick usage:
27434187Smckusick printf("usage: %s [options] special\n", progname);
27534187Smckusick printf("options:\n");
27634187Smckusick printf("\t-? display usage\n");
27734187Smckusick printf("\t-o override some error conditions\n");
27834187Smckusick printf("\t-p\"string\" set prompt to string\n");
27934187Smckusick printf("\t-w open for write\n");
28034187Smckusick exit(1);
28134187Smckusick }
28234187Smckusick /*
28334187Smckusick * Attempt to open the special file.
28434187Smckusick */
28557998Sralph if ((fd = open(argv[1], wrtflag)) < 0) {
28634187Smckusick perror(argv[1]);
28734187Smckusick exit(1);
28834187Smckusick }
28934187Smckusick /*
29034187Smckusick * Read in the super block and validate (not too picky).
29134187Smckusick */
29257998Sralph if (lseek(fd, (off_t)(SBLOCK * DEV_BSIZE), SEEK_SET) == -1) {
29334187Smckusick perror(argv[1]);
29434187Smckusick exit(1);
29534187Smckusick }
29634187Smckusick if (read(fd, &filesystem, sizeof filesystem) != sizeof filesystem) {
29734187Smckusick printf("%s: cannot read superblock\n", argv[1]);
29834187Smckusick exit(1);
29934187Smckusick }
30034187Smckusick fs = &filesystem;
30134187Smckusick if (fs->fs_magic != FS_MAGIC) {
30234187Smckusick printf("%s: Bad magic number in file system\n", argv[1]);
30334187Smckusick exit(1);
30434187Smckusick }
30536249Smckusick #ifdef FS_42POSTBLFMT
30634197Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT)
30734197Smckusick fs->fs_nrpos = 8;
30836249Smckusick #endif
30934187Smckusick printf("fsdb of %s %s -- last mounted on %s\n",
31057998Sralph argv[1], wrtflag ? "(Opened for write)" : "(Read only)",
31134187Smckusick &fs->fs_fsmnt[0]);
31234187Smckusick /*
31334187Smckusick * Malloc buffers and set up cache.
31434187Smckusick */
31534187Smckusick buffers = malloc(NBUF * BLKSIZE);
31634187Smckusick bhdr.fwd = bhdr.back = &bhdr;
31757998Sralph for (i = 0; i < NBUF; i++) {
31834187Smckusick bp = &buf[i];
31934187Smckusick bp->blkaddr = buffers + (i * BLKSIZE);
32034187Smckusick bp->valid = 0;
32134187Smckusick insert(bp);
32234187Smckusick }
32334187Smckusick /*
32434187Smckusick * Malloc filenames structure. The space for the actual filenames
32534187Smckusick * is allocated as it needs it.
32634187Smckusick */
32734187Smckusick filenames = (struct filenames *)calloc(MAXFILES,
32834187Smckusick sizeof (struct filenames));
32934187Smckusick if (filenames == NULL) {
33034187Smckusick printf("out of memory\n");
33134187Smckusick exit(1);
33234187Smckusick }
33334187Smckusick
33434187Smckusick fn = filenames;
33534187Smckusick
33634187Smckusick restore_inode(2);
33734187Smckusick /*
33834187Smckusick * Malloc a few filenames (needed by pwd for example).
33934187Smckusick */
34034187Smckusick for (i = 0; i < MAXPATHLEN; i++) {
34134187Smckusick input_path[i] = calloc(1, MAXNAMLEN);
34234187Smckusick stack_path[i] = calloc(1, MAXNAMLEN);
34334187Smckusick current_path[i] = calloc(1, MAXNAMLEN);
34434187Smckusick if (current_path[i] == NULL) {
34534187Smckusick printf("out of memory\n");
34634187Smckusick exit(1);
34734187Smckusick }
34834187Smckusick }
34934187Smckusick current_pathp = -1;
35034187Smckusick
35157998Sralph signal(2, err);
35234187Smckusick setjmp(env);
35334187Smckusick
35434187Smckusick getnextinput();
35534187Smckusick /*
35634187Smckusick * Main loop and case statement. If an error condition occurs
35734187Smckusick * initialization and recovery is attempted.
35834187Smckusick */
35934187Smckusick for (;;) {
36034187Smckusick if (error) {
36134187Smckusick freemem(filenames, nfiles);
36234187Smckusick nfiles = 0;
36334187Smckusick c_count = 0;
36434187Smckusick count = 1;
36534187Smckusick star = 0;
36634187Smckusick error = 0;
36734187Smckusick paren = 0;
36834187Smckusick acting_on_inode = 0;
36934187Smckusick acting_on_directory = 0;
37034187Smckusick should_print = 1;
37134187Smckusick addr = erraddr;
37234187Smckusick cur_ino = errino;
37334187Smckusick cur_inum = errinum;
37434187Smckusick cur_bytes = errcur_bytes;
37534187Smckusick printf("?\n");
37634187Smckusick getnextinput();
37734187Smckusick if (error)
37834187Smckusick continue;
37934187Smckusick }
38034187Smckusick c_count++;
38134187Smckusick
38234187Smckusick switch (c = getachar()) {
38334187Smckusick
38434187Smckusick case '\n': /* command end */
38534187Smckusick freemem(filenames, nfiles);
38634187Smckusick nfiles = 0;
38734187Smckusick if (should_print && laststyle == '=') {
38834187Smckusick ungetachar(c);
38934187Smckusick goto calc;
39034187Smckusick }
39134187Smckusick if (c_count == 1) {
39234187Smckusick clear = 0;
39334187Smckusick should_print = 1;
39434187Smckusick erraddr = addr;
39534187Smckusick errino = cur_ino;
39634187Smckusick errinum = cur_inum;
39734187Smckusick errcur_bytes = cur_bytes;
39834187Smckusick switch (objsz) {
39934187Smckusick case DIRECTORY:
40057998Sralph addr = getdirslot(dirslot + 1);
40157998Sralph if (addr == 0)
40234187Smckusick should_print = 0;
40334187Smckusick if (error) {
40434187Smckusick ungetachar(c);
40534187Smckusick continue;
40634187Smckusick }
40734187Smckusick break;
40834187Smckusick case INODE:
40934187Smckusick cur_inum++;
41034187Smckusick addr = itob(cur_inum);
41134187Smckusick if (!icheck(addr)) {
41234187Smckusick cur_inum--;
41334187Smckusick should_print = 0;
41434187Smckusick }
41534187Smckusick break;
41634187Smckusick case CGRP:
41734187Smckusick case SB:
41834187Smckusick cur_cgrp++;
41957998Sralph addr = cgrp_check(cur_cgrp);
42057998Sralph if (addr == 0) {
42134187Smckusick cur_cgrp--;
42234187Smckusick continue;
42334187Smckusick }
42434187Smckusick break;
42534187Smckusick default:
42634187Smckusick addr += objsz;
42734187Smckusick cur_bytes += objsz;
42834187Smckusick if (valid_addr() == 0)
42934187Smckusick continue;
43034187Smckusick }
43134187Smckusick }
43234187Smckusick if (type == NUMB)
43334187Smckusick trapped = 0;
43434187Smckusick if (should_print)
43534187Smckusick switch (objsz) {
43634187Smckusick case DIRECTORY:
43734187Smckusick fprnt('?', 'd');
43834187Smckusick break;
43934187Smckusick case INODE:
44034187Smckusick fprnt('?', 'i');
44134187Smckusick if (!error)
44234187Smckusick cur_ino = addr;
44334187Smckusick break;
44434187Smckusick case CGRP:
44534187Smckusick fprnt('?', 'c');
44634187Smckusick break;
44734187Smckusick case SB:
44834187Smckusick fprnt('?', 's');
44934187Smckusick break;
45034187Smckusick case CHAR:
45134187Smckusick case SHORT:
45234187Smckusick case LONG:
45334187Smckusick fprnt(laststyle, lastpo);
45434187Smckusick }
45534187Smckusick if (error) {
45634187Smckusick ungetachar(c);
45734187Smckusick continue;
45834187Smckusick }
45934187Smckusick c_count = colon = acting_on_inode = 0;
46034187Smckusick acting_on_directory = 0;
46134187Smckusick should_print = 1;
46234187Smckusick getnextinput();
46334187Smckusick if (error)
46434187Smckusick continue;
46534187Smckusick erraddr = addr;
46634187Smckusick errino = cur_ino;
46734187Smckusick errinum = cur_inum;
46834187Smckusick errcur_bytes = cur_bytes;
46934187Smckusick continue;
47034187Smckusick
47134187Smckusick case '(': /* numeric expression or unknown command */
47234187Smckusick default:
47334187Smckusick colon = 0;
47434187Smckusick if (digit(c) || c == '(') {
47534187Smckusick ungetachar(c);
47634187Smckusick addr = expr();
47734187Smckusick type = NUMB;
47834187Smckusick value = addr;
47934187Smckusick continue;
48034187Smckusick }
48134187Smckusick printf("unknown command or bad syntax\n");
48234187Smckusick error++;
48334187Smckusick continue;
48434187Smckusick
48534187Smckusick case '?': /* general print facilities */
48634187Smckusick case '/':
48734187Smckusick fprnt(c, getachar());
48834187Smckusick continue;
48934187Smckusick
49034187Smckusick case ';': /* command separator and . */
49134187Smckusick case '\t':
49234187Smckusick case ' ':
49334187Smckusick case '.':
49434187Smckusick continue;
49534187Smckusick
49634187Smckusick case ':': /* command indicator */
49734187Smckusick colon++;
49834187Smckusick commands++;
49934187Smckusick should_print = 0;
50034187Smckusick stringsize = 0;
50134187Smckusick trapped = 0;
50234187Smckusick continue;
50334187Smckusick
50434187Smckusick case ',': /* count indicator */
50534187Smckusick colon = star = 0;
50634187Smckusick if ((c = getachar()) == '*') {
50734187Smckusick star = 1;
50834187Smckusick count = BLKSIZE;
50934187Smckusick } else {
51034187Smckusick ungetachar(c);
51134187Smckusick count = expr();
51234187Smckusick if (error)
51334187Smckusick continue;
51434187Smckusick if (!count)
51534187Smckusick count = 1;
51634187Smckusick }
51734187Smckusick clear = 0;
51834187Smckusick continue;
51934187Smckusick
52034187Smckusick case '+': /* address addition */
52134187Smckusick colon = 0;
52234187Smckusick c = getachar();
52334187Smckusick ungetachar(c);
52434187Smckusick if (c == '\n')
52534187Smckusick temp = 1;
52634187Smckusick else {
52734187Smckusick temp = expr();
52834187Smckusick if (error)
52934187Smckusick continue;
53034187Smckusick }
53134187Smckusick erraddr = addr;
53234187Smckusick errcur_bytes = cur_bytes;
53334187Smckusick switch (objsz) {
53434187Smckusick case DIRECTORY:
53534187Smckusick addr = getdirslot(dirslot + temp);
53634187Smckusick if (error)
53734187Smckusick continue;
53834187Smckusick break;
53934187Smckusick case INODE:
54034187Smckusick cur_inum += temp;
54134187Smckusick addr = itob(cur_inum);
54234187Smckusick if (!icheck(addr)) {
54334187Smckusick cur_inum -= temp;
54434187Smckusick continue;
54534187Smckusick }
54634187Smckusick break;
54734187Smckusick case CGRP:
54834187Smckusick case SB:
54934187Smckusick cur_cgrp += temp;
55034187Smckusick if ((addr = cgrp_check(cur_cgrp)) == 0) {
55134187Smckusick cur_cgrp -= temp;
55234187Smckusick continue;
55334187Smckusick }
55434187Smckusick break;
55534187Smckusick default:
55634187Smckusick laststyle = '/';
55734187Smckusick addr += temp * objsz;
55834187Smckusick cur_bytes += temp * objsz;
55934187Smckusick if (valid_addr() == 0)
56034187Smckusick continue;
56134187Smckusick }
56234187Smckusick value = get(objsz);
56334187Smckusick continue;
56434187Smckusick
56534187Smckusick case '-': /* address subtraction */
56634187Smckusick colon = 0;
56734187Smckusick c = getachar();
56834187Smckusick ungetachar(c);
56934187Smckusick if (c == '\n')
57034187Smckusick temp = 1;
57134187Smckusick else {
57234187Smckusick temp = expr();
57334187Smckusick if (error)
57434187Smckusick continue;
57534187Smckusick }
57634187Smckusick erraddr = addr;
57734187Smckusick errcur_bytes = cur_bytes;
57834187Smckusick switch (objsz) {
57934187Smckusick case DIRECTORY:
58034187Smckusick addr = getdirslot(dirslot - temp);
58134187Smckusick if (error)
58234187Smckusick continue;
58334187Smckusick break;
58434187Smckusick case INODE:
58534187Smckusick cur_inum -= temp;
58634187Smckusick addr = itob(cur_inum);
58734187Smckusick if (!icheck(addr)) {
58834187Smckusick cur_inum += temp;
58934187Smckusick continue;
59034187Smckusick }
59134187Smckusick break;
59234187Smckusick case CGRP:
59334187Smckusick case SB:
59434187Smckusick cur_cgrp -= temp;
59534187Smckusick if ((addr = cgrp_check(cur_cgrp)) == 0) {
59634187Smckusick cur_cgrp += temp;
59734187Smckusick continue;
59834187Smckusick }
59934187Smckusick break;
60034187Smckusick default:
60134187Smckusick laststyle = '/';
60234187Smckusick addr -= temp * objsz;
60334187Smckusick cur_bytes -= temp * objsz;
60434187Smckusick if (valid_addr() == 0)
60534187Smckusick continue;
60634187Smckusick }
60734187Smckusick value = get(objsz);
60834187Smckusick continue;
60934187Smckusick
61034187Smckusick case '*': /* address multiplication */
61134187Smckusick colon = 0;
61234187Smckusick temp = expr();
61334187Smckusick if (error)
61434187Smckusick continue;
61534187Smckusick if (objsz != INODE && objsz != DIRECTORY)
61634187Smckusick laststyle = '/';
61734187Smckusick addr *= temp;
61834187Smckusick value = get(objsz);
61934187Smckusick continue;
62034187Smckusick
62134187Smckusick case '%': /* address division */
62234187Smckusick colon = 0;
62334187Smckusick temp = expr();
62434187Smckusick if (error)
62534187Smckusick continue;
62634187Smckusick if (!temp) {
62734187Smckusick printf("divide by zero\n");
62834187Smckusick error++;
62934187Smckusick continue;
63034187Smckusick }
63134187Smckusick if (objsz != INODE && objsz != DIRECTORY)
63234187Smckusick laststyle = '/';
63334187Smckusick addr /= temp;
63434187Smckusick value = get(objsz);
63534187Smckusick continue;
63634187Smckusick
63734187Smckusick case '=': { /* assignment operation */
63834187Smckusick short tbase = base;
63934187Smckusick
64034187Smckusick calc:
64134187Smckusick c = getachar();
64234187Smckusick if (c == '\n') {
64334187Smckusick ungetachar(c);
64434187Smckusick c = lastpo;
64534187Smckusick if (acting_on_inode == 1) {
64634187Smckusick if (c != 'o' && c != 'd' && c != 'x' &&
64734187Smckusick c != 'O' && c != 'D' && c != 'X') {
64834187Smckusick switch (objsz) {
64934187Smckusick case LONG:
65034187Smckusick c = lastpo = 'X';
65134187Smckusick break;
65234187Smckusick case SHORT:
65334187Smckusick c = lastpo = 'x';
65434187Smckusick break;
65534187Smckusick case CHAR:
65634187Smckusick c = lastpo = 'c';
65734187Smckusick }
65834187Smckusick }
65934187Smckusick } else {
66034187Smckusick if (acting_on_inode == 2)
66134187Smckusick c = lastpo = 't';
66234187Smckusick }
66334187Smckusick } else if (acting_on_inode)
66434187Smckusick lastpo = c;
66534187Smckusick should_print = star = 0;
66634187Smckusick count = 1;
66734187Smckusick erraddr = addr;
66834187Smckusick errcur_bytes = cur_bytes;
66934187Smckusick switch (c) {
67034187Smckusick case '"': /* character string */
67134187Smckusick if (type == NUMB) {
67234187Smckusick blocksize = BLKSIZE;
67334187Smckusick filesize = BLKSIZE * 2;
67434187Smckusick cur_bytes = blkoff(fs, addr);
67534187Smckusick if (objsz==DIRECTORY || objsz==INODE)
67634187Smckusick lastpo = 'X';
67734187Smckusick }
67834187Smckusick puta();
67934187Smckusick continue;
68034187Smckusick case '+': /* =+ operator */
68134187Smckusick temp = expr();
68234187Smckusick value = get(objsz);
68334187Smckusick if (!error)
68457998Sralph put(value+temp, objsz);
68534187Smckusick continue;
68634187Smckusick case '-': /* =- operator */
68734187Smckusick temp = expr();
68834187Smckusick value = get(objsz);
68934187Smckusick if (!error)
69057998Sralph put(value-temp, objsz);
69134187Smckusick continue;
69234187Smckusick case 'b':
69334187Smckusick case 'c':
69434187Smckusick if (objsz == CGRP)
69534187Smckusick fprnt('?', c);
69634187Smckusick else
69734187Smckusick fprnt('/', c);
69834187Smckusick continue;
69934187Smckusick case 'i':
70034187Smckusick addr = cur_ino;
70134187Smckusick fprnt('?', 'i');
70257998Sralph continue;
70334187Smckusick case 's':
70434187Smckusick fprnt('?', 's');
70534187Smckusick continue;
70634187Smckusick case 't':
70734187Smckusick case 'T':
70834187Smckusick laststyle = '=';
70934187Smckusick printf("\t\t");
71034187Smckusick printf("%s", ctime(&value));
71134187Smckusick continue;
71234187Smckusick case 'o':
71334187Smckusick base = OCTAL;
71434187Smckusick goto otx;
71534187Smckusick case 'd':
71634187Smckusick if (objsz == DIRECTORY) {
71734187Smckusick addr = cur_dir;
71834187Smckusick fprnt('?', 'd');
71934187Smckusick continue;
72034187Smckusick }
72134187Smckusick base = DECIMAL;
72234187Smckusick goto otx;
72334187Smckusick case 'x':
72434187Smckusick base = HEX;
72534187Smckusick otx:
72634187Smckusick laststyle = '=';
72734187Smckusick printf("\t\t");
72834187Smckusick if (acting_on_inode)
72934187Smckusick print(value & 0177777L, 12, -8, 0);
73034187Smckusick else
73134187Smckusick print(addr & 0177777L, 12, -8, 0);
73234187Smckusick printf("\n");
73334187Smckusick base = tbase;
73434187Smckusick continue;
73534187Smckusick case 'O':
73634187Smckusick base = OCTAL;
73734187Smckusick goto OTX;
73834187Smckusick case 'D':
73934187Smckusick base = DECIMAL;
74034187Smckusick goto OTX;
74134187Smckusick case 'X':
74234187Smckusick base = HEX;
74334187Smckusick OTX:
74434187Smckusick laststyle = '=';
74534187Smckusick printf("\t\t");
74634187Smckusick if (acting_on_inode)
74734187Smckusick print(value, 12, -8, 0);
74834187Smckusick else
74934187Smckusick print(addr, 12, -8, 0);
75034187Smckusick printf("\n");
75134187Smckusick base = tbase;
75234187Smckusick continue;
75334187Smckusick default: /* regular assignment */
75434187Smckusick ungetachar(c);
75534187Smckusick value = expr();
75634187Smckusick if (error)
75734187Smckusick printf("syntax error\n");
75834187Smckusick else
75957998Sralph put(value, objsz);
76034187Smckusick continue;
76134187Smckusick }
76234187Smckusick }
76334187Smckusick
76434187Smckusick case '>': /* save current address */
76534187Smckusick colon = 0;
76634187Smckusick should_print = 0;
76734187Smckusick c = getachar();
76834187Smckusick if (!letter(c) && !digit(c)) {
76934187Smckusick printf("invalid register specification, ");
77034187Smckusick printf("must be letter or digit\n");
77134187Smckusick error++;
77234187Smckusick continue;
77334187Smckusick }
77434187Smckusick if (letter(c)) {
77534187Smckusick if (c < 'a')
77634187Smckusick c = uppertolower(c);
77734187Smckusick c = hextodigit(c);
77834187Smckusick } else
77934187Smckusick c = numtodigit(c);
78034187Smckusick regs[c].sv_addr = addr;
78134187Smckusick regs[c].sv_value = value;
78234187Smckusick regs[c].sv_objsz = objsz;
78334187Smckusick continue;
78434187Smckusick
78534187Smckusick case '<': /* restore saved address */
78634187Smckusick colon = 0;
78734187Smckusick should_print = 0;
78834187Smckusick c = getachar();
78934187Smckusick if (!letter(c) && !digit(c)) {
79034187Smckusick printf("invalid register specification, ");
79134187Smckusick printf("must be letter or digit\n");
79234187Smckusick error++;
79334187Smckusick continue;
79434187Smckusick }
79534187Smckusick if (letter(c)) {
79634187Smckusick if (c < 'a')
79734187Smckusick c = uppertolower(c);
79834187Smckusick c = hextodigit(c);
79934187Smckusick } else
80034187Smckusick c = numtodigit(c);
80134187Smckusick addr = regs[c].sv_addr;
80234187Smckusick value = regs[c].sv_value;
80334187Smckusick objsz = regs[c].sv_objsz;
80434187Smckusick continue;
80534187Smckusick
80634187Smckusick case 'a':
80734187Smckusick if (colon)
80834187Smckusick colon = 0;
80934187Smckusick else
81034187Smckusick goto no_colon;
81134187Smckusick if (match("at", 2)) { /* access time */
81234187Smckusick acting_on_inode = 2;
81334187Smckusick should_print = 1;
81434187Smckusick addr = (long)
81534187Smckusick &((struct dinode *)cur_ino)->di_atime;
81634187Smckusick value = get(LONG);
81734187Smckusick type = NULL;
81834187Smckusick continue;
81934187Smckusick }
82034187Smckusick goto bad_syntax;
82134187Smckusick
82234187Smckusick case 'b':
82334187Smckusick if (colon)
82434187Smckusick colon = 0;
82534187Smckusick else
82634187Smckusick goto no_colon;
82734187Smckusick if (match("block", 2)) { /* block conversion */
82834187Smckusick if (type == NUMB) {
82934187Smckusick value = addr;
83034187Smckusick cur_bytes = 0;
83134187Smckusick blocksize = BLKSIZE;
83234187Smckusick filesize = BLKSIZE * 2;
83334187Smckusick }
83434187Smckusick addr = value << FRGSHIFT;
83534187Smckusick bod_addr = addr;
83634187Smckusick value = get(LONG);
83734187Smckusick type = BLOCK;
83834187Smckusick dirslot = 0;
83934187Smckusick trapped++;
84034187Smckusick continue;
84134187Smckusick }
84234187Smckusick if (match("bs", 2)) { /* block size */
84334187Smckusick acting_on_inode = 1;
84434187Smckusick should_print = 1;
84534187Smckusick if (icheck(cur_ino) == 0)
84634187Smckusick continue;
84734187Smckusick addr = (long)
84834187Smckusick &((struct dinode *)cur_ino)->di_blocks;
84934187Smckusick value = get(LONG);
85034187Smckusick type = NULL;
85134187Smckusick continue;
85234187Smckusick }
85334187Smckusick if (match("base", 2)) { /* change/show base */
85434187Smckusick showbase:
85534187Smckusick if ((c = getachar()) == '\n') {
85634187Smckusick ungetachar(c);
85734187Smckusick printf("base =\t\t");
85834187Smckusick switch (base) {
85934187Smckusick case OCTAL:
86034187Smckusick printf("OCTAL\n");
86134187Smckusick continue;
86234187Smckusick case DECIMAL:
86334187Smckusick printf("DECIMAL\n");
86434187Smckusick continue;
86534187Smckusick case HEX:
86634187Smckusick printf("HEX\n");
86734187Smckusick continue;
86834187Smckusick }
86934187Smckusick }
87034187Smckusick if (c != '=') {
87134187Smckusick printf("missing '='\n");
87234187Smckusick error++;
87334187Smckusick continue;
87434187Smckusick }
87534187Smckusick value = expr();
87634187Smckusick switch (value) {
87734187Smckusick default:
87834187Smckusick printf("invalid base\n");
87934187Smckusick error++;
88034187Smckusick break;
88134187Smckusick case OCTAL:
88234187Smckusick case DECIMAL:
88334187Smckusick case HEX:
88434187Smckusick base = value;
88534187Smckusick }
88634187Smckusick goto showbase;
88734187Smckusick }
88834187Smckusick goto bad_syntax;
88934187Smckusick
89034187Smckusick case 'c':
89134187Smckusick if (colon)
89234187Smckusick colon = 0;
89334187Smckusick else
89434187Smckusick goto no_colon;
89534187Smckusick if (match("cd", 2)) { /* change directory */
89634187Smckusick top = filenames - 1;
89734187Smckusick eat_spaces();
89834187Smckusick if ((c = getachar()) == '\n') {
89934187Smckusick ungetachar(c);
90034187Smckusick current_pathp = -1;
90134187Smckusick restore_inode(2);
90234187Smckusick continue;
90334187Smckusick }
90434187Smckusick ungetachar(c);
90534187Smckusick temp = cur_inum;
90634187Smckusick doing_cd = 1;
90734187Smckusick parse();
90834187Smckusick doing_cd = 0;
90934187Smckusick if (nfiles != 1) {
91034187Smckusick restore_inode(temp);
91134187Smckusick if (!error) {
91234187Smckusick print_path(input_path,
91334187Smckusick input_pathp);
91434187Smckusick if (nfiles == 0)
91534187Smckusick printf(" not found\n");
91634187Smckusick else
91734187Smckusick printf(" ambiguous\n");
91834187Smckusick error++;
91934187Smckusick }
92034187Smckusick continue;
92134187Smckusick }
92234187Smckusick restore_inode(filenames->ino);
92334187Smckusick if ((mode = icheck(addr)) == 0)
92434187Smckusick continue;
92534187Smckusick if ((mode & IFMT) != IFDIR) {
92634187Smckusick restore_inode(temp);
92734187Smckusick print_path(input_path, input_pathp);
92834187Smckusick printf(" not a directory\n");
92934187Smckusick error++;
93034187Smckusick continue;
93134187Smckusick }
93234187Smckusick for (i = 0; i <= top->len; i++)
93334187Smckusick strcpy(current_path[i],
93434187Smckusick top->fname[i]);
93534187Smckusick current_pathp = top->len;
93634187Smckusick continue;
93734187Smckusick }
93834187Smckusick if (match("cg", 2)) { /* cylinder group */
93934187Smckusick if (type == NUMB)
94034187Smckusick value = addr;
94134187Smckusick if (value > fs->fs_ncg - 1) {
94234187Smckusick printf("maximum cylinder group is ");
94334187Smckusick print(fs->fs_ncg - 1, 8, -8, 0);
94434187Smckusick printf("\n");
94534187Smckusick error++;
94634187Smckusick continue;
94734187Smckusick }
94834187Smckusick type = objsz = CGRP;
94934187Smckusick cur_cgrp = value;
95034187Smckusick addr = cgtod(fs, cur_cgrp) << FRGSHIFT;
95134187Smckusick continue;
95234187Smckusick }
95334187Smckusick if (match("ct", 2)) { /* creation time */
95434187Smckusick acting_on_inode = 2;
95534187Smckusick should_print = 1;
95634187Smckusick addr = (long)
95734187Smckusick &((struct dinode *)cur_ino)->di_ctime;
95834187Smckusick value = get(LONG);
95934187Smckusick type = NULL;
96034187Smckusick continue;
96134187Smckusick }
96234187Smckusick goto bad_syntax;
96334187Smckusick
96434187Smckusick case 'd':
96534187Smckusick if (colon)
96634187Smckusick colon = 0;
96734187Smckusick else
96834187Smckusick goto no_colon;
96934187Smckusick if (match("directory", 2)) { /* directory offsets */
97034187Smckusick if (type == NUMB)
97134187Smckusick value = addr;
97234187Smckusick objsz = DIRECTORY;
97334187Smckusick type = DIRECTORY;
97434187Smckusick addr = getdirslot(value);
97534187Smckusick continue;
97634187Smckusick }
97734187Smckusick if (match("db", 2)) { /* direct block */
97834187Smckusick acting_on_inode = 1;
97934187Smckusick should_print = 1;
98034187Smckusick if (type == NUMB)
98134187Smckusick value = addr;
98234187Smckusick if (value >= NDADDR) {
98334187Smckusick printf("direct blocks are 0 to ");
98434187Smckusick print(NDADDR - 1, 0, 0, 0);
98534187Smckusick printf("\n");
98634187Smckusick error++;
98734187Smckusick continue;
98834187Smckusick }
98934187Smckusick addr = cur_ino;
99034187Smckusick if (!icheck(addr))
99134187Smckusick continue;
99234187Smckusick addr = (long)
99334187Smckusick &((struct dinode *)cur_ino)->di_db[value];
99434187Smckusick bod_addr = addr;
99534187Smckusick cur_bytes = (value) * BLKSIZE;
99634187Smckusick cur_block = value;
99734187Smckusick type = BLOCK;
99834187Smckusick dirslot = 0;
99934187Smckusick value = get(LONG);
100034187Smckusick if (!value && !override) {
100134187Smckusick printf("non existent block\n");
100234187Smckusick error++;
100334187Smckusick }
100434187Smckusick continue;
100534187Smckusick }
100634187Smckusick goto bad_syntax;
100734187Smckusick
100834187Smckusick case 'f':
100957998Sralph if (colon)
101034187Smckusick colon = 0;
101134187Smckusick else
101234187Smckusick goto no_colon;
101334187Smckusick if (match("find", 3)) { /* find command */
101434187Smckusick find();
101534187Smckusick continue;
101634187Smckusick }
101734187Smckusick if (match("fragment", 2)) { /* fragment conv. */
101834187Smckusick if (type == NUMB) {
101934187Smckusick value = addr;
102034187Smckusick cur_bytes = 0;
102134187Smckusick blocksize = FRGSIZE;
102234187Smckusick filesize = FRGSIZE * 2;
102334187Smckusick }
102434187Smckusick if (min(blocksize, filesize) - cur_bytes >
102534187Smckusick FRGSIZE) {
102634187Smckusick blocksize = cur_bytes + FRGSIZE;
102734187Smckusick filesize = blocksize * 2;
102834187Smckusick }
102934187Smckusick addr = value << FRGSHIFT;
103034187Smckusick bod_addr = addr;
103134187Smckusick value = get(LONG);
103234187Smckusick type = FRAGMENT;
103334187Smckusick dirslot = 0;
103434187Smckusick trapped++;
103534187Smckusick continue;
103634187Smckusick }
103734187Smckusick if (match("file", 4)) { /* access as file */
103834187Smckusick acting_on_inode = 1;
103934187Smckusick should_print = 1;
104034187Smckusick if (type == NUMB)
104134187Smckusick value = addr;
104234187Smckusick addr = cur_ino;
104334187Smckusick if ((mode = icheck(addr)) == 0)
104434187Smckusick continue;
104534187Smckusick if ((mode & IFCHR) && !override) {
104634187Smckusick printf("special device\n");
104734187Smckusick error++;
104834187Smckusick continue;
104934187Smckusick }
105034187Smckusick if ((addr = (bmap(value) << FRGSHIFT)) == 0)
105134187Smckusick continue;
105234187Smckusick cur_block = value;
105334187Smckusick bod_addr = addr;
105434187Smckusick type = BLOCK;
105534187Smckusick dirslot = 0;
105634187Smckusick continue;
105734187Smckusick }
105834187Smckusick if (match("fill", 4)) { /* fill */
105934187Smckusick if (getachar() != '=') {
106034187Smckusick printf("missing '='\n");
106134187Smckusick error++;
106234187Smckusick continue;
106334187Smckusick }
106434187Smckusick if (objsz == INODE || objsz == DIRECTORY) {
106534187Smckusick printf("can't fill inode or directory\n");
106634187Smckusick error++;
106734187Smckusick continue;
106834187Smckusick }
106934187Smckusick fill();
107034187Smckusick continue;
107134187Smckusick }
107234187Smckusick goto bad_syntax;
107334187Smckusick
107434187Smckusick case 'g':
107534187Smckusick if (colon)
107634187Smckusick colon = 0;
107734187Smckusick else
107834187Smckusick goto no_colon;
107934187Smckusick if (match("gid", 1)) { /* group id */
108034187Smckusick acting_on_inode = 1;
108134187Smckusick should_print = 1;
108234187Smckusick addr = (long)
108334187Smckusick &((struct dinode *)cur_ino)->di_gid;
108434187Smckusick value = get(SHORT);
108534187Smckusick type = NULL;
108634187Smckusick continue;
108734187Smckusick }
108834187Smckusick goto bad_syntax;
108934187Smckusick
109034187Smckusick case 'i':
109134187Smckusick if (colon)
109234187Smckusick colon = 0;
109334187Smckusick else
109434187Smckusick goto no_colon;
109534187Smckusick if (match("inode", 2)) { /* i# to inode conversion */
109634187Smckusick if (c_count == 2) {
109734187Smckusick addr = cur_ino;
109834187Smckusick value = get(INODE);
109934187Smckusick type = NULL;
110034187Smckusick laststyle = '=';
110134187Smckusick lastpo = 'i';
110234187Smckusick should_print = 1;
110334187Smckusick continue;
110434187Smckusick }
110534187Smckusick if (type == NUMB)
110634187Smckusick value = addr;
110734187Smckusick addr = itob(value);
110834187Smckusick if (!icheck(addr))
110934187Smckusick continue;
111034187Smckusick cur_ino = addr;
111134187Smckusick cur_inum = value;
111234187Smckusick value = get(INODE);
111334187Smckusick type = NULL;
111434187Smckusick continue;
111534187Smckusick }
111634187Smckusick if (match("ib", 2)) { /* indirect block */
111734187Smckusick acting_on_inode = 1;
111834187Smckusick should_print = 1;
111934187Smckusick if (type == NUMB)
112034187Smckusick value = addr;
112134187Smckusick if (value >= NIADDR) {
112234187Smckusick printf("indirect blocks are 0 to ");
112334187Smckusick print(NIADDR - 1, 0, 0, 0);
112434187Smckusick printf("\n");
112534187Smckusick error++;
112634187Smckusick continue;
112734187Smckusick }
112834187Smckusick addr = (long)
112934187Smckusick &((struct dinode *)cur_ino)->di_ib[value];
113034187Smckusick cur_bytes = (NDADDR - 1) * BLKSIZE;
113134187Smckusick temp = 1;
113234187Smckusick for (i = 0; i < value; i++) {
113334187Smckusick temp *= NINDIR(fs) * BLKSIZE;
113434187Smckusick cur_bytes += temp;
113534187Smckusick }
113634187Smckusick type = BLOCK;
113734187Smckusick dirslot = 0;
113834187Smckusick value = get(LONG);
113934187Smckusick if (!value && !override) {
114034187Smckusick printf("non existent block\n");
114134187Smckusick error++;
114234187Smckusick }
114334187Smckusick continue;
114434187Smckusick }
114534187Smckusick goto bad_syntax;
114634187Smckusick
114734187Smckusick case 'l':
114834187Smckusick if (colon)
114934187Smckusick colon = 0;
115034187Smckusick else
115134187Smckusick goto no_colon;
115234187Smckusick if (match("ls", 2)) { /* ls command */
115334187Smckusick temp = cur_inum;
115434187Smckusick recursive = long_list = 0;
115534187Smckusick top = filenames - 1;
115634187Smckusick for (;;) {
115734187Smckusick eat_spaces();
115834187Smckusick if ((c = getachar()) == '-') {
115934187Smckusick if ((c = getachar()) == 'R') {
116034187Smckusick recursive = 1;
116134187Smckusick continue;
116234187Smckusick } else if (c == 'l') {
116334187Smckusick long_list = 1;
116434187Smckusick } else {
116534187Smckusick printf("unknown option ");
116634187Smckusick printf("'%c'\n", c);
116734187Smckusick error++;
116834187Smckusick break;
116934187Smckusick }
117034187Smckusick } else
117134187Smckusick ungetachar(c);
117234187Smckusick if ((c = getachar()) == '\n') {
117334187Smckusick if (c_count != 2) {
117434187Smckusick ungetachar(c);
117534187Smckusick break;
117634187Smckusick }
117734187Smckusick }
117834187Smckusick c_count++;
117934187Smckusick ungetachar(c);
118034187Smckusick parse();
118134187Smckusick restore_inode(temp);
118234187Smckusick if (error)
118334187Smckusick break;
118434187Smckusick }
118534187Smckusick recursive = 0;
118634187Smckusick if (error || nfiles == 0) {
118734187Smckusick if (!error) {
118834187Smckusick print_path(input_path,
118934187Smckusick input_pathp);
119034187Smckusick printf(" not found\n");
119134187Smckusick }
119234187Smckusick continue;
119334187Smckusick }
119434187Smckusick if (nfiles) {
119534187Smckusick cmp_level = 0;
119634187Smckusick qsort((char *)filenames, nfiles,
119734187Smckusick sizeof (struct filenames), ffcmp);
119834187Smckusick ls(filenames, filenames + (nfiles - 1), 0);
119934187Smckusick } else {
120034187Smckusick printf("no match\n");
120134187Smckusick error++;
120234187Smckusick }
120334187Smckusick restore_inode(temp);
120434187Smckusick continue;
120534187Smckusick }
120634187Smckusick if (match("ln", 2)) { /* link count */
120734187Smckusick acting_on_inode = 1;
120834187Smckusick should_print = 1;
120934187Smckusick addr = (long)
121034187Smckusick &((struct dinode *)cur_ino)->di_nlink;
121134187Smckusick value = get(SHORT);
121234187Smckusick type = NULL;
121334187Smckusick continue;
121434187Smckusick }
121534187Smckusick goto bad_syntax;
121634187Smckusick
121734187Smckusick case 'm':
121834187Smckusick if (colon)
121934187Smckusick colon = 0;
122034187Smckusick else
122134187Smckusick goto no_colon;
122234187Smckusick addr = cur_ino;
122334187Smckusick if ((mode = icheck(addr)) == 0)
122434187Smckusick continue;
122534187Smckusick if (match("mt", 2)) { /* modification time */
122634187Smckusick acting_on_inode = 2;
122734187Smckusick should_print = 1;
122834187Smckusick addr = (long)
122934187Smckusick &((struct dinode *)cur_ino)->di_mtime;
123034187Smckusick value = get(LONG);
123134187Smckusick type = NULL;
123234187Smckusick continue;
123334187Smckusick }
123434187Smckusick if (match("md", 2)) { /* mode */
123534187Smckusick acting_on_inode = 1;
123634187Smckusick should_print = 1;
123734187Smckusick addr = (long)
123834187Smckusick &((struct dinode *)cur_ino)->di_mode;
123934187Smckusick value = get(SHORT);
124034187Smckusick type = NULL;
124134187Smckusick continue;
124234187Smckusick }
124334187Smckusick if (match("maj", 2)) { /* major device number */
124434187Smckusick acting_on_inode = 1;
124534187Smckusick should_print = 1;
124634187Smckusick if (devcheck(mode))
124734187Smckusick continue;
124834187Smckusick addr = (long)
124934187Smckusick &((struct dinode *)cur_ino)->di_db[1];
125034187Smckusick value = get(LONG);
125134187Smckusick type = NULL;
125234187Smckusick continue;
125334187Smckusick }
125434187Smckusick if (match("min", 2)) { /* minor device number */
125534187Smckusick acting_on_inode = 1;
125634187Smckusick should_print = 1;
125734187Smckusick if (devcheck(mode))
125834187Smckusick continue;
125934187Smckusick addr = (long)
126034187Smckusick &((struct dinode *)cur_ino)->di_db[0];
126134187Smckusick value = get(LONG);
126234187Smckusick type = NULL;
126334187Smckusick continue;
126434187Smckusick }
126534187Smckusick goto bad_syntax;
126634187Smckusick
126734187Smckusick case 'n':
126834187Smckusick if (colon)
126934187Smckusick colon = 0;
127034187Smckusick else
127134187Smckusick goto no_colon;
127234187Smckusick if (match("nm", 1)) { /* directory name */
127334187Smckusick objsz = DIRECTORY;
127434187Smckusick acting_on_directory = 1;
127534187Smckusick cur_dir = addr;
127634187Smckusick if ((cptr = getblk(addr)) == 0)
127734187Smckusick continue;
127834187Smckusick dirp = (struct direct *)(cptr+blkoff(fs, addr));
127934187Smckusick stringsize = (long)dirp->d_reclen -
128034187Smckusick ((long)&dirp->d_name[0] - (long)&dirp->d_ino);
128134187Smckusick addr = (long)
128234187Smckusick &((struct direct *)addr)->d_name[0];
128334187Smckusick type = NULL;
128434187Smckusick continue;
128534187Smckusick }
128634187Smckusick goto bad_syntax;
128734187Smckusick
128834187Smckusick case 'o':
128957998Sralph if (colon)
129034187Smckusick colon = 0;
129134187Smckusick else
129234187Smckusick goto no_colon;
129334187Smckusick if (match("override", 1)) { /* override flip flop */
129434187Smckusick if (override = !override)
129534187Smckusick printf("error checking off\n");
129634187Smckusick else
129734187Smckusick printf("error checking on\n");
129834187Smckusick continue;
129934187Smckusick }
130034187Smckusick goto bad_syntax;
130134187Smckusick
130234187Smckusick case 'p':
130334187Smckusick if (colon)
130434187Smckusick colon = 0;
130534187Smckusick else
130634187Smckusick goto no_colon;
130734187Smckusick if (match("pwd", 2)) { /* print working dir */
130834187Smckusick print_path(current_path, current_pathp);
130934187Smckusick printf("\n");
131034187Smckusick continue;
131134187Smckusick }
131234187Smckusick if (match("prompt", 2)) { /* change prompt */
131334187Smckusick if ((c = getachar()) != '=') {
131434187Smckusick printf("missing '='\n");
131534187Smckusick error++;
131634187Smckusick continue;
131734187Smckusick }
131834187Smckusick if ((c = getachar()) != '"') {
131934187Smckusick printf("missing '\"'\n");
132034187Smckusick error++;
132134187Smckusick continue;
132234187Smckusick }
132334187Smckusick i = 0;
132434187Smckusick prompt = &prompt[0];
132534187Smckusick while ((c = getachar()) != '"' &&
132634187Smckusick c != '\n') {
132734187Smckusick prompt[i++] = c;
132834187Smckusick if (i >= PROMPTSIZE) {
132934187Smckusick printf("string too long\n");
133034187Smckusick error++;
133134187Smckusick break;
133234187Smckusick }
133334187Smckusick }
133434187Smckusick prompt[i] = '\0';
133534187Smckusick continue;
133634187Smckusick }
133734187Smckusick goto bad_syntax;
133857998Sralph
133934187Smckusick case 'q':
134034187Smckusick if (!colon)
134134187Smckusick goto no_colon;
134234187Smckusick if (match("quit", 1)) { /* quit */
134334187Smckusick if ((c = getachar()) != '\n') {
134434187Smckusick error++;
134534187Smckusick continue;
134634187Smckusick }
134734187Smckusick exit(0);
134834187Smckusick }
134934187Smckusick goto bad_syntax;
135034187Smckusick
135134187Smckusick case 's':
135234187Smckusick if (colon)
135334187Smckusick colon = 0;
135434187Smckusick else
135534187Smckusick goto no_colon;
135634187Smckusick if (match("sb", 2)) { /* super block */
135734187Smckusick if (c_count == 2) {
135834187Smckusick cur_cgrp = -1;
135934187Smckusick type = objsz = SB;
136034187Smckusick laststyle = '=';
136134187Smckusick lastpo = 's';
136234187Smckusick should_print = 1;
136334187Smckusick continue;
136434187Smckusick }
136534187Smckusick if (type == NUMB)
136634187Smckusick value = addr;
136734187Smckusick if (value > fs->fs_ncg - 1) {
136834187Smckusick printf("maximum super block is ");
136934187Smckusick print(fs->fs_ncg - 1, 8, -8, 0);
137034187Smckusick printf("\n");
137134187Smckusick error++;
137234187Smckusick continue;
137334187Smckusick }
137434187Smckusick type = objsz = SB;
137534187Smckusick cur_cgrp = value;
137634187Smckusick addr = cgsblock(fs, cur_cgrp) << FRGSHIFT;
137734187Smckusick continue;
137834187Smckusick }
137934187Smckusick if (match("sz", 2)) { /* file size */
138034187Smckusick acting_on_inode = 1;
138134187Smckusick should_print = 1;
138234187Smckusick addr = (long)
138334187Smckusick &((struct dinode *)cur_ino)->di_size;
138434187Smckusick value = get(LONG);
138534187Smckusick type = NULL;
138634187Smckusick continue;
138734187Smckusick }
138834187Smckusick goto bad_syntax;
138934187Smckusick
139034187Smckusick case 'u':
139134187Smckusick if (colon)
139234187Smckusick colon = 0;
139334187Smckusick else
139434187Smckusick goto no_colon;
139534187Smckusick if (match("uid", 1)) { /* user id */
139634187Smckusick acting_on_inode = 1;
139734187Smckusick should_print = 1;
139834187Smckusick addr = (long)
139934187Smckusick &((struct dinode *)cur_ino)->di_uid;
140034187Smckusick value = get(SHORT);
140134187Smckusick type = NULL;
140234187Smckusick continue;
140334187Smckusick }
140434187Smckusick goto bad_syntax;
140534187Smckusick
140634187Smckusick case 'F': /* buffer status (internal use only) */
140757998Sralph if (colon)
140834187Smckusick colon = 0;
140934187Smckusick else
141034187Smckusick goto no_colon;
141134187Smckusick for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd)
141257998Sralph printf("%8x %d\n", bp->blkno, bp->valid);
141334187Smckusick printf("\n");
141434187Smckusick printf("# commands\t\t%d\n", commands);
141534187Smckusick printf("# read requests\t\t%d\n", read_requests);
141634187Smckusick printf("# actual disk reads\t%d\n", actual_disk_reads);
141734187Smckusick continue;
141834187Smckusick no_colon:
141934187Smckusick printf("a colon should precede a command\n");
142034187Smckusick error++;
142134187Smckusick continue;
142234187Smckusick bad_syntax:
142334187Smckusick printf("more letters needed to distinguish command\n");
142434187Smckusick error++;
142534187Smckusick continue;
142634187Smckusick }
142734187Smckusick }
142834187Smckusick }
142934187Smckusick
143034187Smckusick /*
143134187Smckusick * getachar - get next character from input buffer.
143234187Smckusick */
143334187Smckusick char
getachar()143434187Smckusick getachar()
143534187Smckusick {
143634187Smckusick return(input_buffer[input_pointer++]);
143734187Smckusick }
143834187Smckusick
143934187Smckusick /*
144034187Smckusick * ungetachar - return character to input buffer.
144134187Smckusick */
ungetachar(c)144234187Smckusick ungetachar(c)
144334187Smckusick register char c;
144434187Smckusick {
144534187Smckusick if (input_pointer == 0) {
144634187Smckusick printf("internal problem maintaining input buffer\n");
144734187Smckusick error++;
144834187Smckusick return;
144934187Smckusick }
145034187Smckusick input_buffer[--input_pointer] = c;
145134187Smckusick }
145234187Smckusick
145334187Smckusick /*
145434187Smckusick * getnextinput - display the prompt and read an input line.
145534187Smckusick * An input line is up to 128 characters terminated by the newline
145634187Smckusick * character. Handle overflow, shell escape, and eof.
145734187Smckusick */
getnextinput()145834187Smckusick getnextinput()
145934187Smckusick {
146034187Smckusick register int i;
146134187Smckusick register char c;
146234187Smckusick register short pid, rpid;
146334187Smckusick int retcode;
146434187Smckusick
146534187Smckusick newline:
146634187Smckusick i = 0;
146734187Smckusick printf("%s", prompt);
146834187Smckusick ignore_eol:
146934187Smckusick while ((c = getc(stdin)) != '\n' && !(c == '!' && i == 0) &&
147034187Smckusick !feof(stdin) && i <= INPUTBUFFER - 2)
147134187Smckusick input_buffer[i++] = c;
147234187Smckusick if (input_buffer[i - 1] == '\\') {
147334187Smckusick input_buffer[i++] = c;
147434187Smckusick goto ignore_eol;
147534187Smckusick }
147634187Smckusick if (feof(stdin)) {
147734187Smckusick printf("\n");
147834187Smckusick exit(0);
147934187Smckusick }
148034187Smckusick if (c == '!') {
148134187Smckusick if ((pid = fork()) == 0) {
148237271Sbostic execl(_PATH_BSHELL, "sh", "-t", 0);
148334187Smckusick error++;
148434187Smckusick return;
148534187Smckusick }
148634187Smckusick while ((rpid = wait(&retcode)) != pid && rpid != -1)
148734187Smckusick ;
148834187Smckusick printf("!\n");
148934187Smckusick goto newline;
149034187Smckusick }
149134187Smckusick if (c != '\n')
149234187Smckusick printf("input truncated to 128 characters\n");
149334187Smckusick input_buffer[i] = '\n';
149434187Smckusick input_pointer = 0;
149534187Smckusick }
149634187Smckusick
149734187Smckusick /*
149834187Smckusick * eat_spaces - read extraneous spaces.
149934187Smckusick */
eat_spaces()150034187Smckusick eat_spaces()
150134187Smckusick {
150234187Smckusick register char c;
150334187Smckusick
150434187Smckusick while ((c = getachar()) == ' ')
150534187Smckusick ;
150634187Smckusick ungetachar(c);
150734187Smckusick }
150834187Smckusick
150934187Smckusick /*
151034187Smckusick * restore_inode - set up all inode indicators so inum is now
151134187Smckusick * the current inode.
151234187Smckusick */
restore_inode(inum)151334187Smckusick restore_inode(inum)
151434187Smckusick long inum;
151534187Smckusick {
151634187Smckusick errinum = cur_inum = inum;
151734187Smckusick addr = errino = cur_ino = itob(inum);
151834187Smckusick }
151934187Smckusick
152034187Smckusick /*
152134187Smckusick * match - return false if the input does not match string up to
152234187Smckusick * upto letters. Then proceed to chew up extraneous letters.
152334187Smckusick */
match(string,upto)152434187Smckusick match(string, upto)
152534187Smckusick register char *string;
152634187Smckusick register int upto;
152734187Smckusick {
152834187Smckusick register int i, length = strlen(string) - 1;
152934187Smckusick register char c;
153034187Smckusick int save_upto = upto;
153134187Smckusick
153234187Smckusick while (--upto) {
153334187Smckusick string++;
153434187Smckusick if ((c = getachar()) != *string) {
153534187Smckusick for (i = save_upto - upto; i; i--) {
153634187Smckusick ungetachar(c);
153734187Smckusick c = *--string;
153834187Smckusick }
153934187Smckusick return(0);
154034187Smckusick }
154134187Smckusick length--;
154234187Smckusick }
154334187Smckusick while (length--) {
154434187Smckusick string++;
154534187Smckusick if ((c = getachar()) != *string) {
154634187Smckusick ungetachar(c);
154734187Smckusick return(1);
154834187Smckusick }
154934187Smckusick }
155034187Smckusick return(1);
155134187Smckusick }
155234187Smckusick
155334187Smckusick /*
155434187Smckusick * expr - expression evaluator. Will evaluate expressions from
155534187Smckusick * left to right with no operator precedence. Parentheses may
155634187Smckusick * be used.
155734187Smckusick */
155834187Smckusick long
expr()155934187Smckusick expr()
156034187Smckusick {
156134187Smckusick register long numb = 0, temp;
156234187Smckusick register char c;
156334187Smckusick
156434187Smckusick numb = term();
156534187Smckusick for (;;) {
156634187Smckusick if (error)
156734187Smckusick return;
156834187Smckusick c = getachar();
156934187Smckusick switch (c) {
157034187Smckusick
157134187Smckusick case '+':
157234187Smckusick numb += term();
157334187Smckusick continue;
157434187Smckusick
157534187Smckusick case '-':
157634187Smckusick numb -= term();
157734187Smckusick continue;
157834187Smckusick
157934187Smckusick case '*':
158034187Smckusick numb *= term();
158134187Smckusick continue;
158234187Smckusick
158334187Smckusick case '%':
158434187Smckusick temp = term();
158534187Smckusick if (!temp) {
158634187Smckusick printf("divide by zero\n");
158734187Smckusick error++;
158834187Smckusick return;
158934187Smckusick }
159034187Smckusick numb /= temp;
159134187Smckusick continue;
159234187Smckusick
159334187Smckusick case ')':
159434187Smckusick paren--;
159534187Smckusick return(numb);
159634187Smckusick
159734187Smckusick default:
159834187Smckusick ungetachar(c);
159934187Smckusick if (paren && !error) {
160034187Smckusick printf("missing ')'\n");
160134187Smckusick error++;
160234187Smckusick }
160334187Smckusick return(numb);
160434187Smckusick }
160534187Smckusick }
160634187Smckusick }
160734187Smckusick
160834187Smckusick /*
160934187Smckusick * term - used by expression evaluator to get an operand.
161034187Smckusick */
161134187Smckusick long
term()161234187Smckusick term()
161334187Smckusick {
161434187Smckusick register char c;
161534187Smckusick
161634187Smckusick switch (c = getachar()) {
161734187Smckusick
161834187Smckusick default:
161934187Smckusick ungetachar(c);
162034187Smckusick
162134187Smckusick case '+':
162234187Smckusick return(getnumb());
162334187Smckusick
162434187Smckusick case '-':
162534187Smckusick return(-getnumb());
162634187Smckusick
162734187Smckusick case '(':
162834187Smckusick paren++;
162934187Smckusick return(expr());
163034187Smckusick }
163134187Smckusick }
163234187Smckusick
163334187Smckusick /*
163434187Smckusick * getnumb - read a number from the input stream. A leading
163534187Smckusick * zero signifies octal interpretation, a leading '0x'
163634187Smckusick * signifies hexadecimal, and a leading '0t' signifies
163734187Smckusick * decimal. If the first character is a character,
163834187Smckusick * return an error.
163934187Smckusick */
164034187Smckusick long
getnumb()164134187Smckusick getnumb()
164234187Smckusick {
164334187Smckusick
164434187Smckusick register char c, savec;
164534187Smckusick long number = 0, tbase, num;
164634187Smckusick extern short error;
164734187Smckusick
164834187Smckusick c = getachar();
164934187Smckusick if (!digit(c)) {
165034187Smckusick error++;
165134187Smckusick ungetachar(c);
165234187Smckusick return(-1);
165334187Smckusick }
165434187Smckusick if (c == '0') {
165534187Smckusick tbase = OCTAL;
165634187Smckusick if ((c = getachar()) == 'x')
165734187Smckusick tbase = HEX;
165834187Smckusick else if (c == 't')
165934187Smckusick tbase = DECIMAL;
166034187Smckusick else ungetachar(c);
166134187Smckusick } else {
166234187Smckusick tbase = base;
166334187Smckusick ungetachar(c);
166434187Smckusick }
166534187Smckusick for (;;) {
166634187Smckusick num = tbase;
166734187Smckusick c = savec = getachar();
166834187Smckusick if (HEXLETTER(c))
166934187Smckusick c = uppertolower(c);
167034187Smckusick switch (tbase) {
167134187Smckusick case HEX:
167234187Smckusick if (hexletter(c)) {
167334187Smckusick num = hextodigit(c);
167434187Smckusick break;
167534187Smckusick }
167634187Smckusick case DECIMAL:
167734187Smckusick if (digit(c))
167834187Smckusick num = numtodigit(c);
167934187Smckusick break;
168034187Smckusick case OCTAL:
168134187Smckusick if (octaldigit(c))
168234187Smckusick num = numtodigit(c);
168334187Smckusick }
168434187Smckusick if (num == tbase)
168534187Smckusick break;
168634187Smckusick number = number * tbase + num;
168734187Smckusick }
168834187Smckusick ungetachar(savec);
168934187Smckusick return(number);
169034187Smckusick }
169134187Smckusick
169234187Smckusick /*
169334187Smckusick * find - the syntax is almost identical to the unix command.
169434187Smckusick * find dir [-name pattern] [-inum number]
169534187Smckusick * Note: only one of -name or -inum may be used at a time.
169634187Smckusick * Also, the -print is not needed (implied).
169734187Smckusick */
find()169834187Smckusick find()
169934187Smckusick {
170034187Smckusick register struct filenames *fn;
170134187Smckusick register char c;
170234187Smckusick long temp;
170334187Smckusick short mode;
170434187Smckusick
170534187Smckusick eat_spaces();
170634187Smckusick temp = cur_inum;
170734187Smckusick top = filenames - 1;
170834187Smckusick doing_cd = 1;
170934187Smckusick parse();
171034187Smckusick doing_cd = 0;
171134187Smckusick if (nfiles != 1) {
171234187Smckusick restore_inode(temp);
171334187Smckusick if (!error) {
171434187Smckusick print_path(input_path, input_pathp);
171534187Smckusick if (nfiles == 0)
171634187Smckusick printf(" not found\n");
171734187Smckusick else
171834187Smckusick printf(" ambiguous\n");
171934187Smckusick error++;
172034187Smckusick return;
172134187Smckusick }
172234187Smckusick }
172334187Smckusick restore_inode(filenames->ino);
172434187Smckusick freemem(filenames, nfiles);
172534187Smckusick nfiles = 0;
172634187Smckusick top = filenames - 1;
172734187Smckusick if ((mode = icheck(addr)) == 0)
172834187Smckusick return;
172934187Smckusick if ((mode & IFMT) != IFDIR) {
173034187Smckusick print_path(input_path, input_pathp);
173134187Smckusick printf(" not a directory\n");
173234187Smckusick error++;
173334187Smckusick return;
173434187Smckusick }
173534187Smckusick eat_spaces();
173634187Smckusick if ((c = getachar()) != '-') {
173734187Smckusick printf("missing '-'\n");
173834187Smckusick error++;
173934187Smckusick return;
174034187Smckusick }
174134187Smckusick find_by_name = find_by_inode = 0;
174234187Smckusick c = getachar();
174334187Smckusick if (match("name", 4)) {
174434187Smckusick eat_spaces();
174534187Smckusick find_by_name = 1;
174634187Smckusick } else if (match("inum", 4)) {
174734187Smckusick eat_spaces();
174834187Smckusick find_ino = expr();
174934187Smckusick if (error)
175034187Smckusick return;
175134187Smckusick while ((c = getachar()) != '\n')
175234187Smckusick ;
175334187Smckusick ungetachar(c);
175434187Smckusick find_by_inode = 1;
175534187Smckusick } else {
175634187Smckusick printf("use -name or -inum with find\n");
175734187Smckusick error++;
175834187Smckusick return;
175934187Smckusick }
176034187Smckusick doing_find = 1;
176134187Smckusick parse();
176234187Smckusick doing_find = 0;
176334187Smckusick if (error) {
176434187Smckusick restore_inode(temp);
176534187Smckusick return;
176634187Smckusick }
176734187Smckusick for (fn = filenames; fn <= top; fn++) {
176834187Smckusick if (fn->find == 0)
176934187Smckusick continue;
177034187Smckusick printf("i#: ");
177134187Smckusick print(fn->ino, 12, -8, 0);
177234187Smckusick print_path(fn->fname, fn->len);
177334187Smckusick printf("\n");
177434187Smckusick }
177534187Smckusick restore_inode(temp);
177634187Smckusick }
177734187Smckusick
177834187Smckusick /*
177934187Smckusick * ls - do an ls. Should behave exactly as ls(1).
178034187Smckusick * Only -R and -l is supported and -l gives different results.
178134187Smckusick */
178234187Smckusick ls(fn0, fnlast, level)
178334187Smckusick struct filenames *fn0, *fnlast;
178434187Smckusick short level;
178534187Smckusick {
178634187Smckusick register struct filenames *fn, *fnn;
178734187Smckusick register int i;
178834187Smckusick int fcmp();
178934187Smckusick
179034187Smckusick fn = fn0;
179134187Smckusick for (;;) {
179234187Smckusick fn0 = fn;
179334187Smckusick if (fn0->len) {
179434187Smckusick cmp_level = level;
179534187Smckusick qsort((char *)fn0, fnlast - fn0 + 1,
179634187Smckusick sizeof (struct filenames), fcmp);
179734187Smckusick }
179834187Smckusick for (fnn = fn, fn++; fn <= fnlast; fnn = fn, fn++) {
179934187Smckusick if (fnn->len != fn->len && level == fnn->len - 1)
180034187Smckusick break;
180134187Smckusick if (fnn->len == 0)
180234187Smckusick continue;
180334187Smckusick if (strcmp(fn->fname[level], fnn->fname[level]))
180434187Smckusick break;
180534187Smckusick }
180634187Smckusick if (fn0->len && level != fn0->len - 1)
180734187Smckusick ls(fn0, fnn, level + 1);
180834187Smckusick else {
180934187Smckusick if (fn0 != filenames)
181034187Smckusick printf("\n");
181134187Smckusick print_path(fn0->fname, fn0->len - 1);
181234187Smckusick printf(":\n");
181334187Smckusick if (fn0->len == 0)
181434187Smckusick cmp_level = level;
181534187Smckusick else
181634187Smckusick cmp_level = level + 1;
181734187Smckusick qsort((char *)fn0, fnn - fn0 + 1,
181834187Smckusick sizeof (struct filenames), fcmp);
181934187Smckusick formatf(fn0, fnn);
182034187Smckusick nfiles -= fnn - fn0 + 1;
182134187Smckusick }
182234187Smckusick if (fn > fnlast)
182334187Smckusick return;
182434187Smckusick }
182534187Smckusick }
182634187Smckusick
182734187Smckusick /*
182834187Smckusick * formatf - code lifted from ls.
182934187Smckusick */
formatf(fn0,fnlast)183034187Smckusick formatf(fn0, fnlast)
183134187Smckusick register struct filenames *fn0, *fnlast;
183234187Smckusick {
183334187Smckusick register struct filenames *fn;
183434187Smckusick int width = 0, w, nentry = fnlast - fn0 + 1;
183534187Smckusick int i, j, columns, lines;
183634187Smckusick char *cp;
183734187Smckusick
183834187Smckusick if (long_list) {
183934187Smckusick columns = 1;
184034187Smckusick } else {
184134187Smckusick for (fn = fn0; fn <= fnlast; fn++) {
184234187Smckusick int len = strlen(fn->fname[cmp_level]) + 2;
184334187Smckusick
184434187Smckusick if (len > width)
184534187Smckusick width = len;
184634187Smckusick }
184734187Smckusick width = (width + 8) &~ 7;
184834187Smckusick columns = 80 / width;
184934187Smckusick if (columns == 0)
185034187Smckusick columns = 1;
185134187Smckusick }
185234187Smckusick lines = (nentry + columns - 1) / columns;
185334187Smckusick for (i = 0; i < lines; i++) {
185434187Smckusick for (j = 0; j < columns; j++) {
185534187Smckusick fn = fn0 + j * lines + i;
185634187Smckusick if (long_list) {
185734187Smckusick printf("i#: ");
185834187Smckusick print(fn->ino, 12, -8, 0);
185934187Smckusick }
186034187Smckusick cp = fmtentry(fn);
186134187Smckusick printf("%s", cp);
186234187Smckusick if (fn + lines > fnlast) {
186334187Smckusick printf("\n");
186434187Smckusick break;
186534187Smckusick }
186634187Smckusick w = strlen(cp);
186734187Smckusick while (w < width) {
186834187Smckusick w = (w + 8) &~ 7;
186934187Smckusick putchar('\t');
187034187Smckusick }
187134187Smckusick }
187234187Smckusick }
187334187Smckusick }
187434187Smckusick
187534187Smckusick /*
187634187Smckusick * fmtentry - code lifted from ls.
187734187Smckusick */
187834187Smckusick char *
fmtentry(fn)187934187Smckusick fmtentry(fn)
188034187Smckusick register struct filenames *fn;
188134187Smckusick {
188234187Smckusick static char fmtres[BUFSIZ];
188334187Smckusick register struct dinode *ip;
188434187Smckusick register char *cptr, *cp, *dp;
188534187Smckusick
188634187Smckusick dp = &fmtres[0];
188734187Smckusick for (cp = fn->fname[cmp_level]; *cp; cp++) {
188834187Smckusick if (*cp < ' ' || *cp >= 0177)
188934187Smckusick *dp++ = '?';
189034187Smckusick else
189134187Smckusick *dp++ = *cp;
189234187Smckusick }
189334187Smckusick addr = itob(fn->ino);
189434187Smckusick if ((cptr = getblk(addr)) == 0)
189534187Smckusick return(NULL);
189634187Smckusick cptr += blkoff(fs, addr);
189734187Smckusick ip = (struct dinode *)cptr;
189834187Smckusick switch (ip->di_mode & IFMT) {
189934187Smckusick case IFDIR:
190034187Smckusick *dp++ = '/';
190134187Smckusick break;
190234187Smckusick case IFLNK:
190334187Smckusick *dp++ = '@';
190434187Smckusick break;
190534187Smckusick case IFSOCK:
190634187Smckusick *dp++ = '=';
190734187Smckusick break;
190836249Smckusick #ifdef IFIFO
190936249Smckusick case IFIFO:
191036249Smckusick *dp++ = 'p';
191136249Smckusick break;
191236249Smckusick #endif
191334187Smckusick case IFCHR:
191434187Smckusick case IFBLK:
191534187Smckusick case IFREG:
191634187Smckusick if (ip->di_mode & 0111)
191734187Smckusick *dp++ = '*';
191834187Smckusick else
191934187Smckusick *dp++ = ' ';
192034187Smckusick break;
192134187Smckusick default:
192234187Smckusick *dp++ = '?';
192334187Smckusick
192434187Smckusick }
192534187Smckusick *dp++ = 0;
192634187Smckusick return (fmtres);
192734187Smckusick }
192834187Smckusick
192934187Smckusick /*
193034187Smckusick * fcmp - routine used by qsort. Will sort first by name, then
193134187Smckusick * then by pathname length if names are equal. Uses global
193234187Smckusick * cmp_level to tell what component of the path name we are comparing.
193334187Smckusick */
fcmp(f1,f2)193434187Smckusick fcmp(f1, f2)
193534187Smckusick register struct filenames *f1, *f2;
193634187Smckusick {
193734187Smckusick int value;
193834187Smckusick
193934187Smckusick if ((value = strcmp(f1->fname[cmp_level], f2->fname[cmp_level])))
194034187Smckusick return(value);
194134187Smckusick return (f1->len - f2->len);
194234187Smckusick }
194334187Smckusick
194434187Smckusick /*
194534187Smckusick * ffcmp - routine used by qsort. Sort only by pathname length.
194634187Smckusick */
ffcmp(f1,f2)194734187Smckusick ffcmp(f1, f2)
194834187Smckusick register struct filenames *f1, *f2;
194934187Smckusick {
195034187Smckusick return (f1->len - f2->len);
195134187Smckusick }
195234187Smckusick
195334187Smckusick /*
195434187Smckusick * parse - set up the call to follow_path.
195534187Smckusick */
parse()195634187Smckusick parse()
195734187Smckusick {
195834187Smckusick register int i, j;
195934187Smckusick char c;
196034187Smckusick
196134187Smckusick stack_pathp = input_pathp = -1;
196234187Smckusick if ((c = getachar()) == '/') {
196334187Smckusick while ((c = getachar()) == '/')
196434187Smckusick ;
196534187Smckusick ungetachar(c);
196634187Smckusick cur_inum = 2;
196734187Smckusick if ((c = getachar()) == '\n') {
196834187Smckusick ungetachar('\n');
196934187Smckusick if (doing_cd) {
197034187Smckusick top++;
197134187Smckusick top->ino = 2;
197234187Smckusick top->len = -1;
197334187Smckusick nfiles = 1;
197434187Smckusick return;
197534187Smckusick }
197634187Smckusick } else
197734187Smckusick ungetachar(c);
197834187Smckusick } else {
197934187Smckusick ungetachar(c);
198034187Smckusick stack_pathp = current_pathp;
198134187Smckusick if (!doing_find)
198234187Smckusick input_pathp = current_pathp;
198334187Smckusick for (i = 0; i <= current_pathp; i++) {
198434187Smckusick if (!doing_find)
198534187Smckusick strcpy(input_path[i], current_path[i]);
198634187Smckusick strcpy(stack_path[i], current_path[i]);
198734187Smckusick }
198834187Smckusick }
198934187Smckusick getname();
199034187Smckusick follow_path(stack_pathp + 1, cur_inum);
199134187Smckusick }
199234187Smckusick
199334187Smckusick /*
199434187Smckusick * follow_path - called by cd, find, and ls.
199534187Smckusick * input_path holds the name typed by the user.
199634187Smckusick * stack_path holds the name at the current depth.
199734187Smckusick */
follow_path(level,inum)199834187Smckusick follow_path(level, inum)
199934187Smckusick long level, inum;
200034187Smckusick {
200134187Smckusick register struct direct *dirp;
200234187Smckusick register char **ccptr, *cptr, c;
200334187Smckusick register int i;
200434187Smckusick struct filenames *tos, *bos, *fn, *fnn, *fnnn;
200534187Smckusick long block;
200634187Smckusick short mode;
200734187Smckusick
200834187Smckusick tos = top + 1;
200934187Smckusick restore_inode(inum);
201034187Smckusick if ((mode = icheck(addr)) == 0)
201134187Smckusick return;
201234187Smckusick if ((mode & IFMT) != IFDIR)
201334187Smckusick return;
201434187Smckusick block = cur_bytes = 0;
201534187Smckusick while (cur_bytes < filesize) {
201634187Smckusick if (block == 0 || bcomp(addr)) {
201734187Smckusick error = 0;
201834187Smckusick if ((addr = (bmap(block++) << FRGSHIFT)) == 0)
201934187Smckusick break;
202034187Smckusick if ((cptr = getblk(addr)) == 0)
202134187Smckusick break;
202234187Smckusick cptr += blkoff(fs, addr);
202334187Smckusick }
202434187Smckusick dirp = (struct direct *)cptr;
202534187Smckusick if (dirp->d_ino) {
202634187Smckusick if (level > input_pathp || doing_find ||
202734187Smckusick compare(input_path[level], &dirp->d_name[0], 1)) {
202834187Smckusick if (++top - filenames >= MAXFILES) {
202934187Smckusick printf("too many files\n");
203034187Smckusick error++;
203134187Smckusick return;
203234187Smckusick }
203334187Smckusick top->fname = (char **)calloc(FIRST_DEPTH, sizeof (char **));
203434187Smckusick top->flag = 0;
203534187Smckusick if (top->fname == 0) {
203634187Smckusick printf("out of memory\n");
203734187Smckusick error++;
203834187Smckusick return;
203934187Smckusick }
204034187Smckusick nfiles++;
204134187Smckusick top->ino = dirp->d_ino;
204234187Smckusick top->len = stack_pathp;
204334187Smckusick top->find = 0;
204434187Smckusick if (doing_find) {
204534187Smckusick if (find_by_name) {
204634187Smckusick if (compare(input_path[0], &dirp->d_name[0], 1))
204734187Smckusick top->find = 1;
204834187Smckusick } else if (find_by_inode)
204934187Smckusick if (find_ino == dirp->d_ino)
205034187Smckusick top->find = 1;
205134187Smckusick }
205234187Smckusick if (top->len + 1 >= FIRST_DEPTH && top->flag == 0) {
205334187Smckusick ccptr = (char **)calloc(SECOND_DEPTH, sizeof (char **));
205434187Smckusick if (ccptr == 0) {
205534187Smckusick printf("out of memory\n");
205634187Smckusick error++;
205734187Smckusick return;
205834187Smckusick }
205934187Smckusick for (i = 0; i < FIRST_DEPTH; i++)
206034187Smckusick ccptr[i] = top->fname[i];
206134187Smckusick free((char *)top->fname);
206234187Smckusick top->fname = ccptr;
206334187Smckusick top->flag = 1;
206434187Smckusick }
206534187Smckusick if (top->len >= SECOND_DEPTH) {
206634187Smckusick printf("maximum depth exceeded, try to cd lower\n");
206734187Smckusick error++;
206834187Smckusick return;
206934187Smckusick }
207034187Smckusick /*
207134187Smckusick * Copy current depth.
207234187Smckusick */
207334187Smckusick for (i = 0; i <= stack_pathp; i++) {
207434187Smckusick top->fname[i]=calloc(1, strlen(stack_path[i])+1);
207534187Smckusick if (top->fname[i] == 0) {
207634187Smckusick printf("out of memory\n");
207734187Smckusick error++;
207834187Smckusick return;
207934187Smckusick }
208034187Smckusick strcpy(top->fname[i], stack_path[i]);
208134187Smckusick }
208234187Smckusick /*
208334187Smckusick * Check for '.' or '..' typed.
208434187Smckusick */
208534187Smckusick if ((level <= input_pathp) &&
208634187Smckusick (strcmp(input_path[level], ".") == 0 ||
208734187Smckusick strcmp(input_path[level], "..") == 0)) {
208857998Sralph if (strcmp(input_path[level], "..") == 0 &&
208934187Smckusick top->len >= 0) {
209034187Smckusick free(top->fname[top->len]);
209134187Smckusick top->len -= 1;
209234187Smckusick }
209334187Smckusick } else {
209434187Smckusick /*
209534187Smckusick * Check for duplicates.
209634187Smckusick */
209734187Smckusick if (!doing_cd && !doing_find) {
209834187Smckusick for (fn = filenames; fn < top; fn++) {
209934187Smckusick if (fn->ino == dirp->d_ino &&
210034187Smckusick fn->len == stack_pathp + 1) {
210134187Smckusick for (i = 0; i < fn->len; i++)
210234187Smckusick if (strcmp(fn->fname[i], stack_path[i]))
210334187Smckusick break;
210434187Smckusick if (i != fn->len ||
210534187Smckusick strcmp(fn->fname[i], dirp->d_name))
210634187Smckusick continue;
210734187Smckusick freemem(top, 1);
210834187Smckusick if (top == filenames)
210934187Smckusick top = NULL;
211034187Smckusick else
211134187Smckusick top--;
211234187Smckusick nfiles--;
211334187Smckusick goto duplicate;
211434187Smckusick }
211534187Smckusick }
211634187Smckusick }
211734187Smckusick top->len += 1;
211834187Smckusick top->fname[top->len] = calloc(1,
211934187Smckusick strlen(&dirp->d_name[0])+1);
212034187Smckusick if (top->fname[top->len] == 0) {
212134187Smckusick printf("out of memory\n");
212234187Smckusick error++;
212334187Smckusick return;
212434187Smckusick }
212534187Smckusick strcpy(top->fname[top->len], &dirp->d_name[0]);
212634187Smckusick }
212734187Smckusick }
212834187Smckusick }
212934187Smckusick duplicate:
213034187Smckusick addr += dirp->d_reclen;
213134187Smckusick cptr += dirp->d_reclen;
213234187Smckusick cur_bytes += dirp->d_reclen;
213334187Smckusick }
213434187Smckusick if (top < filenames)
213534187Smckusick return;
213634187Smckusick if ((doing_cd && level == input_pathp) ||
213734187Smckusick (!recursive && !doing_find && level > input_pathp))
213834187Smckusick return;
213934187Smckusick bos = top;
214034187Smckusick /*
214134187Smckusick * Check newly added entries to determine if further expansion
214234187Smckusick * is required.
214334187Smckusick */
214434187Smckusick for (fn = tos; fn <= bos; fn++) {
214534187Smckusick /*
214634187Smckusick * Avoid '.' and '..' if beyond input.
214734187Smckusick */
214834187Smckusick if ((recursive || doing_find) && (level > input_pathp) &&
214934187Smckusick (strcmp(fn->fname[fn->len], ".") == 0 ||
215034187Smckusick strcmp(fn->fname[fn->len], "..") == 0))
215134187Smckusick continue;
215234187Smckusick restore_inode(fn->ino);
215334187Smckusick if ((mode = icheck(cur_ino)) == 0)
215434187Smckusick return;
215534187Smckusick if ((mode & IFMT) == IFDIR || level < input_pathp) {
215634187Smckusick /*
215734187Smckusick * Set up current depth, remove current entry and
215834187Smckusick * continue recursion.
215934187Smckusick */
216034187Smckusick for (i = 0; i <= fn->len; i++)
216134187Smckusick strcpy(stack_path[i], fn->fname[i]);
216234187Smckusick stack_pathp = fn->len;
216334187Smckusick if (!doing_find &&
216434187Smckusick (!recursive || (recursive && level <= input_pathp))) {
216534187Smckusick /*
216634187Smckusick * Remove current entry by moving others up.
216734187Smckusick */
216834187Smckusick freemem(fn, 1);
216934187Smckusick fnn = fn;
217034187Smckusick for (fnnn = fnn, fnn++; fnn <= top; fnnn = fnn, fnn++) {
217134187Smckusick fnnn->ino = fnn->ino;
217234187Smckusick fnnn->len = fnn->len;
217334187Smckusick if (fnnn->len + 1 < FIRST_DEPTH) {
217434187Smckusick fnnn->fname = (char **)calloc(FIRST_DEPTH,
217534187Smckusick sizeof (char **));
217634187Smckusick fnnn->flag = 0;
217734187Smckusick } else if (fnnn->len < SECOND_DEPTH) {
217834187Smckusick fnnn->fname = (char **)calloc(SECOND_DEPTH,
217934187Smckusick sizeof (char **));
218034187Smckusick fnnn->flag = 1;
218134187Smckusick } else {
218234187Smckusick printf("maximum depth exceeded, ");
218334187Smckusick printf("try to cd lower\n");
218434187Smckusick error++;
218534187Smckusick return;
218634187Smckusick }
218734187Smckusick for (i = 0; i <= fnn->len; i++)
218834187Smckusick fnnn->fname[i] = fnn->fname[i];
218934187Smckusick }
219034187Smckusick if (fn == tos)
219134187Smckusick fn--;
219234187Smckusick top--;
219334187Smckusick bos--;
219434187Smckusick nfiles--;
219534187Smckusick }
219634187Smckusick follow_path(level + 1, cur_inum);
219734187Smckusick if (error)
219834187Smckusick return;
219934187Smckusick }
220034187Smckusick }
220134187Smckusick }
220234187Smckusick
220334187Smckusick /*
220434187Smckusick * getname - break up the pathname entered by the user into components.
220534187Smckusick */
getname()220634187Smckusick getname()
220734187Smckusick {
220834187Smckusick register int i;
220934187Smckusick char c;
221034187Smckusick
221134187Smckusick if ((c = getachar()) == '\n') {
221234187Smckusick ungetachar(c);
221334187Smckusick return;
221434187Smckusick }
221534187Smckusick ungetachar(c);
221634187Smckusick input_pathp++;
221734187Smckusick clear:
221834187Smckusick for (i = 0; i < MAXNAMLEN; i++)
221934187Smckusick input_path[input_pathp][i] = '\0';
222034187Smckusick for (;;) {
222134187Smckusick c = getachar();
222234187Smckusick if (c == '\\') {
222334187Smckusick if (strlen(input_path[input_pathp]) + 1 >= MAXNAMLEN) {
222434187Smckusick printf("maximum name length exceeded, ");
222534187Smckusick printf("truncating\n");
222634187Smckusick return;
222734187Smckusick }
222834187Smckusick input_path[input_pathp][strlen(input_path[input_pathp])] = c;
222934187Smckusick input_path[input_pathp][strlen(input_path[input_pathp])] =
223034187Smckusick getachar();
223134187Smckusick continue;
223234187Smckusick }
223334187Smckusick if (c == ' ' || c == '\n') {
223434187Smckusick ungetachar(c);
223534187Smckusick return;
223634187Smckusick }
223734187Smckusick if (!doing_find && c == '/') {
223834187Smckusick if (++input_pathp >= MAXPATHLEN) {
223934187Smckusick printf("maximum path length exceeded, ");
224034187Smckusick printf("truncating\n");
224134187Smckusick input_pathp--;
224234187Smckusick return;
224334187Smckusick }
224434187Smckusick goto clear;
224534187Smckusick }
224634187Smckusick if (strlen(input_path[input_pathp]) >= MAXNAMLEN) {
224734187Smckusick printf("maximum name length exceeded, truncating\n");
224834187Smckusick return;
224934187Smckusick }
225034187Smckusick input_path[input_pathp][strlen(input_path[input_pathp])] = c;
225134187Smckusick }
225234187Smckusick }
225334187Smckusick
225434187Smckusick /*
225534187Smckusick * compare - check if a filename matches the pattern entered by the user.
225634187Smckusick * Handles '*', '?', and '[]'.
225734187Smckusick */
compare(s1,s2,at_start)225834187Smckusick compare(s1, s2, at_start)
225934187Smckusick char *s1, *s2;
226034187Smckusick short at_start;
226134187Smckusick {
226234187Smckusick register char c, *s;
226334187Smckusick
226434187Smckusick s = s2;
226534187Smckusick while (c = *s1) {
226634187Smckusick if (c == '*') {
226734187Smckusick if (at_start && s == s2 && !letter(*s2) && !digit(*s2))
226834187Smckusick return(0);
226934187Smckusick if (*++s1 == 0)
227034187Smckusick return(1);
227134187Smckusick while (*s2) {
227234187Smckusick if (compare(s1, s2, 0))
227334187Smckusick return(1);
227434187Smckusick if (error)
227534187Smckusick return(0);
227634187Smckusick s2++;
227734187Smckusick }
227834187Smckusick }
227934187Smckusick if (*s2 == 0)
228034187Smckusick return(0);
228134187Smckusick if (c == '\\') {
228234187Smckusick s1++;
228334187Smckusick goto compare_chars;
228434187Smckusick }
228534187Smckusick if (c == '?') {
228634187Smckusick if (at_start && s == s2 && !letter(*s2) && !digit(*s2))
228734187Smckusick return(0);
228834187Smckusick s1++;
228934187Smckusick s2++;
229034187Smckusick continue;
229134187Smckusick }
229234187Smckusick if (c == '[') {
229334187Smckusick s1++;
229434187Smckusick if (*s2 >= *s1++) {
229534187Smckusick if (*s1++ != '-') {
229634187Smckusick printf("missing '-'\n");
229734187Smckusick error++;
229834187Smckusick return(0);
229934187Smckusick }
230034187Smckusick if (*s2 <= *s1++) {
230134187Smckusick if (*s1++ != ']') {
230234187Smckusick printf("missing ']'");
230334187Smckusick error++;
230434187Smckusick return(0);
230534187Smckusick }
230634187Smckusick s2++;
230734187Smckusick continue;
230834187Smckusick }
230934187Smckusick }
231034187Smckusick }
231134187Smckusick compare_chars:
231234187Smckusick if (*s1++ == *s2++)
231334187Smckusick continue;
231434187Smckusick else
231534187Smckusick return(0);
231634187Smckusick }
231734187Smckusick if (*s1 == *s2)
231834187Smckusick return(1);
231934187Smckusick return(0);
232034187Smckusick }
232134187Smckusick
232234187Smckusick /*
232334187Smckusick * freemem - free the memory allocated to the filenames structure.
232434187Smckusick */
232534187Smckusick freemem(p, numb)
232634187Smckusick struct filenames *p;
232734187Smckusick int numb;
232834187Smckusick {
232934187Smckusick register int i, j;
233034187Smckusick
233134187Smckusick if (numb == 0)
233234187Smckusick return;
233334187Smckusick for (i = 0; i < numb; i++, p++) {
233434187Smckusick for (j = 0; j <= p->len; j++)
233534187Smckusick free(p->fname[j]);
233634187Smckusick free((char *)p->fname);
233734187Smckusick }
233834187Smckusick }
233934187Smckusick
234034187Smckusick /*
234134187Smckusick * print_path - print the pathname held in p.
234234187Smckusick */
print_path(p,pntr)234334187Smckusick print_path(p, pntr)
234434187Smckusick char *p[];
234534187Smckusick short pntr;
234634187Smckusick {
234734187Smckusick register int i;
234834187Smckusick
234934187Smckusick printf("/");
235034187Smckusick if (pntr >= 0) {
235134187Smckusick for (i = 0; i < pntr; i++)
235234187Smckusick printf("%s/", p[i]);
235334187Smckusick printf("%s", p[pntr]);
235434187Smckusick }
235534187Smckusick }
235634187Smckusick
235734187Smckusick /*
235834187Smckusick * fill - fill a section with a value or string.
235934187Smckusick * addr,count:fill=[value, "string"].
236034187Smckusick */
fill()236134187Smckusick fill()
236234187Smckusick {
236334187Smckusick register char *cptr;
236434187Smckusick register int i;
236534187Smckusick short eof_flag, end = 0, eof = 0;
236634187Smckusick long temp, tcount, taddr;
236734187Smckusick
236834187Smckusick if (!wrtflag) {
236934187Smckusick printf("not opened for write '-w'\n");
237034187Smckusick error++;
237134187Smckusick return;
237234187Smckusick }
237334187Smckusick temp = expr();
237434187Smckusick if (error)
237534187Smckusick return;
237634187Smckusick if ((cptr = getblk(addr)) == 0)
237734187Smckusick return;
237834187Smckusick if (type == NUMB)
237934187Smckusick eof_flag = 0;
238034187Smckusick else
238134187Smckusick eof_flag = 1;
238234187Smckusick taddr = addr;
238334187Smckusick switch (objsz) {
238434187Smckusick case LONG:
238534187Smckusick addr &= ~(LONG - 1);
238634187Smckusick break;
238734187Smckusick case SHORT:
238834187Smckusick addr &= ~(SHORT - 1);
238934187Smckusick temp &= 0177777L;
239034187Smckusick break;
239134187Smckusick case CHAR:
239234187Smckusick temp &= 0377;
239334187Smckusick }
239434187Smckusick cur_bytes -= taddr - addr;
239534187Smckusick cptr += blkoff(fs, addr);
239634187Smckusick tcount = check_addr(eof_flag, &end, &eof, 0);
239734187Smckusick for (i = 0; i < tcount; i++) {
239834187Smckusick switch (objsz) {
239934187Smckusick case LONG:
240034187Smckusick *(long *)cptr = temp;
240134187Smckusick break;
240234187Smckusick case SHORT:
240334187Smckusick *(short *)cptr = temp;
240434187Smckusick break;
240534187Smckusick case CHAR:
240634187Smckusick *cptr = temp;
240734187Smckusick }
240834187Smckusick cptr += objsz;
240934187Smckusick }
241034187Smckusick addr += (tcount - 1) * objsz;
241134187Smckusick cur_bytes += (tcount - 1) * objsz;
241234187Smckusick put(temp, objsz);
241334187Smckusick if (eof) {
241434187Smckusick printf("end of file\n");
241534187Smckusick error++;
241634187Smckusick } else if (end) {
241734187Smckusick printf("end of block\n");
241834187Smckusick error++;
241934187Smckusick }
242034187Smckusick }
242157998Sralph
242234187Smckusick /*
242334187Smckusick * get - read a byte, short or long from the file system.
242434187Smckusick * The entire block containing the desired item is read
242557998Sralph * and the appropriate data is extracted and returned.
242634187Smckusick */
242734187Smckusick long
get(lngth)242834187Smckusick get(lngth)
242934187Smckusick short lngth;
243034187Smckusick {
243134187Smckusick
243234187Smckusick register char *bptr;
243334187Smckusick long temp = addr;
243434187Smckusick
243534187Smckusick objsz = lngth;
243634187Smckusick if (objsz == INODE || objsz == SHORT)
243734187Smckusick temp &= ~(SHORT - 1);
243834187Smckusick else if (objsz == DIRECTORY || objsz == LONG)
243934187Smckusick temp &= ~(LONG - 1);
244034187Smckusick if ((bptr = getblk(temp)) == 0)
244134187Smckusick return(-1);
244234187Smckusick bptr += blkoff(fs, temp);
244334187Smckusick switch (objsz) {
244434187Smckusick case CHAR:
244534187Smckusick return((long)*bptr);
244634187Smckusick case SHORT:
244734187Smckusick case INODE:
244834187Smckusick return((long)(*(short *)bptr));
244934187Smckusick case LONG:
245034187Smckusick case DIRECTORY:
245134187Smckusick return(*(long *)bptr);
245234187Smckusick }
245334187Smckusick return(0);
245434187Smckusick }
245534187Smckusick
245634187Smckusick /*
245734187Smckusick * cgrp_check - make sure that we don't bump the cylinder group
245834187Smckusick * beyond the total number of cylinder groups or before the start.
245934187Smckusick */
cgrp_check(cgrp)246034187Smckusick cgrp_check(cgrp)
246134187Smckusick long cgrp;
246234187Smckusick {
246334187Smckusick if (cgrp < 0) {
246434187Smckusick if (objsz == CGRP)
246534187Smckusick printf("beginning of cylinder groups\n");
246634187Smckusick else
246734187Smckusick printf("beginning of super blocks\n");
246834187Smckusick error++;
246934187Smckusick return(0);
247034187Smckusick }
247134187Smckusick if (cgrp >= fs->fs_ncg) {
247234187Smckusick if (objsz == CGRP)
247334187Smckusick printf("end of cylinder groups\n");
247434187Smckusick else
247534187Smckusick printf("end of super blocks\n");
247634187Smckusick error++;
247734187Smckusick return(0);
247834187Smckusick }
247934187Smckusick if (objsz == CGRP)
248034187Smckusick return(cgtod(fs, cgrp) << FRGSHIFT);
248134187Smckusick else
248234187Smckusick return(cgsblock(fs, cgrp) << FRGSHIFT);
248334187Smckusick }
248434187Smckusick
248534187Smckusick /*
248634187Smckusick * icheck - make sure we can read the block containing the inode
248734187Smckusick * and determine the filesize (0 if inode not allocated). Return
248834187Smckusick * 0 if error otherwise return the mode.
248934187Smckusick */
icheck(address)249034187Smckusick icheck(address)
249134187Smckusick long address;
249234187Smckusick {
249334187Smckusick register char *cptr;
249434187Smckusick register struct dinode *ip;
249534187Smckusick
249634187Smckusick if ((cptr = getblk(address)) == 0)
249734187Smckusick return(0);
249834187Smckusick cptr += blkoff(fs, address);
249934187Smckusick ip = (struct dinode *)cptr;
250034187Smckusick if ((ip->di_mode & IFMT) == 0) {
250134187Smckusick if (!override) {
250234187Smckusick printf("inode not allocated\n");
250334187Smckusick error++;
250434187Smckusick return(0);
250534187Smckusick }
250634187Smckusick blocksize = filesize = 0;
250734187Smckusick } else {
250834187Smckusick trapped++;
250934187Smckusick filesize = ip->di_size;
251034187Smckusick blocksize = filesize * 2;
251134187Smckusick }
251234187Smckusick return(ip->di_mode);
251334187Smckusick }
251434187Smckusick
251534187Smckusick /*
251634187Smckusick * getdirslot - get the address of the directory slot desired.
251734187Smckusick */
getdirslot(slot)251834187Smckusick getdirslot(slot)
251934187Smckusick short slot;
252034187Smckusick {
252134187Smckusick register char *cptr;
252234187Smckusick register struct direct *dirp;
252334187Smckusick register short i;
252434187Smckusick char *string = &scratch[0];
252534187Smckusick short bod = 0, mode, temp;
252634187Smckusick
252734187Smckusick if (slot < 0) {
252834187Smckusick slot = 0;
252934187Smckusick bod++;
253034187Smckusick }
253134187Smckusick if (type != DIRECTORY) {
253234187Smckusick if (type == BLOCK)
253334187Smckusick string = "block";
253434187Smckusick else
253534187Smckusick string = "fragment";
253634187Smckusick addr = bod_addr;
253734187Smckusick if ((cptr = getblk(addr)) == 0)
253834187Smckusick return(0);
253934187Smckusick cptr += blkoff(fs, addr);
254034187Smckusick cur_bytes = 0;
254134187Smckusick dirp = (struct direct *)cptr;
254234187Smckusick for (dirslot = 0; dirslot < slot; dirslot++) {
254334187Smckusick dirp = (struct direct *)cptr;
254434187Smckusick if (blocksize > filesize) {
254534187Smckusick if (cur_bytes + dirp->d_reclen >= filesize) {
254634187Smckusick printf("end of file\n");
254734187Smckusick erraddr = addr;
254834187Smckusick errcur_bytes = cur_bytes;
254934187Smckusick stringsize = STRINGSIZE(dirp);
255034187Smckusick error++;
255134187Smckusick return(addr);
255234187Smckusick }
255334187Smckusick } else {
255434187Smckusick if (cur_bytes + dirp->d_reclen >= blocksize) {
255534187Smckusick printf("end of %s\n", string);
255634187Smckusick erraddr = addr;
255734187Smckusick errcur_bytes = cur_bytes;
255834187Smckusick stringsize = STRINGSIZE(dirp);
255934187Smckusick error++;
256034187Smckusick return(addr);
256134187Smckusick }
256234187Smckusick }
256334187Smckusick cptr += dirp->d_reclen;
256434187Smckusick addr += dirp->d_reclen;
256534187Smckusick cur_bytes += dirp->d_reclen;
256634187Smckusick }
256734187Smckusick if (bod) {
256834187Smckusick if (blocksize > filesize)
256934187Smckusick printf("beginning of file\n");
257034187Smckusick else
257134187Smckusick printf("beginning of %s\n", string);
257234187Smckusick erraddr = addr;
257334187Smckusick errcur_bytes = cur_bytes;
257434187Smckusick error++;
257534187Smckusick }
257634187Smckusick stringsize = STRINGSIZE(dirp);
257734187Smckusick return(addr);
257834187Smckusick } else {
257934187Smckusick addr = cur_ino;
258034187Smckusick if ((mode = icheck(addr)) == 0)
258134187Smckusick return(0);
258234187Smckusick if (!override && (mode & IFDIR) == 0) {
258334187Smckusick printf("inode is not a directory\n");
258434187Smckusick error++;
258534187Smckusick return(0);
258634187Smckusick }
258734187Smckusick temp = slot;
258834187Smckusick i = cur_bytes = 0;
258934187Smckusick for (;;) {
259034187Smckusick if (i == 0 || bcomp(addr)) {
259134187Smckusick error = 0;
259234187Smckusick if ((addr=(bmap(i++) << FRGSHIFT)) == 0)
259334187Smckusick break;
259434187Smckusick if ((cptr = getblk(addr)) == 0)
259534187Smckusick break;
259634187Smckusick cptr += blkoff(fs, addr);
259734187Smckusick }
259834187Smckusick dirp = (struct direct *)cptr;
259934187Smckusick value = dirp->d_ino;
260034187Smckusick if (!temp--)
260134187Smckusick break;
260234187Smckusick if (cur_bytes + dirp->d_reclen >= filesize) {
260334187Smckusick printf("end of file\n");
260434187Smckusick dirslot = slot - temp - 1;
260534187Smckusick objsz = DIRECTORY;
260634187Smckusick erraddr = addr;
260734187Smckusick errcur_bytes = cur_bytes;
260834187Smckusick stringsize = STRINGSIZE(dirp);
260934187Smckusick error++;
261034187Smckusick return(addr);
261134187Smckusick }
261234187Smckusick addr += dirp->d_reclen;
261334187Smckusick cptr += dirp->d_reclen;
261434187Smckusick cur_bytes += dirp->d_reclen;
261534187Smckusick }
261634187Smckusick dirslot = slot;
261734187Smckusick objsz = DIRECTORY;
261834187Smckusick if (bod) {
261934187Smckusick printf("beginning of file\n");
262034187Smckusick erraddr = addr;
262134187Smckusick errcur_bytes = cur_bytes;
262234187Smckusick error++;
262334187Smckusick }
262434187Smckusick stringsize = STRINGSIZE(dirp);
262534187Smckusick return(addr);
262634187Smckusick }
262734187Smckusick }
262834187Smckusick
262934187Smckusick /*
263034187Smckusick * putf - print a byte as an ascii character if possible.
263134187Smckusick * The exceptions are tabs, newlines, backslashes
263234187Smckusick * and nulls which are printed as the standard C
263334187Smckusick * language escapes. Characters which are not
263434187Smckusick * recognized are printed as \?.
263534187Smckusick */
putf(c)263634187Smckusick putf(c)
263734187Smckusick register char c;
263834187Smckusick {
263934187Smckusick
264034187Smckusick if (c<=037 || c>=0177 || c=='\\') {
264134187Smckusick printf("\\");
264234187Smckusick switch (c) {
264334187Smckusick case '\\':
264434187Smckusick printf("\\");
264534187Smckusick break;
264634187Smckusick case '\t':
264734187Smckusick printf("t");
264834187Smckusick break;
264934187Smckusick case '\n':
265034187Smckusick printf("n");
265134187Smckusick break;
265234187Smckusick case '\0':
265334187Smckusick printf("0");
265434187Smckusick break;
265534187Smckusick default:
265634187Smckusick printf("?");
265734187Smckusick }
265834187Smckusick }
265934187Smckusick else {
266034187Smckusick printf("%c", c);
266134187Smckusick printf(" ");
266234187Smckusick }
266334187Smckusick }
266434187Smckusick
266534187Smckusick /*
266634187Smckusick * put - write an item into the buffer for the current address
266734187Smckusick * block. The value is checked to make sure that it will
266834187Smckusick * fit in the size given without truncation. If successful,
266934187Smckusick * the entire block is written back to the file system.
267034187Smckusick */
put(item,lngth)267157998Sralph put(item, lngth)
267234187Smckusick long item;
267334187Smckusick short lngth;
267434187Smckusick {
267534187Smckusick
267634187Smckusick register char *bptr, *sbptr;
267734187Smckusick register long *vptr;
267857998Sralph off_t s_err;
267957998Sralph long nbytes;
268034187Smckusick long olditem;
268134187Smckusick
268234187Smckusick if (!wrtflag) {
268334187Smckusick printf("not opened for write '-w'\n");
268434187Smckusick error++;
268534187Smckusick return;
268634187Smckusick }
268734187Smckusick objsz = lngth;
268834187Smckusick if ((sbptr = getblk(addr)) == 0)
268934187Smckusick return;
269034187Smckusick bptr = sbptr + blkoff(fs, addr);
269134187Smckusick switch (objsz) {
269234187Smckusick case LONG:
269334187Smckusick case DIRECTORY:
269434187Smckusick olditem = *(long *)bptr;
269534187Smckusick *(long *)bptr = item;
269634187Smckusick break;
269734187Smckusick case SHORT:
269834187Smckusick case INODE:
269934187Smckusick olditem = (long)*(short *)bptr;
270034187Smckusick item &= 0177777L;
270134187Smckusick *(short *)bptr = item;
270234187Smckusick break;
270334187Smckusick case CHAR:
270434187Smckusick olditem = (long)*bptr;
270534187Smckusick item &= 0377;
270634187Smckusick *bptr = lobyte(loword(item));
270734187Smckusick break;
270834187Smckusick default:
270934187Smckusick error++;
271034187Smckusick return;
271134187Smckusick }
271257998Sralph if ((s_err = lseek(fd, (off_t)(addr & fs->fs_bmask), SEEK_SET)) == -1) {
271334187Smckusick error++;
271457998Sralph printf("seek error : %x\n", addr);
271534187Smckusick return(0);
271634187Smckusick }
271734187Smckusick if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) {
271834187Smckusick error++;
271957998Sralph printf("write error : addr = %x\n", addr);
272057998Sralph printf(" : s_err = %qx\n", s_err);
272157998Sralph printf(" : nbytes = %x\n", nbytes);
272234187Smckusick return(0);
272334187Smckusick }
272434187Smckusick if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) {
272534187Smckusick index(base);
272634187Smckusick print(olditem, 8, -8, 0);
272734187Smckusick printf("\t=\t");
272834187Smckusick print(item, 8, -8, 0);
272934187Smckusick printf("\n");
273034187Smckusick } else {
273134187Smckusick if (objsz == DIRECTORY) {
273234187Smckusick addr = cur_dir;
273334187Smckusick fprnt('?', 'd');
273434187Smckusick } else {
273534187Smckusick addr = cur_ino;
273634187Smckusick objsz = INODE;
273734187Smckusick fprnt('?', 'i');
273834187Smckusick }
273934187Smckusick }
274034187Smckusick return;
274134187Smckusick }
274234187Smckusick
274334187Smckusick /*
274434187Smckusick * getblk - check if the desired block is in the file system.
274534187Smckusick * Search the incore buffers to see if the block is already
274634187Smckusick * available. If successful, unlink the buffer control block
274734187Smckusick * from its position in the buffer list and re-insert it at
274834187Smckusick * the head of the list. If failure, use the last buffer
274934187Smckusick * in the list for the desired block. Again, this control
275034187Smckusick * block is placed at the head of the list. This process
275134187Smckusick * will leave commonly requested blocks in the in-core buffers.
275234187Smckusick * Finally, a pointer to the buffer is returned.
275334187Smckusick */
275434187Smckusick char *
getblk(address)275534187Smckusick getblk(address)
275634187Smckusick long address;
275734187Smckusick {
275834187Smckusick
275934187Smckusick register struct buf *bp;
276057998Sralph off_t s_err;
276157998Sralph long nbytes;
276234187Smckusick unsigned long block;
276334187Smckusick
276434187Smckusick read_requests++;
276534187Smckusick block = lblkno(fs, address);
276634187Smckusick if (block >= fragstoblks(fs, fs->fs_size)) {
276734187Smckusick printf("block exceeds maximum block in file system\n");
276834187Smckusick error++;
276934187Smckusick return(0);
277034187Smckusick }
277134187Smckusick for (bp=bhdr.fwd; bp!= &bhdr; bp=bp->fwd)
277234187Smckusick if (bp->valid && bp->blkno==block)
277334187Smckusick goto xit;
277434187Smckusick actual_disk_reads++;
277534187Smckusick bp = bhdr.back;
277634187Smckusick bp->blkno = block;
277734187Smckusick bp->valid = 0;
277857998Sralph s_err = lseek(fd, (off_t)(address & fs->fs_bmask), SEEK_SET);
277957998Sralph if (s_err == -1) {
278034187Smckusick error++;
278157998Sralph printf("seek error : %x\n", address);
278234187Smckusick return(0);
278334187Smckusick }
278434187Smckusick if ((nbytes = read(fd, bp->blkaddr, BLKSIZE)) != BLKSIZE) {
278534187Smckusick error++;
278657998Sralph printf("read error : addr = %x\n", address);
278757998Sralph printf(" : s_err = %qx\n", s_err);
278857998Sralph printf(" : nbytes = %x\n", nbytes);
278934187Smckusick return(0);
279034187Smckusick }
279134187Smckusick bp->valid++;
279234187Smckusick xit: bp->back->fwd = bp->fwd;
279334187Smckusick bp->fwd->back = bp->back;
279434187Smckusick insert(bp);
279534187Smckusick return(bp->blkaddr);
279634187Smckusick }
279734187Smckusick
279834187Smckusick /*
279934187Smckusick * insert - place the designated buffer control block
280034187Smckusick * at the head of the linked list of buffers.
280134187Smckusick */
insert(bp)280234187Smckusick insert(bp)
280334187Smckusick register struct buf *bp;
280434187Smckusick {
280534187Smckusick
280634187Smckusick bp->back = &bhdr;
280734187Smckusick bp->fwd = bhdr.fwd;
280834187Smckusick bhdr.fwd->back = bp;
280934187Smckusick bhdr.fwd = bp;
281034187Smckusick }
281134187Smckusick
281234187Smckusick /*
281334187Smckusick * err - called on interrupts. Set the current address
281434187Smckusick * back to the last address stored in erraddr. Reset all
281534187Smckusick * appropriate flags. A reset call is made to return
281634187Smckusick * to the main loop;
281734187Smckusick */
281846706Sbostic void
err()281934187Smckusick err()
282034187Smckusick {
282134187Smckusick freemem(filenames, nfiles);
282234187Smckusick nfiles = 0;
282357998Sralph signal(2, err);
282434187Smckusick addr = erraddr;
282534187Smckusick cur_ino = errino;
282634187Smckusick cur_inum = errinum;
282734187Smckusick cur_bytes = errcur_bytes;
282834187Smckusick error = 0;
282934187Smckusick c_count = 0;
283034187Smckusick printf("\n?\n");
283134187Smckusick fseek(stdin, 0L, 2);
283257998Sralph longjmp(env, 0);
283334187Smckusick }
283434187Smckusick
283534187Smckusick /*
283657998Sralph * devcheck - check that the given mode represents a
283734187Smckusick * special device. The IFCHR bit is on for both
283834187Smckusick * character and block devices.
283934187Smckusick */
devcheck(md)284034187Smckusick devcheck(md)
284134187Smckusick register short md;
284234187Smckusick {
284334187Smckusick if (override)
284434187Smckusick return(0);
284534187Smckusick if (md & IFCHR)
284634187Smckusick return(0);
284734187Smckusick printf("not character or block device\n");
284834187Smckusick error++;
284934187Smckusick return(1);
285034187Smckusick }
285134187Smckusick
285234187Smckusick /*
285334187Smckusick * nullblk - return error if address is zero. This is done
285434187Smckusick * to prevent block 0 from being used as an indirect block
285534187Smckusick * for a large file or as a data block for a small file.
285634187Smckusick */
nullblk(bn)285734187Smckusick nullblk(bn)
285834187Smckusick long bn;
285934187Smckusick {
286034187Smckusick if (bn != 0)
286134187Smckusick return(0);
286234187Smckusick printf("non existent block\n");
286334187Smckusick error++;
286434187Smckusick return(1);
286534187Smckusick }
286634187Smckusick
286734187Smckusick /*
286834187Smckusick * puta - put ascii characters into a buffer. The string
286934187Smckusick * terminates with a quote or newline. The leading quote,
287034187Smckusick * which is optional for directory names, was stripped off
287134187Smckusick * by the assignment case in the main loop.
287234187Smckusick */
puta()287334187Smckusick puta()
287434187Smckusick {
287534187Smckusick register char *cptr, c;
287634187Smckusick register int i;
287734187Smckusick char *sbptr;
287834187Smckusick short terror = 0;
287957998Sralph long maxchars, nbytes, temp;
288057998Sralph off_t s_err;
288134187Smckusick long taddr = addr, tcount = 0, item, olditem = 0;
288234187Smckusick
288334187Smckusick if (!wrtflag) {
288434187Smckusick printf("not opened for write '-w'\n");
288534187Smckusick error++;
288634187Smckusick return;
288734187Smckusick }
288834187Smckusick if ((sbptr = getblk(addr)) == 0)
288934187Smckusick return;
289034187Smckusick cptr = sbptr + blkoff(fs, addr);
289134187Smckusick if (objsz == DIRECTORY) {
289234187Smckusick if (acting_on_directory)
289334187Smckusick maxchars = stringsize - 1;
289434187Smckusick else
289534187Smckusick maxchars = LONG;
289634187Smckusick } else if (objsz == INODE)
289734187Smckusick maxchars = objsz - (addr - cur_ino);
289834187Smckusick else
289934187Smckusick maxchars = min(blocksize - cur_bytes, filesize - cur_bytes);
290034187Smckusick while ((c = getachar()) != '"') {
290134187Smckusick if (tcount >= maxchars) {
290234187Smckusick printf("string too long\n");
290334187Smckusick if (objsz == DIRECTORY)
290434187Smckusick addr = cur_dir;
290534187Smckusick else if (acting_on_inode || objsz == INODE)
290634187Smckusick addr = cur_ino;
290734187Smckusick else
290834187Smckusick addr = taddr;
290934187Smckusick erraddr = addr;
291034187Smckusick errcur_bytes = cur_bytes;
291134187Smckusick terror++;
291234187Smckusick break;
291334187Smckusick }
291434187Smckusick tcount++;
291534187Smckusick if (c == '\n') {
291634187Smckusick ungetachar(c);
291734187Smckusick break;
291834187Smckusick }
291934187Smckusick temp = (long)*cptr;
292034187Smckusick olditem <<= BITSPERCHAR;
292134187Smckusick olditem += temp & 0xff;
292234187Smckusick if (c == '\\') {
292334187Smckusick switch (c = getachar()) {
292434187Smckusick case 't':
292534187Smckusick *cptr++ = '\t';
292634187Smckusick break;
292734187Smckusick case 'n':
292834187Smckusick *cptr++ = '\n';
292934187Smckusick break;
293034187Smckusick case '0':
293134187Smckusick *cptr++ = '\0';
293234187Smckusick break;
293334187Smckusick default:
293434187Smckusick *cptr++ = c;
293534187Smckusick break;
293634187Smckusick }
293734187Smckusick }
293834187Smckusick else
293934187Smckusick *cptr++ = c;
294034187Smckusick }
294134187Smckusick if (objsz == DIRECTORY && acting_on_directory)
294234187Smckusick for (i = tcount; i <= maxchars; i++)
294334187Smckusick *cptr++ = '\0';
294457998Sralph if ((s_err = lseek(fd, (off_t)(addr & fs->fs_bmask), SEEK_SET)) == -1) {
294534187Smckusick error++;
294657998Sralph printf("seek error : %x\n", addr);
294734187Smckusick return(0);
294834187Smckusick }
294934187Smckusick if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) {
295034187Smckusick error++;
295157998Sralph printf("write error : addr = %x\n", addr);
295257998Sralph printf(" : s_err = %qx\n", s_err);
295357998Sralph printf(" : nbytes = %x\n", nbytes);
295434187Smckusick return(0);
295534187Smckusick }
295634187Smckusick if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) {
295734187Smckusick addr += tcount;
295834187Smckusick cur_bytes += tcount;
295934187Smckusick taddr = addr;
296034187Smckusick if (objsz != CHAR) {
296134187Smckusick addr &= ~(objsz - 1);
296234187Smckusick cur_bytes -= taddr - addr;
296334187Smckusick }
296434187Smckusick if (addr == taddr) {
296534187Smckusick addr -= objsz;
296634187Smckusick taddr = addr;
296734187Smckusick }
296834187Smckusick tcount = LONG - (taddr - addr);
296934187Smckusick index(base);
297034187Smckusick if ((cptr = getblk(addr)) == 0)
297134187Smckusick return;
297234187Smckusick cptr += blkoff(fs, addr);
297334187Smckusick switch (objsz) {
297434187Smckusick case LONG:
297534187Smckusick item = *(long *)cptr;
297634187Smckusick if (tcount < LONG) {
297734187Smckusick olditem <<= tcount * BITSPERCHAR;
297834187Smckusick temp = 1;
297934187Smckusick for (i = 0; i < (tcount*BITSPERCHAR); i++)
298034187Smckusick temp <<= 1;
298134187Smckusick olditem += item & (temp - 1);
298234187Smckusick }
298334187Smckusick break;
298434187Smckusick case SHORT:
298534187Smckusick item = (long)*(short *)cptr;
298634187Smckusick if (tcount < SHORT) {
298734187Smckusick olditem <<= tcount * BITSPERCHAR;
298834187Smckusick temp = 1;
298934187Smckusick for (i = 0; i < (tcount * BITSPERCHAR); i++)
299034187Smckusick temp <<= 1;
299134187Smckusick olditem += item & (temp - 1);
299234187Smckusick }
299334187Smckusick olditem &= 0177777L;
299434187Smckusick break;
299534187Smckusick case CHAR:
299634187Smckusick item = (long)*cptr;
299734187Smckusick olditem &= 0377;
299834187Smckusick }
299934187Smckusick print(olditem, 8, -8, 0);
300034187Smckusick printf("\t=\t");
300134187Smckusick print(item, 8, -8, 0);
300234187Smckusick printf("\n");
300334187Smckusick } else {
300434187Smckusick if (objsz == DIRECTORY) {
300534187Smckusick addr = cur_dir;
300634187Smckusick fprnt('?', 'd');
300734187Smckusick } else {
300834187Smckusick addr = cur_ino;
300934187Smckusick objsz = INODE;
301034187Smckusick fprnt('?', 'i');
301134187Smckusick }
301234187Smckusick }
301334187Smckusick if (terror)
301434187Smckusick error++;
301534187Smckusick }
301634187Smckusick
301734187Smckusick /*
301834187Smckusick * fprnt - print data. 'count' elements are printed where '*' will
301934187Smckusick * print an entire blocks worth or up to the eof, whichever
302034187Smckusick * occurs first. An error will occur if crossing a block boundary
302134187Smckusick * is attempted since consecutive blocks don't usually have
302234187Smckusick * meaning. Current print types:
302334187Smckusick * / b - print as bytes (base sensitive)
302434187Smckusick * c - print as characters
302534187Smckusick * o O - print as octal shorts (longs)
302634187Smckusick * d D - print as decimal shorts (longs)
302734187Smckusick * x X - print as hexadecimal shorts (longs)
302834187Smckusick * ? c - print as cylinder groups
302934187Smckusick * d - print as directories
303034187Smckusick * i - print as inodes
303134187Smckusick * s - print as super blocks
303234187Smckusick */
fprnt(style,po)303334187Smckusick fprnt(style, po)
303434187Smckusick register char style, po;
303534187Smckusick {
303634187Smckusick register int i;
303734187Smckusick register struct fs *sb;
303834187Smckusick register struct cg *cg;
303934187Smckusick register struct direct *dirp;
304034187Smckusick register struct dinode *ip;
304134187Smckusick int tbase;
304234187Smckusick char c, *cptr, *p;
304334187Smckusick long tinode, tcount, temp, taddr;
304434187Smckusick short offset, mode, end = 0, eof = 0, eof_flag;
304534187Smckusick unsigned short *sptr;
304634187Smckusick unsigned long *lptr;
304734187Smckusick
304834187Smckusick laststyle = style;
304934187Smckusick lastpo = po;
305034187Smckusick should_print = 0;
305134187Smckusick if (count != 1) {
305234187Smckusick if (clear) {
305334187Smckusick count = 1;
305434187Smckusick star = 0;
305534187Smckusick clear = 0;
305634187Smckusick } else
305734187Smckusick clear = 1;
305834187Smckusick }
305934187Smckusick tcount = count;
306034187Smckusick offset = blkoff(fs, addr);
306134187Smckusick
306234187Smckusick if (style == '/') {
306334187Smckusick if (type == NUMB)
306434187Smckusick eof_flag = 0;
306534187Smckusick else
306634187Smckusick eof_flag = 1;
306734187Smckusick switch (po) {
306834187Smckusick
306934187Smckusick case 'c': /* print as characters */
307034187Smckusick case 'b': /* or bytes */
307134187Smckusick if ((cptr = getblk(addr)) == 0)
307234187Smckusick return;
307334187Smckusick cptr += offset;
307434187Smckusick objsz = CHAR;
307534187Smckusick tcount = check_addr(eof_flag, &end, &eof, 0);
307634187Smckusick if (tcount) {
307734187Smckusick for (i=0; tcount--; i++) {
307834187Smckusick if (i % 16 == 0) {
307934187Smckusick if (i)
308034187Smckusick printf("\n");
308134187Smckusick index(base);
308234187Smckusick }
308334187Smckusick if (po == 'c') {
308434187Smckusick putf(*cptr++);
308534187Smckusick if ((i + 1) % 16)
308634187Smckusick printf(" ");
308734187Smckusick } else {
308834187Smckusick if ((i + 1) % 16 == 0)
308934187Smckusick print(*cptr++ & 0377,
309057998Sralph 2, -2, 0);
309134187Smckusick else
309234187Smckusick print(*cptr++ & 0377,
309357998Sralph 4, -2, 0);
309434187Smckusick }
309534187Smckusick addr += CHAR;
309634187Smckusick cur_bytes += CHAR;
309734187Smckusick }
309834187Smckusick printf("\n");
309934187Smckusick }
310034187Smckusick addr -= CHAR;
310134187Smckusick erraddr = addr;
310234187Smckusick cur_bytes -= CHAR;
310334187Smckusick errcur_bytes = cur_bytes;
310434187Smckusick if (eof) {
310534187Smckusick printf("end of file\n");
310634187Smckusick error++;
310734187Smckusick } else if (end) {
310834187Smckusick if (type == BLOCK)
310934187Smckusick printf("end of block\n");
311034187Smckusick else
311134187Smckusick printf("end of fragment\n");
311234187Smckusick error++;
311334187Smckusick }
311434187Smckusick return;
311534187Smckusick
311634187Smckusick case 'o': /* print as octal shorts */
311734187Smckusick tbase = OCTAL;
311834187Smckusick goto otx;
311934187Smckusick case 'd': /* print as decimal shorts */
312034187Smckusick tbase = DECIMAL;
312134187Smckusick goto otx;
312234187Smckusick case 'x': /* print as hex shorts */
312334187Smckusick tbase = HEX;
312434187Smckusick otx:
312534187Smckusick if ((cptr = getblk(addr)) == 0)
312634187Smckusick return;
312734187Smckusick taddr = addr;
312834187Smckusick addr &= ~(SHORT - 1);
312934187Smckusick cur_bytes -= taddr - addr;
313034187Smckusick cptr += blkoff(fs, addr);
313134187Smckusick sptr = (unsigned short *)cptr;
313234187Smckusick objsz = SHORT;
313334187Smckusick tcount = check_addr(eof_flag, &end, &eof, 0);
313434187Smckusick if (tcount) {
313534187Smckusick for (i=0; tcount--; i++) {
313634187Smckusick sptr = (unsigned short *)
313734187Smckusick print_check(sptr, &tcount, tbase, i);
313834187Smckusick switch (po) {
313934187Smckusick case 'o':
314057998Sralph printf("%06o ", *sptr++);
314134187Smckusick break;
314234187Smckusick case 'd':
314357998Sralph printf("%05d ", *sptr++);
314434187Smckusick break;
314534187Smckusick case 'x':
314657998Sralph printf("%04x ", *sptr++);
314734187Smckusick }
314834187Smckusick addr += SHORT;
314934187Smckusick cur_bytes += SHORT;
315034187Smckusick }
315134187Smckusick printf("\n");
315234187Smckusick }
315334187Smckusick addr -= SHORT;
315434187Smckusick erraddr = addr;
315534187Smckusick cur_bytes -= SHORT;
315634187Smckusick errcur_bytes = cur_bytes;
315734187Smckusick if (eof) {
315834187Smckusick printf("end of file\n");
315934187Smckusick error++;
316034187Smckusick } else if (end) {
316134187Smckusick if (type == BLOCK)
316234187Smckusick printf("end of block\n");
316334187Smckusick else
316434187Smckusick printf("end of fragment\n");
316534187Smckusick error++;
316634187Smckusick }
316734187Smckusick return;
316834187Smckusick
316934187Smckusick case 'O': /* print as octal longs */
317034187Smckusick tbase = OCTAL;
317134187Smckusick goto OTX;
317234187Smckusick case 'D': /* print as decimal longs */
317334187Smckusick tbase = DECIMAL;
317434187Smckusick goto OTX;
317534187Smckusick case 'X': /* print as hex longs */
317634187Smckusick tbase = HEX;
317734187Smckusick OTX:
317834187Smckusick if ((cptr = getblk(addr)) == 0)
317934187Smckusick return;
318034187Smckusick taddr = addr;
318134187Smckusick addr &= ~(LONG - 1);
318234187Smckusick cur_bytes -= taddr - addr;
318334187Smckusick cptr += blkoff(fs, addr);
318434187Smckusick lptr = (unsigned long *)cptr;
318534187Smckusick objsz = LONG;
318634187Smckusick tcount = check_addr(eof_flag, &end, &eof, 0);
318734187Smckusick if (tcount) {
318834187Smckusick for (i=0; tcount--; i++) {
318934187Smckusick lptr =
319034187Smckusick print_check(lptr, &tcount, tbase, i);
319134187Smckusick switch (po) {
319234187Smckusick case 'O':
319357998Sralph printf("%011o ", *lptr++);
319434187Smckusick break;
319534187Smckusick case 'D':
319657998Sralph printf("%010u ", *lptr++);
319734187Smckusick break;
319834187Smckusick case 'X':
319957998Sralph printf("%08x ", *lptr++);
320034187Smckusick }
320134187Smckusick addr += LONG;
320234187Smckusick cur_bytes += LONG;
320334187Smckusick }
320434187Smckusick printf("\n");
320534187Smckusick }
320634187Smckusick addr -= LONG;
320734187Smckusick erraddr = addr;
320834187Smckusick cur_bytes -= LONG;
320934187Smckusick errcur_bytes = cur_bytes;
321034187Smckusick if (eof) {
321134187Smckusick printf("end of file\n");
321234187Smckusick error++;
321334187Smckusick } else if (end) {
321434187Smckusick if (type == BLOCK)
321534187Smckusick printf("end of block\n");
321634187Smckusick else
321734187Smckusick printf("end of fragment\n");
321834187Smckusick error++;
321934187Smckusick }
322034187Smckusick return;
322134187Smckusick
322234187Smckusick default:
322334187Smckusick error++;
322434187Smckusick printf("no such print option\n");
322534187Smckusick return;
322634187Smckusick }
322734187Smckusick } else
322834187Smckusick switch (po) {
322934187Smckusick
323034187Smckusick case 'c': /* print as cylinder group */
323134187Smckusick if (type != NUMB)
323234187Smckusick if (cur_cgrp + count > fs->fs_ncg) {
323334187Smckusick tcount = fs->fs_ncg - cur_cgrp;
323434187Smckusick if (!star)
323534187Smckusick end++;
323634187Smckusick }
323734187Smckusick addr &= ~(LONG - 1);
323834187Smckusick for (; tcount--;) {
323934187Smckusick erraddr = addr;
324034187Smckusick errcur_bytes = cur_bytes;
324134187Smckusick if (type != NUMB) {
324234187Smckusick addr = cgtod(fs, cur_cgrp)
324334187Smckusick << FRGSHIFT;
324434187Smckusick cur_cgrp++;
324534187Smckusick }
324634187Smckusick if ((cptr = getblk(addr)) == 0) {
324734187Smckusick if (cur_cgrp)
324834187Smckusick cur_cgrp--;
324934187Smckusick return;
325034187Smckusick }
325134187Smckusick cptr += blkoff(fs, addr);
325234187Smckusick cg = (struct cg *)cptr;
325334187Smckusick if (type == NUMB) {
325434187Smckusick cur_cgrp = cg->cg_cgx + 1;
325534187Smckusick type = objsz = CGRP;
325634187Smckusick if (cur_cgrp + count - 1 > fs->fs_ncg) {
325734187Smckusick tcount = fs->fs_ncg - cur_cgrp;
325834187Smckusick if (!star)
325934187Smckusick end++;
326034187Smckusick }
326134187Smckusick }
326234197Smckusick if (!override && !cg_chkmagic(cg)) {
326334187Smckusick printf("invalid cylinder group ");
326434187Smckusick printf("magic word\n");
326534187Smckusick if (cur_cgrp)
326634187Smckusick cur_cgrp--;
326734187Smckusick error++;
326834187Smckusick return;
326934187Smckusick }
327034197Smckusick printcg(cg);
327134187Smckusick if (tcount)
327234187Smckusick printf("\n");
327334187Smckusick }
327434187Smckusick cur_cgrp--;
327534187Smckusick if (end) {
327634187Smckusick printf("end of cylinder groups\n");
327734187Smckusick error++;
327834187Smckusick }
327934187Smckusick return;
328034187Smckusick
328134187Smckusick case 'd': /* print as directories */
328234187Smckusick if ((cptr = getblk(addr)) == 0)
328334187Smckusick return;
328434187Smckusick if (type == NUMB) {
328534187Smckusick if (fragoff(fs, addr)) {
328634187Smckusick printf("address must be at the ");
328734187Smckusick printf("beginning of a fragment\n");
328834187Smckusick error++;
328934187Smckusick return;
329034187Smckusick }
329134187Smckusick bod_addr = addr;
329234187Smckusick type = FRAGMENT;
329334187Smckusick dirslot = 0;
329434187Smckusick cur_bytes = 0;
329534187Smckusick blocksize = FRGSIZE;
329634187Smckusick filesize = FRGSIZE * 2;
329734187Smckusick }
329834187Smckusick cptr += offset;
329934187Smckusick objsz = DIRECTORY;
330034187Smckusick while (tcount-- && cur_bytes < filesize &&
330134187Smckusick cur_bytes < blocksize && !bcomp(addr)) {
330234187Smckusick dirp = (struct direct *)cptr;
330334187Smckusick tinode = dirp->d_ino;
330434187Smckusick printf("i#: ");
330534187Smckusick if (tinode == 0)
330634187Smckusick printf("free\t");
330734187Smckusick else
330834187Smckusick print(tinode, 12, -8, 0);
330957998Sralph printf("%s\n", &dirp->d_name[0]);
331034187Smckusick erraddr = addr;
331134187Smckusick errcur_bytes = cur_bytes;
331234187Smckusick addr += dirp->d_reclen;
331334187Smckusick cptr += dirp->d_reclen;
331434187Smckusick cur_bytes += dirp->d_reclen;
331534187Smckusick dirslot++;
331634187Smckusick }
331734187Smckusick addr = erraddr;
331834187Smckusick cur_dir = addr;
331934187Smckusick cur_bytes = errcur_bytes;
332034187Smckusick stringsize = STRINGSIZE(dirp);
332134187Smckusick dirslot--;
332234187Smckusick if (tcount >= 0 && !star) {
332334187Smckusick switch (type) {
332434187Smckusick case FRAGMENT:
332534187Smckusick printf("end of fragment\n");
332634187Smckusick break;
332734187Smckusick case BLOCK:
332834187Smckusick printf("end of block\n");
332934187Smckusick break;
333034187Smckusick default:
333134187Smckusick printf("end of directory\n");
333234187Smckusick }
333334187Smckusick error++;
333434187Smckusick } else
333534187Smckusick error = 0;
333634187Smckusick return;
333734187Smckusick
333834187Smckusick case 'i': /* print as inodes */
333934187Smckusick if ((ip = (struct dinode *)getblk(addr)) == 0)
334034187Smckusick return;
334134187Smckusick for (i=1; i < fs->fs_ncg; i++)
334257998Sralph if (addr < (cgimin(fs, i) << FRGSHIFT))
334334187Smckusick break;
334434187Smckusick i--;
334534187Smckusick offset /= INODE;
334657998Sralph temp = (addr - (cgimin(fs, i) << FRGSHIFT)) >> FRGSHIFT;
334757998Sralph temp = (i * fs->fs_ipg) + fragstoblks(fs, temp) *
334834187Smckusick INOPB(fs) + offset;
334934187Smckusick if (count + offset > INOPB(fs)) {
335034187Smckusick tcount = INOPB(fs) - offset;
335134187Smckusick if (!star)
335234187Smckusick end++;
335334187Smckusick }
335434187Smckusick objsz = INODE;
335534187Smckusick ip += offset;
335634187Smckusick for (i=0; tcount--; ip++, temp++) {
335734187Smckusick if ((mode = icheck(addr)) == 0)
335834187Smckusick if (!override)
335934187Smckusick continue;
336034187Smckusick p = " ugtrwxrwxrwx";
336134187Smckusick
336234187Smckusick switch (mode & IFMT) {
336334187Smckusick case IFDIR:
336434187Smckusick c = 'd';
336534187Smckusick break;
336634187Smckusick case IFCHR:
336734187Smckusick c = 'c';
336834187Smckusick break;
336934187Smckusick case IFBLK:
337034187Smckusick c = 'b';
337134187Smckusick break;
337234187Smckusick case IFREG:
337334187Smckusick c = '-';
337434187Smckusick break;
337534187Smckusick case IFLNK:
337634187Smckusick c = 'l';
337734187Smckusick break;
337834187Smckusick case IFSOCK:
337934187Smckusick c = 's';
338034187Smckusick break;
338134187Smckusick default:
338234187Smckusick c = '?';
338334187Smckusick if (!override)
338434187Smckusick goto empty;
338534187Smckusick
338634187Smckusick }
338734187Smckusick printf("i#: ");
338857998Sralph print(temp, 12, -8, 0);
338934187Smckusick printf(" md: ");
339034187Smckusick printf("%c", c);
339134187Smckusick for (mode = mode << 4; *++p; mode = mode << 1) {
339234187Smckusick if (mode & IFREG)
339334187Smckusick printf("%c", *p);
339434187Smckusick else
339534187Smckusick printf("-");
339657998Sralph }
339734187Smckusick printf(" uid: ");
339857998Sralph print(ip->di_uid, 8, -4, 0);
339934187Smckusick printf(" gid: ");
340057998Sralph print(ip->di_gid, 8, -4, 0);
340134187Smckusick printf("\n");
340234187Smckusick printf("ln: ");
340357998Sralph print(ip->di_nlink, 8, -4, 0);
340434187Smckusick printf(" bs: ");
340557998Sralph print(ip->di_blocks, 12, -8, 0);
340634187Smckusick printf(" sz : ");
340764645Shibler print((int)ip->di_size, 12, -8, 0);
340834187Smckusick printf("\n");
340934187Smckusick if (ip->di_mode & IFCHR) {
341034187Smckusick printf("maj: ");
341157998Sralph print(ip->di_db[1] & 0377, 4, -2, 0);
341234187Smckusick printf(" min: ");
341357998Sralph print(ip->di_db[0] & 0377, 4, -2, 0);
341434187Smckusick printf("\n");
341534187Smckusick } else {
341634187Smckusick for (i = 0; i < NDADDR; ) {
341734187Smckusick if (ip->di_db[i] == 0)
341834187Smckusick break;
341957998Sralph printf("db#%x: ", i);
342057998Sralph print(ip->di_db[i], 11, -8, 0);
342134187Smckusick if (++i % 4 == 0)
342234187Smckusick printf("\n");
342334187Smckusick else
342434187Smckusick printf(" ");
342534187Smckusick }
342634187Smckusick if (i % 4)
342734187Smckusick printf("\n");
342834187Smckusick for (i = 0; i < NIADDR; i++) {
342934187Smckusick if (ip->di_ib[i] == 0)
343034187Smckusick break;
343157998Sralph printf("ib#%x: ", i);
343257998Sralph print(ip->di_ib[i], 11, -8, 0);
343334187Smckusick printf(" ");
343434187Smckusick }
343534187Smckusick if (i)
343634187Smckusick printf("\n");
343734187Smckusick }
343834187Smckusick if (count == 1) {
343934187Smckusick printf("\taccessed: %s",
3440*69260Smckusick ctime(&ip->di_atime));
344134187Smckusick printf("\tmodified: %s",
3442*69260Smckusick ctime(&ip->di_mtime));
344334187Smckusick printf("\tcreated : %s",
3444*69260Smckusick ctime(&ip->di_ctime));
344534187Smckusick }
344634187Smckusick if (tcount)
344734187Smckusick printf("\n");
344834187Smckusick empty:
344934187Smckusick if (c == '?' && !override) {
345034187Smckusick printf("i#: ");
345134187Smckusick print(temp, 12, -8, 0);
345234187Smckusick printf(" is unallocated\n");
345334187Smckusick if (count != 1)
345434187Smckusick printf("\n");
345534187Smckusick }
345634187Smckusick cur_ino = erraddr = addr;
345734187Smckusick errcur_bytes = cur_bytes;
345834187Smckusick cur_inum++;
345934187Smckusick addr = addr + INODE;
346034187Smckusick }
346134187Smckusick addr = erraddr;
346234187Smckusick cur_bytes = errcur_bytes;
346334187Smckusick cur_inum--;
346434187Smckusick if (end) {
346534187Smckusick printf("end of block\n");
346634187Smckusick error++;
346734187Smckusick }
346834187Smckusick return;
346934187Smckusick
347034187Smckusick case 's': /* print as super block */
347134187Smckusick if (cur_cgrp == -1) {
347234187Smckusick addr = SBLOCK * DEV_BSIZE;
347334187Smckusick type = NUMB;
347434187Smckusick }
347534187Smckusick addr &= ~(LONG - 1);
347634187Smckusick if (type != NUMB)
347734187Smckusick if (cur_cgrp + count > fs->fs_ncg) {
347834187Smckusick tcount = fs->fs_ncg - cur_cgrp;
347934187Smckusick if (!star)
348034187Smckusick end++;
348134187Smckusick }
348234187Smckusick for (; tcount--;) {
348334187Smckusick erraddr = addr;
348434187Smckusick cur_bytes = errcur_bytes;
348534187Smckusick if (type != NUMB) {
348634187Smckusick addr = cgsblock(fs, cur_cgrp)
348734187Smckusick << FRGSHIFT;
348834187Smckusick cur_cgrp++;
348934187Smckusick }
349034187Smckusick if ((cptr = getblk(addr)) == 0) {
349134187Smckusick if (cur_cgrp)
349234187Smckusick cur_cgrp--;
349334187Smckusick return;
349434187Smckusick }
349534187Smckusick cptr += blkoff(fs, addr);
349634187Smckusick sb = (struct fs *)cptr;
349734187Smckusick if (type == NUMB) {
349834187Smckusick for (i = 0; i < fs->fs_ncg; i++)
349934187Smckusick if (addr == cgsblock(fs, i) <<
350034187Smckusick FRGSHIFT)
350134187Smckusick break;
350234187Smckusick if (i == fs->fs_ncg)
350334187Smckusick cur_cgrp = 0;
350434187Smckusick else
350534187Smckusick cur_cgrp = i + 1;
350634187Smckusick type = objsz = SB;
350734187Smckusick if (cur_cgrp + count - 1 > fs->fs_ncg) {
350834187Smckusick tcount = fs->fs_ncg - cur_cgrp;
350934187Smckusick if (!star)
351034187Smckusick end++;
351134187Smckusick }
351234187Smckusick }
351334187Smckusick if (sb->fs_magic != FS_MAGIC) {
351434187Smckusick cur_cgrp = 0;
351534187Smckusick if (!override) {
351634187Smckusick printf("invalid super block ");
351734187Smckusick printf("magic word\n");
351834187Smckusick cur_cgrp--;
351934187Smckusick error++;
352034187Smckusick return;
352134187Smckusick }
352234187Smckusick }
352334187Smckusick if (cur_cgrp == 0)
352434187Smckusick printf("\tsuper block:\n");
352534187Smckusick else {
352634187Smckusick printf("\tsuper block in cylinder ");
352734187Smckusick printf("group ");
352834187Smckusick print(cur_cgrp - 1, 0, 0, 0);
352934187Smckusick printf(":\n");
353034187Smckusick }
353134197Smckusick printsb(sb);
353234187Smckusick if (tcount)
353334187Smckusick printf("\n");
353434187Smckusick }
353534187Smckusick cur_cgrp--;
353634187Smckusick if (end) {
353734187Smckusick printf("end of super blocks\n");
353834187Smckusick error++;
353934187Smckusick }
354034187Smckusick return;
354134187Smckusick default:
354234187Smckusick error++;
354334187Smckusick printf("no such print option\n");
354434187Smckusick return;
354534187Smckusick }
354634187Smckusick }
354734187Smckusick
354834187Smckusick /*
354934187Smckusick * valid_addr - call check_addr to validate the current address.
355034187Smckusick */
valid_addr()355134187Smckusick valid_addr()
355234187Smckusick {
355334187Smckusick short eof_flag, end = 0, eof = 0;
355434187Smckusick long tcount = count;
355534187Smckusick
355634187Smckusick if (!trapped)
355734187Smckusick return(1);
355834187Smckusick if (cur_bytes < 0) {
355934187Smckusick cur_bytes = 0;
356034187Smckusick if (blocksize > filesize) {
356134187Smckusick printf("beginning of file\n");
356234187Smckusick } else {
356334187Smckusick if (type == BLOCK)
356434187Smckusick printf("beginning of block\n");
356534187Smckusick else
356634187Smckusick printf("beginning of fragment\n");
356734187Smckusick }
356834187Smckusick error++;
356934187Smckusick return(0);
357034187Smckusick }
357134187Smckusick count = 1;
357234187Smckusick check_addr(1, &end, &eof, (filesize < blocksize));
357334187Smckusick count = tcount;
357434187Smckusick if (eof) {
357534187Smckusick printf("end of file\n");
357634187Smckusick error++;
357734187Smckusick return(0);
357834187Smckusick }
357934187Smckusick if (end == 2) {
358034187Smckusick if (erraddr > addr) {
358134187Smckusick if (type == BLOCK)
358234187Smckusick printf("beginning of block\n");
358334187Smckusick else
358434187Smckusick printf("beginning of fragment\n");
358534187Smckusick error++;
358634187Smckusick return(0);
358734187Smckusick }
358834187Smckusick }
358934187Smckusick if (end) {
359034187Smckusick if (type == BLOCK)
359134187Smckusick printf("end of block\n");
359234187Smckusick else
359334187Smckusick printf("end of fragment\n");
359434187Smckusick error++;
359534187Smckusick return(0);
359634187Smckusick }
359734187Smckusick return(1);
359834187Smckusick }
359934187Smckusick
360034187Smckusick /*
360134187Smckusick * check_addr - check if the address crosses the end of block or
360234187Smckusick * end of file. Return the proper count.
360334187Smckusick */
check_addr(eof_flag,end,eof,keep_on)360434187Smckusick check_addr(eof_flag, end, eof, keep_on)
360534187Smckusick short eof_flag, *end, *eof, keep_on;
360634187Smckusick {
360734187Smckusick long temp, tcount = count, taddr = addr, tcur_bytes = cur_bytes;
360834187Smckusick
360934187Smckusick if (bcomp(addr + count * objsz - 1) ||
361034187Smckusick (keep_on && taddr < (bmap(cur_block) << FRGSHIFT))) {
361134187Smckusick error = 0;
361234187Smckusick addr = taddr;
361334187Smckusick cur_bytes = tcur_bytes;
361434187Smckusick if (keep_on) {
361534187Smckusick if (addr < erraddr) {
361634187Smckusick if (cur_bytes < 0) {
361734187Smckusick (*end) = 2;
361834187Smckusick return;
361934187Smckusick }
362034187Smckusick temp = cur_block - lblkno(fs, cur_bytes);
362134187Smckusick cur_block -= temp;
362234187Smckusick if ((addr = bmap(cur_block) << FRGSHIFT) == 0) {
362334187Smckusick cur_block += temp;
362434187Smckusick return;
362534187Smckusick }
362634187Smckusick temp = tcur_bytes - cur_bytes;
362734187Smckusick addr += temp;
362834187Smckusick cur_bytes += temp;
362934187Smckusick return;
363034187Smckusick } else {
363134187Smckusick if (cur_bytes >= filesize) {
363234187Smckusick (*eof)++;
363334187Smckusick return;
363434187Smckusick }
363534187Smckusick temp = lblkno(fs, cur_bytes) - cur_block;
363634187Smckusick cur_block += temp;
363734187Smckusick if ((addr = bmap(cur_block) << FRGSHIFT) == 0) {
363834187Smckusick cur_block -= temp;
363934187Smckusick return;
364034187Smckusick }
364134187Smckusick temp = tcur_bytes - cur_bytes;
364234187Smckusick addr += temp;
364334187Smckusick cur_bytes += temp;
364434187Smckusick return;
364534187Smckusick }
364634187Smckusick }
364734187Smckusick tcount = (blkroundup(fs, addr+1)-addr) / objsz;
364834187Smckusick if (!star)
364934187Smckusick (*end) = 2;
365034187Smckusick }
365134187Smckusick addr = taddr;
365234187Smckusick cur_bytes = tcur_bytes;
365334187Smckusick if (eof_flag) {
365434187Smckusick if (blocksize > filesize) {
365534187Smckusick if (cur_bytes >= filesize) {
365634187Smckusick tcount = 0;
365734187Smckusick (*eof)++;
365834187Smckusick } else if (tcount > (filesize - cur_bytes) / objsz) {
365934187Smckusick tcount = (filesize - cur_bytes) / objsz;
366034187Smckusick if (!star || tcount == 0)
366134187Smckusick (*eof)++;
366234187Smckusick }
366334187Smckusick } else {
366434187Smckusick if (cur_bytes >= blocksize) {
366534187Smckusick tcount = 0;
366634187Smckusick (*end)++;
366734187Smckusick } else if (tcount > (blocksize - cur_bytes) / objsz) {
366834187Smckusick tcount = (blocksize - cur_bytes) / objsz;
366934187Smckusick if (!star || tcount == 0)
367034187Smckusick (*end)++;
367134187Smckusick }
367234187Smckusick }
367334187Smckusick }
367434187Smckusick return(tcount);
367534187Smckusick }
367634187Smckusick
367734187Smckusick /*
367834187Smckusick * print_check - check if the index needs to be printed and delete
367934187Smckusick * rows of zeros from the output.
368034187Smckusick */
368134187Smckusick unsigned long *
print_check(lptr,tcount,tbase,i)368234187Smckusick print_check(lptr, tcount, tbase, i)
368334187Smckusick unsigned long *lptr;
368434187Smckusick long *tcount;
368534187Smckusick short tbase;
368634187Smckusick register int i;
368734187Smckusick {
368834187Smckusick register int j, k, temp = BYTESPERLINE / objsz;
368934187Smckusick short first_time = 0;
369034187Smckusick unsigned long *tlptr;
369134187Smckusick unsigned short *tsptr, *sptr;
369234187Smckusick
369334187Smckusick sptr = (unsigned short *)lptr;
369434187Smckusick if (i == 0)
369534187Smckusick first_time = 1;
369634187Smckusick if (i % temp == 0) {
369734187Smckusick if (*tcount >= temp - 1) {
369834187Smckusick if (objsz == SHORT)
369934187Smckusick tsptr = sptr;
370034187Smckusick else
370134187Smckusick tlptr = lptr;
370234187Smckusick k = *tcount - 1;
370334187Smckusick for (j = i; k--; j++)
370434187Smckusick if (objsz == SHORT) {
370534187Smckusick if (*tsptr++ != 0)
370634187Smckusick break;
370734187Smckusick } else {
370834187Smckusick if (*tlptr++ != 0)
370934187Smckusick break;
371034187Smckusick }
371134187Smckusick if (j > (i + temp - 1)) {
371234187Smckusick j = (j - i) / temp;
371334187Smckusick while (j-- > 0) {
371434187Smckusick if (objsz == SHORT)
371534187Smckusick sptr += temp;
371634187Smckusick else
371734187Smckusick lptr += temp;
371834187Smckusick *tcount -= temp;
371934187Smckusick i += temp;
372057998Sralph addr += BYTESPERLINE;
372134187Smckusick cur_bytes += BYTESPERLINE;
372234187Smckusick }
372334187Smckusick if (first_time)
372434187Smckusick printf("*");
372534187Smckusick else
372634187Smckusick printf("\n*");
372734187Smckusick }
372834187Smckusick if (i)
372934187Smckusick printf("\n");
373034187Smckusick index(tbase);
373134187Smckusick } else {
373234187Smckusick if (i)
373334187Smckusick printf("\n");
373434187Smckusick index(tbase);
373534187Smckusick }
373634187Smckusick }
373734187Smckusick if(objsz == SHORT)
373834187Smckusick return((unsigned long *)sptr);
373934187Smckusick else
374034187Smckusick return(lptr);
374134187Smckusick }
374234187Smckusick
374334187Smckusick /*
374434187Smckusick * index - print a byte index for the printout in base b
374534187Smckusick * with leading zeros.
374634187Smckusick */
index(b)374734187Smckusick index(b)
374834187Smckusick int b;
374934187Smckusick {
375034187Smckusick int tbase = base;
375134187Smckusick
375234187Smckusick base = b;
375334187Smckusick print(addr, 8, 8, 1);
375434187Smckusick printf(":\t");
375534187Smckusick base = tbase;
375634187Smckusick }
375734187Smckusick
375834187Smckusick /*
375934187Smckusick * print - print out the value to digits places with/without
376034187Smckusick * leading zeros and right/left justified in the current base.
376134187Smckusick */
print(value,fieldsz,digits,lead)376234187Smckusick print(value, fieldsz, digits, lead)
376334187Smckusick int value, fieldsz, digits, lead;
376434187Smckusick {
376534187Smckusick register int i, left = 0;
376634187Smckusick char mode = BASE[base - OCTAL];
376734187Smckusick char *string = &scratch[0];
376834187Smckusick
376934187Smckusick if (digits < 0) {
377034187Smckusick left = 1;
377134187Smckusick digits *= -1;
377234187Smckusick }
377334187Smckusick if (base != HEX)
377434187Smckusick if (digits)
377534187Smckusick digits = digits + (digits - 1)/((base >> 1) - 1) + 1;
377634187Smckusick else
377734187Smckusick digits = 1;
377834187Smckusick if (lead) {
377934187Smckusick if (left)
378034187Smckusick sprintf(string, "%%%c%d%d.%d%c",
378134187Smckusick '-', 0, digits, lead, mode);
378234187Smckusick else
378334187Smckusick sprintf(string, "%%%d%d.%d%c", 0, digits, lead, mode);
378434187Smckusick } else {
378534187Smckusick if (left)
378634187Smckusick sprintf(string, "%%%c%d%c", '-', digits, mode);
378734187Smckusick else
378834187Smckusick sprintf(string, "%%%d%c", digits, mode);
378934187Smckusick }
379034187Smckusick printf(string, value);
379134187Smckusick for (i = 0; i < fieldsz - digits; i++)
379234187Smckusick printf(" ");
379334187Smckusick }
379434187Smckusick
379534187Smckusick /*
379634197Smckusick * Print out the contents of a superblock.
379734197Smckusick */
379834197Smckusick printsb(fs)
379934197Smckusick struct fs *fs;
380034197Smckusick {
380134197Smckusick int c, i, j, k, size;
380234197Smckusick
380336249Smckusick #ifdef FS_42POSTBLFMT
380434197Smckusick if (fs->fs_postblformat == FS_42POSTBLFMT)
380534197Smckusick fs->fs_nrpos = 8;
380634197Smckusick printf("magic\t%x\tformat\t%s\ttime\t%s", fs->fs_magic,
380734197Smckusick fs->fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
380834197Smckusick ctime(&fs->fs_time));
380936249Smckusick #else
381036249Smckusick printf("magic\t%x\ttime\t%s",
381136249Smckusick fs->fs_magic, ctime(&fs->fs_time));
381236249Smckusick #endif
381334197Smckusick printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
381434197Smckusick fs->fs_cstotal.cs_nbfree, fs->fs_cstotal.cs_ndir,
381534197Smckusick fs->fs_cstotal.cs_nifree, fs->fs_cstotal.cs_nffree);
381634197Smckusick printf("ncg\t%d\tncyl\t%d\tsize\t%d\tblocks\t%d\n",
381734197Smckusick fs->fs_ncg, fs->fs_ncyl, fs->fs_size, fs->fs_dsize);
381834197Smckusick printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n",
381934197Smckusick fs->fs_bsize, fs->fs_bshift, fs->fs_bmask);
382034197Smckusick printf("fsize\t%d\tshift\t%d\tmask\t0x%08x\n",
382134197Smckusick fs->fs_fsize, fs->fs_fshift, fs->fs_fmask);
382234197Smckusick printf("frag\t%d\tshift\t%d\tfsbtodb\t%d\n",
382334197Smckusick fs->fs_frag, fs->fs_fragshift, fs->fs_fsbtodb);
382434197Smckusick printf("cpg\t%d\tbpg\t%d\tfpg\t%d\tipg\t%d\n",
382534197Smckusick fs->fs_cpg, fs->fs_fpg / fs->fs_frag, fs->fs_fpg, fs->fs_ipg);
382634197Smckusick printf("minfree\t%d%%\toptim\t%s\tmaxcontig %d\tmaxbpg\t%d\n",
382734197Smckusick fs->fs_minfree, fs->fs_optim == FS_OPTSPACE ? "space" : "time",
382834197Smckusick fs->fs_maxcontig, fs->fs_maxbpg);
382936249Smckusick #ifdef FS_42POSTBLFMT
383034197Smckusick printf("rotdelay %dms\theadswitch %dus\ttrackseek %dus\trps\t%d\n",
383134197Smckusick fs->fs_rotdelay, fs->fs_headswitch, fs->fs_trkseek, fs->fs_rps);
383234197Smckusick printf("ntrak\t%d\tnsect\t%d\tnpsect\t%d\tspc\t%d\n",
383334197Smckusick fs->fs_ntrak, fs->fs_nsect, fs->fs_npsect, fs->fs_spc);
383434197Smckusick printf("trackskew %d\tinterleave %d\n",
383534197Smckusick fs->fs_trackskew, fs->fs_interleave);
383636249Smckusick #else
383736249Smckusick printf("rotdelay %dms\trps\t%d\n",
383836249Smckusick fs->fs_rotdelay, fs->fs_rps);
383936249Smckusick printf("ntrak\t%d\tnsect\t%d\tspc\t%d\n",
384036249Smckusick fs->fs_ntrak, fs->fs_nsect, fs->fs_spc);
384136249Smckusick #endif
384234197Smckusick printf("nindir\t%d\tinopb\t%d\tnspf\t%d\n",
384334197Smckusick fs->fs_nindir, fs->fs_inopb, fs->fs_nspf);
384434197Smckusick printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
384534197Smckusick fs->fs_sblkno, fs->fs_cblkno, fs->fs_iblkno, fs->fs_dblkno);
384634197Smckusick printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
384734197Smckusick fs->fs_sbsize, fs->fs_cgsize, fs->fs_cgoffset, fs->fs_cgmask);
384834197Smckusick printf("csaddr\t%d\tcssize\t%d\tshift\t%d\tmask\t0x%08x\n",
384934197Smckusick fs->fs_csaddr, fs->fs_cssize, fs->fs_csshift, fs->fs_csmask);
385034197Smckusick printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\n",
385134197Smckusick fs->fs_cgrotor, fs->fs_fmod, fs->fs_ronly);
385236249Smckusick #ifdef FS_42POSTBLFMT
385334197Smckusick if (fs->fs_cpc != 0)
385434197Smckusick printf("blocks available in each of %d rotational positions",
385534197Smckusick fs->fs_nrpos);
385634197Smckusick else
385734197Smckusick printf("insufficient space to maintain rotational tables\n");
385836249Smckusick #endif
385934197Smckusick for (c = 0; c < fs->fs_cpc; c++) {
386034197Smckusick printf("\ncylinder number %d:", c);
386136249Smckusick #ifdef FS_42POSTBLFMT
386234197Smckusick for (i = 0; i < fs->fs_nrpos; i++) {
386334197Smckusick if (fs_postbl(fs, c)[i] == -1)
386434197Smckusick continue;
386534197Smckusick printf("\n position %d:\t", i);
386634197Smckusick for (j = fs_postbl(fs, c)[i], k = 1; ;
386734197Smckusick j += fs_rotbl(fs)[j], k++) {
386834197Smckusick printf("%5d", j);
386934197Smckusick if (k % 12 == 0)
387034197Smckusick printf("\n\t\t");
387134197Smckusick if (fs_rotbl(fs)[j] == 0)
387234197Smckusick break;
387334197Smckusick }
387434197Smckusick }
387536249Smckusick #else
387636249Smckusick for (i = 0; i < NRPOS; i++) {
387736249Smckusick if (fs->fs_postbl[c][i] == -1)
387836249Smckusick continue;
387936249Smckusick printf("\n position %d:\t", i);
388036249Smckusick for (j = fs->fs_postbl[c][i], k = 1; ;
388136249Smckusick j += fs->fs_rotbl[j], k++) {
388236249Smckusick printf("%5d", j);
388336249Smckusick if (k % 12 == 0)
388436249Smckusick printf("\n\t\t");
388536249Smckusick if (fs->fs_rotbl[j] == 0)
388636249Smckusick break;
388736249Smckusick }
388836249Smckusick }
388936249Smckusick #endif
389034197Smckusick }
389157998Sralph printf("\ncs[].cs_(nbfree, ndir, nifree, nffree):\n\t");
389234197Smckusick for (i = 0, j = 0; i < fs->fs_cssize; i += fs->fs_bsize, j++) {
389334197Smckusick size = fs->fs_cssize - i < fs->fs_bsize ?
389434197Smckusick fs->fs_cssize - i : fs->fs_bsize;
389534197Smckusick fs->fs_csp[j] = (struct csum *)calloc(1, size);
389657998Sralph (void)lseek(fd, fsbtodb(fs, (fs->fs_csaddr + j * fs->fs_frag)) *
389757998Sralph fs->fs_fsize / fsbtodb(fs, 1), SEEK_SET);
389834197Smckusick if (read(fd, fs->fs_csp[j], size) != size) {
389934197Smckusick for (j--; j >= 0; j--)
390034197Smckusick free(fs->fs_csp[j]);
390134197Smckusick return;
390234197Smckusick }
390334197Smckusick }
390434197Smckusick for (i = 0; i < fs->fs_ncg; i++) {
390534197Smckusick struct csum *cs = &fs->fs_cs(fs, i);
390634197Smckusick if (i && i % 4 == 0)
390734197Smckusick printf("\n\t");
390834197Smckusick printf("(%d,%d,%d,%d) ",
390934197Smckusick cs->cs_nbfree, cs->cs_ndir, cs->cs_nifree, cs->cs_nffree);
391034197Smckusick }
391134197Smckusick for (j--; j >= 0; j--)
391234197Smckusick free(fs->fs_csp[j]);
391334197Smckusick printf("\n");
391434197Smckusick if (fs->fs_ncyl % fs->fs_cpg) {
391534197Smckusick printf("cylinders in last group %d\n",
391634197Smckusick i = fs->fs_ncyl % fs->fs_cpg);
391734197Smckusick printf("blocks in last group %d\n",
391834197Smckusick i * fs->fs_spc / NSPB(fs));
391934197Smckusick }
392034197Smckusick }
392134197Smckusick
392234197Smckusick /*
392334197Smckusick * Print out the contents of a cylinder group.
392434197Smckusick */
392534197Smckusick printcg(cg)
392634197Smckusick struct cg *cg;
392734197Smckusick {
392857998Sralph int i, j;
392934197Smckusick
393034197Smckusick printf("\ncg %d:\n", cg->cg_cgx);
393136249Smckusick #ifdef FS_42POSTBLFMT
393234197Smckusick printf("magic\t%x\ttell\t%x\ttime\t%s",
393334197Smckusick fs->fs_postblformat == FS_42POSTBLFMT ?
393434197Smckusick ((struct ocg *)cg)->cg_magic : cg->cg_magic,
393534197Smckusick fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1),
393634197Smckusick ctime(&cg->cg_time));
393736249Smckusick #else
393836249Smckusick printf("magic\t%x\ttell\t%x\ttime\t%s",
393936249Smckusick cg->cg_magic,
394036249Smckusick fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1),
394136249Smckusick ctime(&cg->cg_time));
394236249Smckusick #endif
394334197Smckusick printf("cgx\t%d\tncyl\t%d\tniblk\t%d\tndblk\t%d\n",
394434197Smckusick cg->cg_cgx, cg->cg_ncyl, cg->cg_niblk, cg->cg_ndblk);
394534197Smckusick printf("nbfree\t%d\tndir\t%d\tnifree\t%d\tnffree\t%d\n",
394634197Smckusick cg->cg_cs.cs_nbfree, cg->cg_cs.cs_ndir,
394734197Smckusick cg->cg_cs.cs_nifree, cg->cg_cs.cs_nffree);
394834197Smckusick printf("rotor\t%d\tirotor\t%d\tfrotor\t%d\nfrsum",
394934197Smckusick cg->cg_rotor, cg->cg_irotor, cg->cg_frotor);
395034197Smckusick for (i = 1, j = 0; i < fs->fs_frag; i++) {
395134197Smckusick printf("\t%d", cg->cg_frsum[i]);
395234197Smckusick j += i * cg->cg_frsum[i];
395334197Smckusick }
395434197Smckusick printf("\nsum of frsum: %d\niused:\t", j);
395534197Smckusick pbits(cg_inosused(cg), fs->fs_ipg);
395634197Smckusick printf("free:\t");
395734197Smckusick pbits(cg_blksfree(cg), fs->fs_fpg);
395834197Smckusick printf("b:\n");
395934197Smckusick for (i = 0; i < fs->fs_cpg; i++) {
396034197Smckusick if (cg_blktot(cg)[i] == 0)
396134197Smckusick continue;
396234197Smckusick printf(" c%d:\t(%d)\t", i, cg_blktot(cg)[i]);
396336249Smckusick #ifdef FS_42POSTBLFMT
396434197Smckusick for (j = 0; j < fs->fs_nrpos; j++) {
396534197Smckusick if (fs->fs_cpc == 0 ||
396634197Smckusick fs_postbl(fs, i % fs->fs_cpc)[j] == -1)
396734197Smckusick continue;
396834197Smckusick printf(" %d", cg_blks(fs, cg, i)[j]);
396934197Smckusick }
397036249Smckusick #else
397136249Smckusick for (j = 0; j < NRPOS; j++) {
397236249Smckusick if (fs->fs_cpc == 0 ||
397336249Smckusick fs->fs_postbl[i % fs->fs_cpc][j] == -1)
397436249Smckusick continue;
397536249Smckusick printf(" %d", cg->cg_b[i][j]);
397636249Smckusick }
397736249Smckusick #endif
397834197Smckusick printf("\n");
397934197Smckusick }
398034197Smckusick }
398134197Smckusick
398234197Smckusick /*
398334197Smckusick * Print out the contents of a bit array.
398434197Smckusick */
pbits(cp,max)398534197Smckusick pbits(cp, max)
398634197Smckusick register char *cp;
398734197Smckusick int max;
398834197Smckusick {
398934197Smckusick register int i;
399034197Smckusick int count = 0, j;
399134197Smckusick
399234197Smckusick for (i = 0; i < max; i++)
399334197Smckusick if (isset(cp, i)) {
399434197Smckusick if (count)
399534197Smckusick printf(",%s", count % 6 ? " " : "\n\t");
399634197Smckusick count++;
399734197Smckusick printf("%d", i);
399834197Smckusick j = i;
399934197Smckusick while ((i+1)<max && isset(cp, i+1))
400034197Smckusick i++;
400134197Smckusick if (i != j)
400234197Smckusick printf("-%d", i);
400334197Smckusick }
400434197Smckusick printf("\n");
400534197Smckusick }
400634197Smckusick
400734197Smckusick /*
400834187Smckusick * bcomp - used to check for block over/under flows when stepping through
400934187Smckusick * a file system.
401034187Smckusick */
bcomp(addr)401134187Smckusick bcomp(addr)
401234187Smckusick long addr;
401334187Smckusick {
401434187Smckusick if (override)
401534187Smckusick return(0);
401634187Smckusick if (lblkno(fs, addr) == (bhdr.fwd)->blkno)
401734187Smckusick return(0);
401834187Smckusick error++;
401934187Smckusick return(1);
402034187Smckusick }
402134187Smckusick
402234187Smckusick /*
402334187Smckusick * bmap - maps the logical block number of a file into
402434187Smckusick * the corresponding physical block on the file
402534187Smckusick * system.
402634187Smckusick */
402734187Smckusick long
bmap(bn)402834187Smckusick bmap(bn)
402934187Smckusick long bn;
403034187Smckusick {
403134187Smckusick register int i, j;
403234187Smckusick register struct dinode *ip;
403334187Smckusick int sh;
403434187Smckusick long nb;
403534187Smckusick
403634187Smckusick ip = (struct dinode *)cur_ino;
403734187Smckusick if (bn < NDADDR) {
403834187Smckusick addr = (long)&ip->di_db[bn];
403934187Smckusick cur_bytes = bn * BLKSIZE;
404034187Smckusick return(nullblk(nb=get(LONG)) ? 0L : nb);
404134187Smckusick }
404234187Smckusick
404334187Smckusick sh = 1;
404434187Smckusick bn -= NDADDR;
404534187Smckusick for (j = NIADDR; j > 0; j--) {
404634187Smckusick sh *= NINDIR(fs);
404734187Smckusick if (bn < sh)
404834187Smckusick break;
404934187Smckusick bn -= sh;
405034187Smckusick }
405134187Smckusick if (j == 0) {
405234187Smckusick printf("file too big\n");
405334187Smckusick error++;
405434187Smckusick return(0L);
405534187Smckusick }
405634187Smckusick addr = (long)&ip->di_ib[NIADDR - j];
405734187Smckusick nb = get(LONG);
405834187Smckusick if (nb == 0)
405934187Smckusick return(0L);
406034187Smckusick for (; j <= NIADDR; j++) {
406134187Smckusick sh /= NINDIR(fs);
406234187Smckusick addr = (nb << FRGSHIFT) + ((bn / sh) % NINDIR(fs)) * LONG;
406334187Smckusick if (nullblk(nb = get(LONG)))
406434187Smckusick return(0L);
406534187Smckusick }
406634187Smckusick return(nb);
406734187Smckusick }
4068