10Sstevel@tonic-gate /*
2*12875SJohn.Zolnowsky@Sun.COM * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
30Sstevel@tonic-gate */
40Sstevel@tonic-gate
50Sstevel@tonic-gate /*
60Sstevel@tonic-gate * Copyright (c) 1988 Regents of the University of California.
70Sstevel@tonic-gate * All rights reserved.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by
100Sstevel@tonic-gate * Computer Consoles Inc.
110Sstevel@tonic-gate *
120Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted
130Sstevel@tonic-gate * provided that: (1) source distributions retain this entire copyright
140Sstevel@tonic-gate * notice and comment, and (2) distributions including binaries display
150Sstevel@tonic-gate * the following acknowledgement: ``This product includes software
160Sstevel@tonic-gate * developed by the University of California, Berkeley and its contributors''
170Sstevel@tonic-gate * in the documentation or other materials provided with the distribution
180Sstevel@tonic-gate * and in all advertising materials mentioning features or use of this
190Sstevel@tonic-gate * software. Neither the name of the University nor the names of its
200Sstevel@tonic-gate * contributors may be used to endorse or promote products derived
210Sstevel@tonic-gate * from this software without specific prior written permission.
220Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
230Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
240Sstevel@tonic-gate * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #ifndef lint
280Sstevel@tonic-gate char copyright[] =
290Sstevel@tonic-gate "@(#) Copyright(c) 1988 Regents of the University of California.\n\
300Sstevel@tonic-gate All rights reserved.\n";
310Sstevel@tonic-gate #endif /* not lint */
320Sstevel@tonic-gate
330Sstevel@tonic-gate #ifndef lint
340Sstevel@tonic-gate static char sccsid[] = "@(#)fsdb.c 5.8 (Berkeley) 6/1/90";
350Sstevel@tonic-gate #endif /* not lint */
360Sstevel@tonic-gate
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate * fsdb - file system debugger
390Sstevel@tonic-gate *
400Sstevel@tonic-gate * usage: fsdb [-o suboptions] special
410Sstevel@tonic-gate * options/suboptions:
420Sstevel@tonic-gate * -o
430Sstevel@tonic-gate * ? display usage
440Sstevel@tonic-gate * o override some error conditions
450Sstevel@tonic-gate * p="string" set prompt to string
460Sstevel@tonic-gate * w open for write
470Sstevel@tonic-gate */
480Sstevel@tonic-gate
490Sstevel@tonic-gate #include <sys/param.h>
500Sstevel@tonic-gate #include <sys/signal.h>
510Sstevel@tonic-gate #include <sys/file.h>
520Sstevel@tonic-gate #include <inttypes.h>
530Sstevel@tonic-gate #include <sys/sysmacros.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate #ifdef sun
560Sstevel@tonic-gate #include <unistd.h>
570Sstevel@tonic-gate #include <stdlib.h>
580Sstevel@tonic-gate #include <string.h>
590Sstevel@tonic-gate #include <fcntl.h>
600Sstevel@tonic-gate #include <signal.h>
610Sstevel@tonic-gate #include <sys/types.h>
620Sstevel@tonic-gate #include <sys/vnode.h>
630Sstevel@tonic-gate #include <sys/mntent.h>
640Sstevel@tonic-gate #include <sys/wait.h>
650Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
660Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
670Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
680Sstevel@tonic-gate #include <sys/fs/ufs_acl.h>
690Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
700Sstevel@tonic-gate #else
710Sstevel@tonic-gate #include <sys/dir.h>
720Sstevel@tonic-gate #include <ufs/fs.h>
730Sstevel@tonic-gate #include <ufs/dinode.h>
740Sstevel@tonic-gate #include <paths.h>
750Sstevel@tonic-gate #endif /* sun */
760Sstevel@tonic-gate
770Sstevel@tonic-gate #include <stdio.h>
780Sstevel@tonic-gate #include <setjmp.h>
790Sstevel@tonic-gate
800Sstevel@tonic-gate #define OLD_FSDB_COMPATIBILITY /* To support the obsoleted "-z" option */
810Sstevel@tonic-gate
820Sstevel@tonic-gate #ifndef _PATH_BSHELL
830Sstevel@tonic-gate #define _PATH_BSHELL "/bin/sh"
840Sstevel@tonic-gate #endif /* _PATH_BSHELL */
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate * Defines from the 4.3-tahoe file system, for systems with the 4.2 or 4.3
870Sstevel@tonic-gate * file system.
880Sstevel@tonic-gate */
890Sstevel@tonic-gate #ifndef FS_42POSTBLFMT
900Sstevel@tonic-gate #define cg_blktot(cgp) (((cgp))->cg_btot)
910Sstevel@tonic-gate #define cg_blks(fs, cgp, cylno) (((cgp))->cg_b[cylno])
920Sstevel@tonic-gate #define cg_inosused(cgp) (((cgp))->cg_iused)
930Sstevel@tonic-gate #define cg_blksfree(cgp) (((cgp))->cg_free)
940Sstevel@tonic-gate #define cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
950Sstevel@tonic-gate #endif
960Sstevel@tonic-gate
970Sstevel@tonic-gate /*
980Sstevel@tonic-gate * Never changing defines.
990Sstevel@tonic-gate */
1000Sstevel@tonic-gate #define OCTAL 8 /* octal base */
1010Sstevel@tonic-gate #define DECIMAL 10 /* decimal base */
1020Sstevel@tonic-gate #define HEX 16 /* hexadecimal base */
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate /*
1050Sstevel@tonic-gate * Adjustable defines.
1060Sstevel@tonic-gate */
1070Sstevel@tonic-gate #define NBUF 10 /* number of cache buffers */
1080Sstevel@tonic-gate #define PROMPTSIZE 80 /* size of user definable prompt */
1090Sstevel@tonic-gate #define MAXFILES 40000 /* max number of files ls can handle */
1100Sstevel@tonic-gate #define FIRST_DEPTH 10 /* default depth for find and ls */
1110Sstevel@tonic-gate #define SECOND_DEPTH 100 /* second try at depth (maximum) */
1120Sstevel@tonic-gate #define INPUTBUFFER 1040 /* size of input buffer */
1130Sstevel@tonic-gate #define BYTESPERLINE 16 /* bytes per line of /dxo output */
1140Sstevel@tonic-gate #define NREG 36 /* number of save registers */
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate #define DEVPREFIX "/dev/" /* Uninteresting part of "special" */
1170Sstevel@tonic-gate
1180Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
1190Sstevel@tonic-gate #define FSDB_OPTIONS "o:wp:z:"
1200Sstevel@tonic-gate #else
1210Sstevel@tonic-gate #define FSDB_OPTIONS "o:wp:"
1220Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * Values dependent on sizes of structs and such.
1270Sstevel@tonic-gate */
1280Sstevel@tonic-gate #define NUMB 3 /* these three are arbitrary, */
1290Sstevel@tonic-gate #define BLOCK 5 /* but must be different from */
1300Sstevel@tonic-gate #define FRAGMENT 7 /* the rest (hence odd). */
1310Sstevel@tonic-gate #define BITSPERCHAR 8 /* couldn't find it anywhere */
1320Sstevel@tonic-gate #define CHAR (sizeof (char))
1330Sstevel@tonic-gate #define SHORT (sizeof (short))
1340Sstevel@tonic-gate #define LONG (sizeof (long))
1350Sstevel@tonic-gate #define U_OFFSET_T (sizeof (u_offset_t)) /* essentially "long long" */
1360Sstevel@tonic-gate #define INODE (sizeof (struct dinode))
1370Sstevel@tonic-gate #define DIRECTORY (sizeof (struct direct))
1380Sstevel@tonic-gate #define CGRP (sizeof (struct cg))
1390Sstevel@tonic-gate #define SB (sizeof (struct fs))
1400Sstevel@tonic-gate #define BLKSIZE (fs->fs_bsize) /* for clarity */
1410Sstevel@tonic-gate #define FRGSIZE (fs->fs_fsize)
1420Sstevel@tonic-gate #define BLKSHIFT (fs->fs_bshift)
1430Sstevel@tonic-gate #define FRGSHIFT (fs->fs_fshift)
1440Sstevel@tonic-gate #define SHADOW_DATA (sizeof (struct ufs_fsd))
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate /*
1470Sstevel@tonic-gate * Messy macros that would otherwise clutter up such glamorous code.
1480Sstevel@tonic-gate */
1490Sstevel@tonic-gate #define itob(i) (((u_offset_t)itod(fs, (i)) << \
1500Sstevel@tonic-gate (u_offset_t)FRGSHIFT) + (u_offset_t)itoo(fs, (i)) * (u_offset_t)INODE)
1510Sstevel@tonic-gate #define min(x, y) ((x) < (y) ? (x) : (y))
1520Sstevel@tonic-gate #define STRINGSIZE(d) ((long)d->d_reclen - \
1530Sstevel@tonic-gate ((long)&d->d_name[0] - (long)&d->d_ino))
1540Sstevel@tonic-gate #define letter(c) ((((c) >= 'a')&&((c) <= 'z')) ||\
1550Sstevel@tonic-gate (((c) >= 'A')&&((c) <= 'Z')))
1560Sstevel@tonic-gate #define digit(c) (((c) >= '0') && ((c) <= '9'))
1570Sstevel@tonic-gate #define HEXLETTER(c) (((c) >= 'A') && ((c) <= 'F'))
1580Sstevel@tonic-gate #define hexletter(c) (((c) >= 'a') && ((c) <= 'f'))
1590Sstevel@tonic-gate #define octaldigit(c) (((c) >= '0') && ((c) <= '7'))
1600Sstevel@tonic-gate #define uppertolower(c) ((c) - 'A' + 'a')
1610Sstevel@tonic-gate #define hextodigit(c) ((c) - 'a' + 10)
1620Sstevel@tonic-gate #define numtodigit(c) ((c) - '0')
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate #if !defined(loword)
1650Sstevel@tonic-gate #define loword(X) (((ushort_t *)&X)[1])
1660Sstevel@tonic-gate #endif /* loword */
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate #if !defined(lobyte)
1690Sstevel@tonic-gate #define lobyte(X) (((unsigned char *)&X)[1])
1700Sstevel@tonic-gate #endif /* lobyte */
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate * buffer cache structure.
1740Sstevel@tonic-gate */
1750Sstevel@tonic-gate static struct lbuf {
1760Sstevel@tonic-gate struct lbuf *fwd;
1770Sstevel@tonic-gate struct lbuf *back;
1780Sstevel@tonic-gate char *blkaddr;
1790Sstevel@tonic-gate short valid;
1800Sstevel@tonic-gate u_offset_t blkno;
1810Sstevel@tonic-gate } lbuf[NBUF], bhdr;
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate /*
1840Sstevel@tonic-gate * used to hold save registers (see '<' and '>').
1850Sstevel@tonic-gate */
1860Sstevel@tonic-gate struct save_registers {
1870Sstevel@tonic-gate u_offset_t sv_addr;
1880Sstevel@tonic-gate u_offset_t sv_value;
1890Sstevel@tonic-gate long sv_objsz;
1900Sstevel@tonic-gate } regs[NREG];
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate * cd, find, and ls use this to hold filenames. Each filename is broken
1940Sstevel@tonic-gate * up by a slash. In other words, /usr/src/adm would have a len field
1950Sstevel@tonic-gate * of 2 (starting from 0), and filenames->fname[0-2] would hold usr,
1960Sstevel@tonic-gate * src, and adm components of the pathname.
1970Sstevel@tonic-gate */
1980Sstevel@tonic-gate static struct filenames {
1990Sstevel@tonic-gate ino_t ino; /* inode */
2000Sstevel@tonic-gate long len; /* number of components */
2010Sstevel@tonic-gate char flag; /* flag if using SECOND_DEPTH allocator */
2020Sstevel@tonic-gate char find; /* flag if found by find */
2030Sstevel@tonic-gate char **fname; /* hold components of pathname */
2040Sstevel@tonic-gate } *filenames, *top;
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate enum log_enum { LOG_NDELTAS, LOG_ALLDELTAS, LOG_CHECKSCAN };
2070Sstevel@tonic-gate #ifdef sun
2080Sstevel@tonic-gate struct fs *fs;
2090Sstevel@tonic-gate static union {
2100Sstevel@tonic-gate struct fs un_filesystem;
2110Sstevel@tonic-gate char un_sbsize[SBSIZE];
2120Sstevel@tonic-gate } fs_un;
2130Sstevel@tonic-gate #define filesystem fs_un.un_filesystem
2140Sstevel@tonic-gate #else
2150Sstevel@tonic-gate struct fs filesystem, *fs; /* super block */
2160Sstevel@tonic-gate #endif /* sun */
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate /*
2190Sstevel@tonic-gate * Global data.
2200Sstevel@tonic-gate */
2210Sstevel@tonic-gate static char *input_path[MAXPATHLEN];
2220Sstevel@tonic-gate static char *stack_path[MAXPATHLEN];
2230Sstevel@tonic-gate static char *current_path[MAXPATHLEN];
2240Sstevel@tonic-gate static char input_buffer[INPUTBUFFER];
2250Sstevel@tonic-gate static char *prompt;
2260Sstevel@tonic-gate static char *buffers;
2270Sstevel@tonic-gate static char scratch[64];
2280Sstevel@tonic-gate static char BASE[] = "o u x";
2290Sstevel@tonic-gate static char PROMPT[PROMPTSIZE];
2300Sstevel@tonic-gate static char laststyle = '/';
2310Sstevel@tonic-gate static char lastpo = 'x';
2320Sstevel@tonic-gate static short input_pointer;
2330Sstevel@tonic-gate static short current_pathp;
2340Sstevel@tonic-gate static short stack_pathp;
2350Sstevel@tonic-gate static short input_pathp;
2360Sstevel@tonic-gate static short cmp_level;
2370Sstevel@tonic-gate static int nfiles;
2380Sstevel@tonic-gate static short type = NUMB;
2390Sstevel@tonic-gate static short dirslot;
2400Sstevel@tonic-gate static short fd;
2410Sstevel@tonic-gate static short c_count;
2420Sstevel@tonic-gate static short error;
2430Sstevel@tonic-gate static short paren;
2440Sstevel@tonic-gate static short trapped;
2450Sstevel@tonic-gate static short doing_cd;
2460Sstevel@tonic-gate static short doing_find;
2470Sstevel@tonic-gate static short find_by_name;
2480Sstevel@tonic-gate static short find_by_inode;
2490Sstevel@tonic-gate static short long_list;
2500Sstevel@tonic-gate static short recursive;
2510Sstevel@tonic-gate static short objsz = SHORT;
2520Sstevel@tonic-gate static short override = 0;
2530Sstevel@tonic-gate static short wrtflag = O_RDONLY;
2540Sstevel@tonic-gate static short base = HEX;
2550Sstevel@tonic-gate static short acting_on_inode;
2560Sstevel@tonic-gate static short acting_on_directory;
2570Sstevel@tonic-gate static short should_print = 1;
2580Sstevel@tonic-gate static short clear;
2590Sstevel@tonic-gate static short star;
2600Sstevel@tonic-gate static u_offset_t addr;
2610Sstevel@tonic-gate static u_offset_t bod_addr;
2620Sstevel@tonic-gate static u_offset_t value;
2630Sstevel@tonic-gate static u_offset_t erraddr;
2640Sstevel@tonic-gate static long errcur_bytes;
2650Sstevel@tonic-gate static u_offset_t errino;
2660Sstevel@tonic-gate static long errinum;
2670Sstevel@tonic-gate static long cur_cgrp;
2680Sstevel@tonic-gate static u_offset_t cur_ino;
2690Sstevel@tonic-gate static long cur_inum;
2700Sstevel@tonic-gate static u_offset_t cur_dir;
2710Sstevel@tonic-gate static long cur_block;
2720Sstevel@tonic-gate static long cur_bytes;
2730Sstevel@tonic-gate static long find_ino;
2740Sstevel@tonic-gate static u_offset_t filesize;
2750Sstevel@tonic-gate static u_offset_t blocksize;
2760Sstevel@tonic-gate static long stringsize;
2770Sstevel@tonic-gate static long count = 1;
2780Sstevel@tonic-gate static long commands;
2790Sstevel@tonic-gate static long read_requests;
2800Sstevel@tonic-gate static long actual_disk_reads;
2810Sstevel@tonic-gate static jmp_buf env;
2820Sstevel@tonic-gate static long maxfiles;
2830Sstevel@tonic-gate static long cur_shad;
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate #ifndef sun
2860Sstevel@tonic-gate extern char *malloc(), *calloc();
2870Sstevel@tonic-gate #endif
2880Sstevel@tonic-gate static char getachar();
2890Sstevel@tonic-gate static char *getblk(), *fmtentry();
2900Sstevel@tonic-gate
2911051Smaheshvs static offset_t get(short);
2920Sstevel@tonic-gate static long bmap();
2930Sstevel@tonic-gate static long expr();
2940Sstevel@tonic-gate static long term();
2950Sstevel@tonic-gate static long getnumb();
2960Sstevel@tonic-gate static u_offset_t getdirslot();
2971051Smaheshvs static unsigned long *print_check(unsigned long *, long *, short, int);
2981051Smaheshvs
2991051Smaheshvs static void usage(char *);
3001051Smaheshvs static void ungetachar(char);
3010Sstevel@tonic-gate static void getnextinput();
3020Sstevel@tonic-gate static void eat_spaces();
3031051Smaheshvs static void restore_inode(ino_t);
3040Sstevel@tonic-gate static void find();
3051051Smaheshvs static void ls(struct filenames *, struct filenames *, short);
3061051Smaheshvs static void formatf(struct filenames *, struct filenames *);
3070Sstevel@tonic-gate static void parse();
3081051Smaheshvs static void follow_path(long, long);
3090Sstevel@tonic-gate static void getname();
3101051Smaheshvs static void freemem(struct filenames *, int);
3111051Smaheshvs static void print_path(char **, int);
3120Sstevel@tonic-gate static void fill();
3131051Smaheshvs static void put(u_offset_t, short);
3141051Smaheshvs static void insert(struct lbuf *);
3150Sstevel@tonic-gate static void puta();
3161051Smaheshvs static void fprnt(char, char);
3170Sstevel@tonic-gate static void index();
3180Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
3190Sstevel@tonic-gate static void printll
3200Sstevel@tonic-gate (u_offset_t value, int fieldsz, int digits, int lead);
3210Sstevel@tonic-gate #define print(value, fieldsz, digits, lead) \
3220Sstevel@tonic-gate printll((u_offset_t)value, fieldsz, digits, lead)
3230Sstevel@tonic-gate #else /* !_LARGEFILE64_SOURCE */
3240Sstevel@tonic-gate static void print(long value, int fieldsz, int digits, int lead);
3250Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
3261051Smaheshvs static void printsb(struct fs *);
3271051Smaheshvs static void printcg(struct cg *);
3281051Smaheshvs static void pbits(unsigned char *, int);
3291051Smaheshvs static void old_fsdb(int, char *); /* For old fsdb functionality */
3301051Smaheshvs
3311051Smaheshvs static int isnumber(char *);
3321051Smaheshvs static int icheck(u_offset_t);
3331051Smaheshvs static int cgrp_check(long);
3340Sstevel@tonic-gate static int valid_addr();
3351051Smaheshvs static int match(char *, int);
3361051Smaheshvs static int devcheck(short);
3370Sstevel@tonic-gate static int bcomp();
3381051Smaheshvs static int compare(char *, char *, short);
3391051Smaheshvs static int check_addr(short, short *, short *, short);
3400Sstevel@tonic-gate static int fcmp();
3410Sstevel@tonic-gate static int ffcmp();
3420Sstevel@tonic-gate
3431051Smaheshvs static int getshadowslot(long);
3441051Smaheshvs static void getshadowdata(long *, int);
3451051Smaheshvs static void syncshadowscan(int);
3461051Smaheshvs static void log_display_header(void);
3471051Smaheshvs static void log_show(enum log_enum);
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate #ifdef sun
3500Sstevel@tonic-gate static void err();
3510Sstevel@tonic-gate #else
3520Sstevel@tonic-gate static int err();
3530Sstevel@tonic-gate #endif /* sun */
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate /* Suboption vector */
3560Sstevel@tonic-gate static char *subopt_v[] = {
3570Sstevel@tonic-gate #define OVERRIDE 0
3580Sstevel@tonic-gate "o",
3590Sstevel@tonic-gate #define NEW_PROMPT 1
3600Sstevel@tonic-gate "p",
3610Sstevel@tonic-gate #define WRITE_ENABLED 2
3620Sstevel@tonic-gate "w",
3630Sstevel@tonic-gate #define ALT_PROMPT 3
3640Sstevel@tonic-gate "prompt",
3650Sstevel@tonic-gate NULL
3660Sstevel@tonic-gate };
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate * main - lines are read up to the unprotected ('\') newline and
3700Sstevel@tonic-gate * held in an input buffer. Characters may be read from the
3710Sstevel@tonic-gate * input buffer using getachar() and unread using ungetachar().
3720Sstevel@tonic-gate * Reading the whole line ahead allows the use of debuggers
3730Sstevel@tonic-gate * which would otherwise be impossible since the debugger
3740Sstevel@tonic-gate * and fsdb could not share stdin.
3750Sstevel@tonic-gate */
3760Sstevel@tonic-gate
3771051Smaheshvs int
main(int argc,char * argv[])3781051Smaheshvs main(int argc, char *argv[])
3790Sstevel@tonic-gate {
3800Sstevel@tonic-gate
3811051Smaheshvs char c, *cptr;
3821051Smaheshvs short i;
3831051Smaheshvs struct direct *dirp;
3841051Smaheshvs struct lbuf *bp;
3851051Smaheshvs char *progname;
3861051Smaheshvs short colon, mode;
3871051Smaheshvs long temp;
3880Sstevel@tonic-gate
3890Sstevel@tonic-gate /* Options/Suboptions processing */
3900Sstevel@tonic-gate int opt;
3910Sstevel@tonic-gate char *subopts;
3920Sstevel@tonic-gate char *optval;
3930Sstevel@tonic-gate
3940Sstevel@tonic-gate /*
3950Sstevel@tonic-gate * The following are used to support the old fsdb functionality
3960Sstevel@tonic-gate * of clearing an inode. It's better to use 'clri'.
3970Sstevel@tonic-gate */
3980Sstevel@tonic-gate int inum; /* Inode number to clear */
3990Sstevel@tonic-gate char *special;
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate setbuf(stdin, NULL);
4020Sstevel@tonic-gate progname = argv[0];
4030Sstevel@tonic-gate prompt = &PROMPT[0];
4040Sstevel@tonic-gate /*
4050Sstevel@tonic-gate * Parse options.
4060Sstevel@tonic-gate */
4070Sstevel@tonic-gate while ((opt = getopt(argc, argv, FSDB_OPTIONS)) != EOF) {
4080Sstevel@tonic-gate switch (opt) {
4090Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
4100Sstevel@tonic-gate case 'z': /* Hack - Better to use clri */
4110Sstevel@tonic-gate (void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
4120Sstevel@tonic-gate "Warning: The '-z' option of 'fsdb_ufs' has been declared obsolete",
4130Sstevel@tonic-gate "and may not be supported in a future version of Solaris.",
4140Sstevel@tonic-gate "While this functionality is currently still supported, the",
4150Sstevel@tonic-gate "recommended procedure to clear an inode is to use clri(1M).");
4160Sstevel@tonic-gate if (isnumber(optarg)) {
4170Sstevel@tonic-gate inum = atoi(optarg);
4180Sstevel@tonic-gate special = argv[optind];
4190Sstevel@tonic-gate /* Doesn't return */
4200Sstevel@tonic-gate old_fsdb(inum, special);
4210Sstevel@tonic-gate } else {
4220Sstevel@tonic-gate usage(progname);
4230Sstevel@tonic-gate exit(31+1);
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate /* Should exit() before here */
4260Sstevel@tonic-gate /*NOTREACHED*/
4270Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
4280Sstevel@tonic-gate case 'o':
4290Sstevel@tonic-gate /* UFS Specific Options */
4300Sstevel@tonic-gate subopts = optarg;
4310Sstevel@tonic-gate while (*subopts != '\0') {
4320Sstevel@tonic-gate switch (getsubopt(&subopts, subopt_v,
4330Sstevel@tonic-gate &optval)) {
4340Sstevel@tonic-gate case OVERRIDE:
4350Sstevel@tonic-gate printf("error checking off\n");
4360Sstevel@tonic-gate override = 1;
4370Sstevel@tonic-gate break;
4380Sstevel@tonic-gate
4390Sstevel@tonic-gate /*
4400Sstevel@tonic-gate * Change the "-o prompt=foo" option to
4410Sstevel@tonic-gate * "-o p=foo" to match documentation.
4420Sstevel@tonic-gate * ALT_PROMPT continues support for the
4430Sstevel@tonic-gate * undocumented "-o prompt=foo" option so
4440Sstevel@tonic-gate * that we don't break anyone.
4450Sstevel@tonic-gate */
4460Sstevel@tonic-gate case NEW_PROMPT:
4470Sstevel@tonic-gate case ALT_PROMPT:
4480Sstevel@tonic-gate if (optval == NULL) {
4490Sstevel@tonic-gate (void) fprintf(stderr,
4500Sstevel@tonic-gate "No prompt string\n");
4510Sstevel@tonic-gate usage(progname);
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate (void) strncpy(PROMPT, optval,
4540Sstevel@tonic-gate PROMPTSIZE);
4550Sstevel@tonic-gate break;
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate case WRITE_ENABLED:
4580Sstevel@tonic-gate /* suitable for open */
4590Sstevel@tonic-gate wrtflag = O_RDWR;
4600Sstevel@tonic-gate break;
4610Sstevel@tonic-gate
4620Sstevel@tonic-gate default:
4630Sstevel@tonic-gate usage(progname);
4640Sstevel@tonic-gate /* Should exit here */
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate break;
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate default:
4700Sstevel@tonic-gate usage(progname);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate if ((argc - optind) != 1) { /* Should just have "special" left */
4750Sstevel@tonic-gate usage(progname);
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate special = argv[optind];
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate /*
4800Sstevel@tonic-gate * Unless it's already been set, the default prompt includes the
4810Sstevel@tonic-gate * name of the special device.
4820Sstevel@tonic-gate */
4830Sstevel@tonic-gate if (*prompt == NULL)
4840Sstevel@tonic-gate (void) sprintf(prompt, "%s > ", special);
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate /*
4870Sstevel@tonic-gate * Attempt to open the special file.
4880Sstevel@tonic-gate */
4890Sstevel@tonic-gate if ((fd = open(special, wrtflag)) < 0) {
4900Sstevel@tonic-gate perror(special);
4910Sstevel@tonic-gate exit(1);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate /*
4940Sstevel@tonic-gate * Read in the super block and validate (not too picky).
4950Sstevel@tonic-gate */
4960Sstevel@tonic-gate if (llseek(fd, (offset_t)(SBLOCK * DEV_BSIZE), 0) == -1) {
4970Sstevel@tonic-gate perror(special);
4980Sstevel@tonic-gate exit(1);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate #ifdef sun
5020Sstevel@tonic-gate if (read(fd, &filesystem, SBSIZE) != SBSIZE) {
5030Sstevel@tonic-gate printf("%s: cannot read superblock\n", special);
5040Sstevel@tonic-gate exit(1);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate #else
5070Sstevel@tonic-gate if (read(fd, &filesystem, sizeof (filesystem)) != sizeof (filesystem)) {
5080Sstevel@tonic-gate printf("%s: cannot read superblock\n", special);
5090Sstevel@tonic-gate exit(1);
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate #endif /* sun */
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate fs = &filesystem;
5140Sstevel@tonic-gate if ((fs->fs_magic != FS_MAGIC) && (fs->fs_magic != MTB_UFS_MAGIC)) {
5150Sstevel@tonic-gate if (!override) {
5160Sstevel@tonic-gate printf("%s: Bad magic number in file system\n",
5170Sstevel@tonic-gate special);
5180Sstevel@tonic-gate exit(1);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate printf("WARNING: Bad magic number in file system. ");
5220Sstevel@tonic-gate printf("Continue? (y/n): ");
5230Sstevel@tonic-gate (void) fflush(stdout);
5240Sstevel@tonic-gate if (gets(input_buffer) == NULL) {
5250Sstevel@tonic-gate exit(1);
5260Sstevel@tonic-gate }
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate if (*input_buffer != 'y' && *input_buffer != 'Y') {
5290Sstevel@tonic-gate exit(1);
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
533757Svsakar if ((fs->fs_magic == FS_MAGIC &&
534757Svsakar (fs->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
535757Svsakar fs->fs_version != UFS_VERSION_MIN)) ||
536757Svsakar (fs->fs_magic == MTB_UFS_MAGIC &&
5370Sstevel@tonic-gate (fs->fs_version > MTB_UFS_VERSION_1 ||
538757Svsakar fs->fs_version < MTB_UFS_VERSION_MIN))) {
5390Sstevel@tonic-gate if (!override) {
5400Sstevel@tonic-gate printf("%s: Unrecognized UFS version number: %d\n",
5410Sstevel@tonic-gate special, fs->fs_version);
5420Sstevel@tonic-gate exit(1);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate printf("WARNING: Unrecognized UFS version number. ");
5460Sstevel@tonic-gate printf("Continue? (y/n): ");
5470Sstevel@tonic-gate (void) fflush(stdout);
5480Sstevel@tonic-gate if (gets(input_buffer) == NULL) {
5490Sstevel@tonic-gate exit(1);
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate if (*input_buffer != 'y' && *input_buffer != 'Y') {
5530Sstevel@tonic-gate exit(1);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
5570Sstevel@tonic-gate if (fs->fs_postblformat == FS_42POSTBLFMT)
5580Sstevel@tonic-gate fs->fs_nrpos = 8;
5590Sstevel@tonic-gate #endif
5600Sstevel@tonic-gate printf("fsdb of %s %s -- last mounted on %s\n",
5610Sstevel@tonic-gate special,
5620Sstevel@tonic-gate (wrtflag == O_RDWR) ? "(Opened for write)" : "(Read only)",
5630Sstevel@tonic-gate &fs->fs_fsmnt[0]);
5640Sstevel@tonic-gate #ifdef sun
5650Sstevel@tonic-gate printf("fs_clean is currently set to ");
5660Sstevel@tonic-gate switch (fs->fs_clean) {
5670Sstevel@tonic-gate
5680Sstevel@tonic-gate case FSACTIVE:
5690Sstevel@tonic-gate printf("FSACTIVE\n");
5700Sstevel@tonic-gate break;
5710Sstevel@tonic-gate case FSCLEAN:
5720Sstevel@tonic-gate printf("FSCLEAN\n");
5730Sstevel@tonic-gate break;
5740Sstevel@tonic-gate case FSSTABLE:
5750Sstevel@tonic-gate printf("FSSTABLE\n");
5760Sstevel@tonic-gate break;
5770Sstevel@tonic-gate case FSBAD:
5780Sstevel@tonic-gate printf("FSBAD\n");
5790Sstevel@tonic-gate break;
5800Sstevel@tonic-gate case FSSUSPEND:
5810Sstevel@tonic-gate printf("FSSUSPEND\n");
5820Sstevel@tonic-gate break;
5830Sstevel@tonic-gate case FSLOG:
5840Sstevel@tonic-gate printf("FSLOG\n");
5850Sstevel@tonic-gate break;
5860Sstevel@tonic-gate case FSFIX:
5870Sstevel@tonic-gate printf("FSFIX\n");
5880Sstevel@tonic-gate if (!override) {
5890Sstevel@tonic-gate printf("%s: fsck may be running on this file system\n",
5900Sstevel@tonic-gate special);
5910Sstevel@tonic-gate exit(1);
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate
5940Sstevel@tonic-gate printf("WARNING: fsck may be running on this file system. ");
5950Sstevel@tonic-gate printf("Continue? (y/n): ");
5960Sstevel@tonic-gate (void) fflush(stdout);
5970Sstevel@tonic-gate if (gets(input_buffer) == NULL) {
5980Sstevel@tonic-gate exit(1);
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate if (*input_buffer != 'y' && *input_buffer != 'Y') {
6020Sstevel@tonic-gate exit(1);
6030Sstevel@tonic-gate }
6040Sstevel@tonic-gate break;
6050Sstevel@tonic-gate default:
6060Sstevel@tonic-gate printf("an unknown value (0x%x)\n", fs->fs_clean);
6070Sstevel@tonic-gate break;
6080Sstevel@tonic-gate }
6090Sstevel@tonic-gate
6100Sstevel@tonic-gate if (fs->fs_state == (FSOKAY - fs->fs_time)) {
6110Sstevel@tonic-gate printf("fs_state consistent (fs_clean CAN be trusted)\n");
6120Sstevel@tonic-gate } else {
6130Sstevel@tonic-gate printf("fs_state inconsistent (fs_clean CAN'T trusted)\n");
6140Sstevel@tonic-gate }
6150Sstevel@tonic-gate #endif /* sun */
6160Sstevel@tonic-gate /*
6170Sstevel@tonic-gate * Malloc buffers and set up cache.
6180Sstevel@tonic-gate */
6190Sstevel@tonic-gate buffers = malloc(NBUF * BLKSIZE);
6200Sstevel@tonic-gate bhdr.fwd = bhdr.back = &bhdr;
6210Sstevel@tonic-gate for (i = 0; i < NBUF; i++) {
6220Sstevel@tonic-gate bp = &lbuf[i];
6230Sstevel@tonic-gate bp->blkaddr = buffers + (i * BLKSIZE);
6240Sstevel@tonic-gate bp->valid = 0;
6250Sstevel@tonic-gate insert(bp);
6260Sstevel@tonic-gate }
6270Sstevel@tonic-gate /*
6280Sstevel@tonic-gate * Malloc filenames structure. The space for the actual filenames
6290Sstevel@tonic-gate * is allocated as it needs it. We estimate the size based on the
6300Sstevel@tonic-gate * number of inodes(objects) in the filesystem and the number of
6310Sstevel@tonic-gate * directories. The number of directories are padded by 3 because
6320Sstevel@tonic-gate * each directory traversed during a "find" or "ls -R" needs 3
6330Sstevel@tonic-gate * entries.
6340Sstevel@tonic-gate */
6350Sstevel@tonic-gate maxfiles = (long)((((u_offset_t)fs->fs_ncg * (u_offset_t)fs->fs_ipg) -
6360Sstevel@tonic-gate (u_offset_t)fs->fs_cstotal.cs_nifree) +
6370Sstevel@tonic-gate ((u_offset_t)fs->fs_cstotal.cs_ndir * (u_offset_t)3));
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate filenames = (struct filenames *)calloc(maxfiles,
6400Sstevel@tonic-gate sizeof (struct filenames));
6410Sstevel@tonic-gate if (filenames == NULL) {
6420Sstevel@tonic-gate /*
6430Sstevel@tonic-gate * If we could not allocate memory for all of files
6440Sstevel@tonic-gate * in the filesystem then, back off to the old fixed
6450Sstevel@tonic-gate * value.
6460Sstevel@tonic-gate */
6470Sstevel@tonic-gate maxfiles = MAXFILES;
6480Sstevel@tonic-gate filenames = (struct filenames *)calloc(maxfiles,
6490Sstevel@tonic-gate sizeof (struct filenames));
6500Sstevel@tonic-gate if (filenames == NULL) {
6510Sstevel@tonic-gate printf("out of memory\n");
6520Sstevel@tonic-gate exit(1);
6530Sstevel@tonic-gate }
6540Sstevel@tonic-gate }
6550Sstevel@tonic-gate
6560Sstevel@tonic-gate restore_inode(2);
6570Sstevel@tonic-gate /*
6580Sstevel@tonic-gate * Malloc a few filenames (needed by pwd for example).
6590Sstevel@tonic-gate */
6600Sstevel@tonic-gate for (i = 0; i < MAXPATHLEN; i++) {
6610Sstevel@tonic-gate input_path[i] = calloc(1, MAXNAMLEN);
6620Sstevel@tonic-gate stack_path[i] = calloc(1, MAXNAMLEN);
6630Sstevel@tonic-gate current_path[i] = calloc(1, MAXNAMLEN);
6640Sstevel@tonic-gate if (current_path[i] == NULL) {
6650Sstevel@tonic-gate printf("out of memory\n");
6660Sstevel@tonic-gate exit(1);
6670Sstevel@tonic-gate }
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate current_pathp = -1;
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate (void) signal(2, err);
6720Sstevel@tonic-gate (void) setjmp(env);
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate getnextinput();
6750Sstevel@tonic-gate /*
6760Sstevel@tonic-gate * Main loop and case statement. If an error condition occurs
6770Sstevel@tonic-gate * initialization and recovery is attempted.
6780Sstevel@tonic-gate */
6790Sstevel@tonic-gate for (;;) {
6800Sstevel@tonic-gate if (error) {
6810Sstevel@tonic-gate freemem(filenames, nfiles);
6820Sstevel@tonic-gate nfiles = 0;
6830Sstevel@tonic-gate c_count = 0;
6840Sstevel@tonic-gate count = 1;
6850Sstevel@tonic-gate star = 0;
6860Sstevel@tonic-gate error = 0;
6870Sstevel@tonic-gate paren = 0;
6880Sstevel@tonic-gate acting_on_inode = 0;
6890Sstevel@tonic-gate acting_on_directory = 0;
6900Sstevel@tonic-gate should_print = 1;
6910Sstevel@tonic-gate addr = erraddr;
6920Sstevel@tonic-gate cur_ino = errino;
6930Sstevel@tonic-gate cur_inum = errinum;
6940Sstevel@tonic-gate cur_bytes = errcur_bytes;
6950Sstevel@tonic-gate printf("?\n");
6960Sstevel@tonic-gate getnextinput();
6970Sstevel@tonic-gate if (error)
6980Sstevel@tonic-gate continue;
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate c_count++;
7010Sstevel@tonic-gate
7020Sstevel@tonic-gate switch (c = getachar()) {
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate case '\n': /* command end */
7050Sstevel@tonic-gate freemem(filenames, nfiles);
7060Sstevel@tonic-gate nfiles = 0;
7070Sstevel@tonic-gate if (should_print && laststyle == '=') {
7080Sstevel@tonic-gate ungetachar(c);
7090Sstevel@tonic-gate goto calc;
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate if (c_count == 1) {
7120Sstevel@tonic-gate clear = 0;
7130Sstevel@tonic-gate should_print = 1;
7140Sstevel@tonic-gate erraddr = addr;
7150Sstevel@tonic-gate errino = cur_ino;
7160Sstevel@tonic-gate errinum = cur_inum;
7170Sstevel@tonic-gate errcur_bytes = cur_bytes;
7180Sstevel@tonic-gate switch (objsz) {
7190Sstevel@tonic-gate case DIRECTORY:
7200Sstevel@tonic-gate if ((addr = getdirslot(
7210Sstevel@tonic-gate (long)dirslot+1)) == 0)
7220Sstevel@tonic-gate should_print = 0;
7230Sstevel@tonic-gate if (error) {
7240Sstevel@tonic-gate ungetachar(c);
7250Sstevel@tonic-gate continue;
7260Sstevel@tonic-gate }
7270Sstevel@tonic-gate break;
7280Sstevel@tonic-gate case INODE:
7290Sstevel@tonic-gate cur_inum++;
7300Sstevel@tonic-gate addr = itob(cur_inum);
7310Sstevel@tonic-gate if (!icheck(addr)) {
7320Sstevel@tonic-gate cur_inum--;
7330Sstevel@tonic-gate should_print = 0;
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate break;
7360Sstevel@tonic-gate case CGRP:
7370Sstevel@tonic-gate case SB:
7380Sstevel@tonic-gate cur_cgrp++;
7390Sstevel@tonic-gate addr = cgrp_check(cur_cgrp);
7400Sstevel@tonic-gate if (addr == 0) {
7410Sstevel@tonic-gate cur_cgrp--;
7420Sstevel@tonic-gate continue;
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate break;
7450Sstevel@tonic-gate case SHADOW_DATA:
7460Sstevel@tonic-gate if ((addr = getshadowslot(
7470Sstevel@tonic-gate (long)cur_shad + 1)) == 0)
7480Sstevel@tonic-gate should_print = 0;
7490Sstevel@tonic-gate if (error) {
7500Sstevel@tonic-gate ungetachar(c);
7510Sstevel@tonic-gate continue;
7520Sstevel@tonic-gate }
7530Sstevel@tonic-gate break;
7540Sstevel@tonic-gate default:
7550Sstevel@tonic-gate addr += objsz;
7560Sstevel@tonic-gate cur_bytes += objsz;
7570Sstevel@tonic-gate if (valid_addr() == 0)
7580Sstevel@tonic-gate continue;
7590Sstevel@tonic-gate }
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate if (type == NUMB)
7620Sstevel@tonic-gate trapped = 0;
7630Sstevel@tonic-gate if (should_print)
7640Sstevel@tonic-gate switch (objsz) {
7650Sstevel@tonic-gate case DIRECTORY:
7660Sstevel@tonic-gate fprnt('?', 'd');
7670Sstevel@tonic-gate break;
7680Sstevel@tonic-gate case INODE:
7690Sstevel@tonic-gate fprnt('?', 'i');
7700Sstevel@tonic-gate if (!error)
7710Sstevel@tonic-gate cur_ino = addr;
7720Sstevel@tonic-gate break;
7730Sstevel@tonic-gate case CGRP:
7740Sstevel@tonic-gate fprnt('?', 'c');
7750Sstevel@tonic-gate break;
7760Sstevel@tonic-gate case SB:
7770Sstevel@tonic-gate fprnt('?', 's');
7780Sstevel@tonic-gate break;
7790Sstevel@tonic-gate case SHADOW_DATA:
7800Sstevel@tonic-gate fprnt('?', 'S');
7810Sstevel@tonic-gate break;
7820Sstevel@tonic-gate case CHAR:
7830Sstevel@tonic-gate case SHORT:
7840Sstevel@tonic-gate case LONG:
7850Sstevel@tonic-gate fprnt(laststyle, lastpo);
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate if (error) {
7880Sstevel@tonic-gate ungetachar(c);
7890Sstevel@tonic-gate continue;
7900Sstevel@tonic-gate }
7910Sstevel@tonic-gate c_count = colon = acting_on_inode = 0;
7920Sstevel@tonic-gate acting_on_directory = 0;
7930Sstevel@tonic-gate should_print = 1;
7940Sstevel@tonic-gate getnextinput();
7950Sstevel@tonic-gate if (error)
7960Sstevel@tonic-gate continue;
7970Sstevel@tonic-gate erraddr = addr;
7980Sstevel@tonic-gate errino = cur_ino;
7990Sstevel@tonic-gate errinum = cur_inum;
8000Sstevel@tonic-gate errcur_bytes = cur_bytes;
8010Sstevel@tonic-gate continue;
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate case '(': /* numeric expression or unknown command */
8040Sstevel@tonic-gate default:
8050Sstevel@tonic-gate colon = 0;
8060Sstevel@tonic-gate if (digit(c) || c == '(') {
8070Sstevel@tonic-gate ungetachar(c);
8080Sstevel@tonic-gate addr = expr();
8090Sstevel@tonic-gate type = NUMB;
8100Sstevel@tonic-gate value = addr;
8110Sstevel@tonic-gate continue;
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate printf("unknown command or bad syntax\n");
8140Sstevel@tonic-gate error++;
8150Sstevel@tonic-gate continue;
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate case '?': /* general print facilities */
8180Sstevel@tonic-gate case '/':
8190Sstevel@tonic-gate fprnt(c, getachar());
8200Sstevel@tonic-gate continue;
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate case ';': /* command separator and . */
8230Sstevel@tonic-gate case '\t':
8240Sstevel@tonic-gate case ' ':
8250Sstevel@tonic-gate case '.':
8260Sstevel@tonic-gate continue;
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate case ':': /* command indicator */
8290Sstevel@tonic-gate colon++;
8300Sstevel@tonic-gate commands++;
8310Sstevel@tonic-gate should_print = 0;
8320Sstevel@tonic-gate stringsize = 0;
8330Sstevel@tonic-gate trapped = 0;
8340Sstevel@tonic-gate continue;
8350Sstevel@tonic-gate
8360Sstevel@tonic-gate case ',': /* count indicator */
8370Sstevel@tonic-gate colon = star = 0;
8380Sstevel@tonic-gate if ((c = getachar()) == '*') {
8390Sstevel@tonic-gate star = 1;
8400Sstevel@tonic-gate count = BLKSIZE;
8410Sstevel@tonic-gate } else {
8420Sstevel@tonic-gate ungetachar(c);
8430Sstevel@tonic-gate count = expr();
8440Sstevel@tonic-gate if (error)
8450Sstevel@tonic-gate continue;
8460Sstevel@tonic-gate if (!count)
8470Sstevel@tonic-gate count = 1;
8480Sstevel@tonic-gate }
8490Sstevel@tonic-gate clear = 0;
8500Sstevel@tonic-gate continue;
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate case '+': /* address addition */
8530Sstevel@tonic-gate colon = 0;
8540Sstevel@tonic-gate c = getachar();
8550Sstevel@tonic-gate ungetachar(c);
8560Sstevel@tonic-gate if (c == '\n')
8570Sstevel@tonic-gate temp = 1;
8580Sstevel@tonic-gate else {
8590Sstevel@tonic-gate temp = expr();
8600Sstevel@tonic-gate if (error)
8610Sstevel@tonic-gate continue;
8620Sstevel@tonic-gate }
8630Sstevel@tonic-gate erraddr = addr;
8640Sstevel@tonic-gate errcur_bytes = cur_bytes;
8650Sstevel@tonic-gate switch (objsz) {
8660Sstevel@tonic-gate case DIRECTORY:
8670Sstevel@tonic-gate addr = getdirslot((long)(dirslot + temp));
8680Sstevel@tonic-gate if (error)
8690Sstevel@tonic-gate continue;
8700Sstevel@tonic-gate break;
8710Sstevel@tonic-gate case INODE:
8720Sstevel@tonic-gate cur_inum += temp;
8730Sstevel@tonic-gate addr = itob(cur_inum);
8740Sstevel@tonic-gate if (!icheck(addr)) {
8750Sstevel@tonic-gate cur_inum -= temp;
8760Sstevel@tonic-gate continue;
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate break;
8790Sstevel@tonic-gate case CGRP:
8800Sstevel@tonic-gate case SB:
8810Sstevel@tonic-gate cur_cgrp += temp;
8820Sstevel@tonic-gate if ((addr = cgrp_check(cur_cgrp)) == 0) {
8830Sstevel@tonic-gate cur_cgrp -= temp;
8840Sstevel@tonic-gate continue;
8850Sstevel@tonic-gate }
8860Sstevel@tonic-gate break;
8870Sstevel@tonic-gate case SHADOW_DATA:
8880Sstevel@tonic-gate addr = getshadowslot((long)(cur_shad + temp));
8890Sstevel@tonic-gate if (error)
8900Sstevel@tonic-gate continue;
8910Sstevel@tonic-gate break;
8920Sstevel@tonic-gate
8930Sstevel@tonic-gate default:
8940Sstevel@tonic-gate laststyle = '/';
8950Sstevel@tonic-gate addr += temp * objsz;
8960Sstevel@tonic-gate cur_bytes += temp * objsz;
8970Sstevel@tonic-gate if (valid_addr() == 0)
8980Sstevel@tonic-gate continue;
8990Sstevel@tonic-gate }
9000Sstevel@tonic-gate value = get(objsz);
9010Sstevel@tonic-gate continue;
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate case '-': /* address subtraction */
9040Sstevel@tonic-gate colon = 0;
9050Sstevel@tonic-gate c = getachar();
9060Sstevel@tonic-gate ungetachar(c);
9070Sstevel@tonic-gate if (c == '\n')
9080Sstevel@tonic-gate temp = 1;
9090Sstevel@tonic-gate else {
9100Sstevel@tonic-gate temp = expr();
9110Sstevel@tonic-gate if (error)
9120Sstevel@tonic-gate continue;
9130Sstevel@tonic-gate }
9140Sstevel@tonic-gate erraddr = addr;
9150Sstevel@tonic-gate errcur_bytes = cur_bytes;
9160Sstevel@tonic-gate switch (objsz) {
9170Sstevel@tonic-gate case DIRECTORY:
9180Sstevel@tonic-gate addr = getdirslot((long)(dirslot - temp));
9190Sstevel@tonic-gate if (error)
9200Sstevel@tonic-gate continue;
9210Sstevel@tonic-gate break;
9220Sstevel@tonic-gate case INODE:
9230Sstevel@tonic-gate cur_inum -= temp;
9240Sstevel@tonic-gate addr = itob(cur_inum);
9250Sstevel@tonic-gate if (!icheck(addr)) {
9260Sstevel@tonic-gate cur_inum += temp;
9270Sstevel@tonic-gate continue;
9280Sstevel@tonic-gate }
9290Sstevel@tonic-gate break;
9300Sstevel@tonic-gate case CGRP:
9310Sstevel@tonic-gate case SB:
9320Sstevel@tonic-gate cur_cgrp -= temp;
9330Sstevel@tonic-gate if ((addr = cgrp_check(cur_cgrp)) == 0) {
9340Sstevel@tonic-gate cur_cgrp += temp;
9350Sstevel@tonic-gate continue;
9360Sstevel@tonic-gate }
9370Sstevel@tonic-gate break;
9380Sstevel@tonic-gate case SHADOW_DATA:
9390Sstevel@tonic-gate addr = getshadowslot((long)(cur_shad - temp));
9400Sstevel@tonic-gate if (error)
9410Sstevel@tonic-gate continue;
9420Sstevel@tonic-gate break;
9430Sstevel@tonic-gate default:
9440Sstevel@tonic-gate laststyle = '/';
9450Sstevel@tonic-gate addr -= temp * objsz;
9460Sstevel@tonic-gate cur_bytes -= temp * objsz;
9470Sstevel@tonic-gate if (valid_addr() == 0)
9480Sstevel@tonic-gate continue;
9490Sstevel@tonic-gate }
9500Sstevel@tonic-gate value = get(objsz);
9510Sstevel@tonic-gate continue;
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate case '*': /* address multiplication */
9540Sstevel@tonic-gate colon = 0;
9550Sstevel@tonic-gate temp = expr();
9560Sstevel@tonic-gate if (error)
9570Sstevel@tonic-gate continue;
9580Sstevel@tonic-gate if (objsz != INODE && objsz != DIRECTORY)
9590Sstevel@tonic-gate laststyle = '/';
9600Sstevel@tonic-gate addr *= temp;
9610Sstevel@tonic-gate value = get(objsz);
9620Sstevel@tonic-gate continue;
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate case '%': /* address division */
9650Sstevel@tonic-gate colon = 0;
9660Sstevel@tonic-gate temp = expr();
9670Sstevel@tonic-gate if (error)
9680Sstevel@tonic-gate continue;
9690Sstevel@tonic-gate if (!temp) {
9700Sstevel@tonic-gate printf("divide by zero\n");
9710Sstevel@tonic-gate error++;
9720Sstevel@tonic-gate continue;
9730Sstevel@tonic-gate }
9740Sstevel@tonic-gate if (objsz != INODE && objsz != DIRECTORY)
9750Sstevel@tonic-gate laststyle = '/';
9760Sstevel@tonic-gate addr /= temp;
9770Sstevel@tonic-gate value = get(objsz);
9780Sstevel@tonic-gate continue;
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate case '=': { /* assignment operation */
9810Sstevel@tonic-gate short tbase;
9820Sstevel@tonic-gate calc:
9830Sstevel@tonic-gate tbase = base;
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate c = getachar();
9860Sstevel@tonic-gate if (c == '\n') {
9870Sstevel@tonic-gate ungetachar(c);
9880Sstevel@tonic-gate c = lastpo;
9890Sstevel@tonic-gate if (acting_on_inode == 1) {
9900Sstevel@tonic-gate if (c != 'o' && c != 'd' && c != 'x' &&
9910Sstevel@tonic-gate c != 'O' && c != 'D' && c != 'X') {
9920Sstevel@tonic-gate switch (objsz) {
9930Sstevel@tonic-gate case LONG:
9940Sstevel@tonic-gate c = lastpo = 'X';
9950Sstevel@tonic-gate break;
9960Sstevel@tonic-gate case SHORT:
9970Sstevel@tonic-gate c = lastpo = 'x';
9980Sstevel@tonic-gate break;
9990Sstevel@tonic-gate case CHAR:
10000Sstevel@tonic-gate c = lastpo = 'c';
10010Sstevel@tonic-gate }
10020Sstevel@tonic-gate }
10030Sstevel@tonic-gate } else {
10040Sstevel@tonic-gate if (acting_on_inode == 2)
10050Sstevel@tonic-gate c = lastpo = 't';
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate } else if (acting_on_inode)
10080Sstevel@tonic-gate lastpo = c;
10090Sstevel@tonic-gate should_print = star = 0;
10100Sstevel@tonic-gate count = 1;
10110Sstevel@tonic-gate erraddr = addr;
10120Sstevel@tonic-gate errcur_bytes = cur_bytes;
10130Sstevel@tonic-gate switch (c) {
10140Sstevel@tonic-gate case '"': /* character string */
10150Sstevel@tonic-gate if (type == NUMB) {
10160Sstevel@tonic-gate blocksize = BLKSIZE;
10170Sstevel@tonic-gate filesize = BLKSIZE * 2;
10180Sstevel@tonic-gate cur_bytes = blkoff(fs, addr);
10190Sstevel@tonic-gate if (objsz == DIRECTORY ||
10200Sstevel@tonic-gate objsz == INODE)
10210Sstevel@tonic-gate lastpo = 'X';
10220Sstevel@tonic-gate }
10230Sstevel@tonic-gate puta();
10240Sstevel@tonic-gate continue;
10250Sstevel@tonic-gate case '+': /* =+ operator */
10260Sstevel@tonic-gate temp = expr();
10270Sstevel@tonic-gate value = get(objsz);
10280Sstevel@tonic-gate if (!error)
10290Sstevel@tonic-gate put(value+temp, objsz);
10300Sstevel@tonic-gate continue;
10310Sstevel@tonic-gate case '-': /* =- operator */
10320Sstevel@tonic-gate temp = expr();
10330Sstevel@tonic-gate value = get(objsz);
10340Sstevel@tonic-gate if (!error)
10350Sstevel@tonic-gate put(value-temp, objsz);
10360Sstevel@tonic-gate continue;
10370Sstevel@tonic-gate case 'b':
10380Sstevel@tonic-gate case 'c':
10390Sstevel@tonic-gate if (objsz == CGRP)
10400Sstevel@tonic-gate fprnt('?', c);
10410Sstevel@tonic-gate else
10420Sstevel@tonic-gate fprnt('/', c);
10430Sstevel@tonic-gate continue;
10440Sstevel@tonic-gate case 'i':
10450Sstevel@tonic-gate addr = cur_ino;
10460Sstevel@tonic-gate fprnt('?', 'i');
10470Sstevel@tonic-gate continue;
10480Sstevel@tonic-gate case 's':
10490Sstevel@tonic-gate fprnt('?', 's');
10500Sstevel@tonic-gate continue;
10510Sstevel@tonic-gate case 't':
10520Sstevel@tonic-gate case 'T':
10530Sstevel@tonic-gate laststyle = '=';
10540Sstevel@tonic-gate printf("\t\t");
10550Sstevel@tonic-gate {
10560Sstevel@tonic-gate /*
10570Sstevel@tonic-gate * Truncation is intentional so
10580Sstevel@tonic-gate * ctime is happy.
10590Sstevel@tonic-gate */
10600Sstevel@tonic-gate time_t tvalue = (time_t)value;
10610Sstevel@tonic-gate printf("%s", ctime(&tvalue));
10620Sstevel@tonic-gate }
10630Sstevel@tonic-gate continue;
10640Sstevel@tonic-gate case 'o':
10650Sstevel@tonic-gate base = OCTAL;
10660Sstevel@tonic-gate goto otx;
10670Sstevel@tonic-gate case 'd':
10680Sstevel@tonic-gate if (objsz == DIRECTORY) {
10690Sstevel@tonic-gate addr = cur_dir;
10700Sstevel@tonic-gate fprnt('?', 'd');
10710Sstevel@tonic-gate continue;
10720Sstevel@tonic-gate }
10730Sstevel@tonic-gate base = DECIMAL;
10740Sstevel@tonic-gate goto otx;
10750Sstevel@tonic-gate case 'x':
10760Sstevel@tonic-gate base = HEX;
10770Sstevel@tonic-gate otx:
10780Sstevel@tonic-gate laststyle = '=';
10790Sstevel@tonic-gate printf("\t\t");
10800Sstevel@tonic-gate if (acting_on_inode)
10810Sstevel@tonic-gate print(value & 0177777L, 12, -8, 0);
10820Sstevel@tonic-gate else
10830Sstevel@tonic-gate print(addr & 0177777L, 12, -8, 0);
10840Sstevel@tonic-gate printf("\n");
10850Sstevel@tonic-gate base = tbase;
10860Sstevel@tonic-gate continue;
10870Sstevel@tonic-gate case 'O':
10880Sstevel@tonic-gate base = OCTAL;
10890Sstevel@tonic-gate goto OTX;
10900Sstevel@tonic-gate case 'D':
10910Sstevel@tonic-gate base = DECIMAL;
10920Sstevel@tonic-gate goto OTX;
10930Sstevel@tonic-gate case 'X':
10940Sstevel@tonic-gate base = HEX;
10950Sstevel@tonic-gate OTX:
10960Sstevel@tonic-gate laststyle = '=';
10970Sstevel@tonic-gate printf("\t\t");
10980Sstevel@tonic-gate if (acting_on_inode)
10990Sstevel@tonic-gate print(value, 12, -8, 0);
11000Sstevel@tonic-gate else
11010Sstevel@tonic-gate print(addr, 12, -8, 0);
11020Sstevel@tonic-gate printf("\n");
11030Sstevel@tonic-gate base = tbase;
11040Sstevel@tonic-gate continue;
11050Sstevel@tonic-gate default: /* regular assignment */
11060Sstevel@tonic-gate ungetachar(c);
11070Sstevel@tonic-gate value = expr();
11080Sstevel@tonic-gate if (error)
11090Sstevel@tonic-gate printf("syntax error\n");
11100Sstevel@tonic-gate else
11110Sstevel@tonic-gate put(value, objsz);
11120Sstevel@tonic-gate continue;
11130Sstevel@tonic-gate }
11140Sstevel@tonic-gate }
11150Sstevel@tonic-gate
11160Sstevel@tonic-gate case '>': /* save current address */
11170Sstevel@tonic-gate colon = 0;
11180Sstevel@tonic-gate should_print = 0;
11190Sstevel@tonic-gate c = getachar();
11200Sstevel@tonic-gate if (!letter(c) && !digit(c)) {
11210Sstevel@tonic-gate printf("invalid register specification, ");
11220Sstevel@tonic-gate printf("must be letter or digit\n");
11230Sstevel@tonic-gate error++;
11240Sstevel@tonic-gate continue;
11250Sstevel@tonic-gate }
11260Sstevel@tonic-gate if (letter(c)) {
11270Sstevel@tonic-gate if (c < 'a')
11280Sstevel@tonic-gate c = uppertolower(c);
11290Sstevel@tonic-gate c = hextodigit(c);
11300Sstevel@tonic-gate } else
11310Sstevel@tonic-gate c = numtodigit(c);
11320Sstevel@tonic-gate regs[c].sv_addr = addr;
11330Sstevel@tonic-gate regs[c].sv_value = value;
11340Sstevel@tonic-gate regs[c].sv_objsz = objsz;
11350Sstevel@tonic-gate continue;
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate case '<': /* restore saved address */
11380Sstevel@tonic-gate colon = 0;
11390Sstevel@tonic-gate should_print = 0;
11400Sstevel@tonic-gate c = getachar();
11410Sstevel@tonic-gate if (!letter(c) && !digit(c)) {
11420Sstevel@tonic-gate printf("invalid register specification, ");
11430Sstevel@tonic-gate printf("must be letter or digit\n");
11440Sstevel@tonic-gate error++;
11450Sstevel@tonic-gate continue;
11460Sstevel@tonic-gate }
11470Sstevel@tonic-gate if (letter(c)) {
11480Sstevel@tonic-gate if (c < 'a')
11490Sstevel@tonic-gate c = uppertolower(c);
11500Sstevel@tonic-gate c = hextodigit(c);
11510Sstevel@tonic-gate } else
11520Sstevel@tonic-gate c = numtodigit(c);
11530Sstevel@tonic-gate addr = regs[c].sv_addr;
11540Sstevel@tonic-gate value = regs[c].sv_value;
11550Sstevel@tonic-gate objsz = regs[c].sv_objsz;
11560Sstevel@tonic-gate continue;
11570Sstevel@tonic-gate
11580Sstevel@tonic-gate case 'a':
11590Sstevel@tonic-gate if (colon)
11600Sstevel@tonic-gate colon = 0;
11610Sstevel@tonic-gate else
11620Sstevel@tonic-gate goto no_colon;
11630Sstevel@tonic-gate if (match("at", 2)) { /* access time */
11640Sstevel@tonic-gate acting_on_inode = 2;
11650Sstevel@tonic-gate should_print = 1;
11661051Smaheshvs addr = (long)&((struct dinode *)
11671051Smaheshvs (uintptr_t)cur_ino)->di_atime;
11680Sstevel@tonic-gate value = get(LONG);
11690Sstevel@tonic-gate type = NULL;
11700Sstevel@tonic-gate continue;
11710Sstevel@tonic-gate }
11720Sstevel@tonic-gate goto bad_syntax;
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate case 'b':
11750Sstevel@tonic-gate if (colon)
11760Sstevel@tonic-gate colon = 0;
11770Sstevel@tonic-gate else
11780Sstevel@tonic-gate goto no_colon;
11790Sstevel@tonic-gate if (match("block", 2)) { /* block conversion */
11800Sstevel@tonic-gate if (type == NUMB) {
11810Sstevel@tonic-gate value = addr;
11820Sstevel@tonic-gate cur_bytes = 0;
11830Sstevel@tonic-gate blocksize = BLKSIZE;
11840Sstevel@tonic-gate filesize = BLKSIZE * 2;
11850Sstevel@tonic-gate }
11860Sstevel@tonic-gate addr = value << FRGSHIFT;
11870Sstevel@tonic-gate bod_addr = addr;
11880Sstevel@tonic-gate value = get(LONG);
11890Sstevel@tonic-gate type = BLOCK;
11900Sstevel@tonic-gate dirslot = 0;
11910Sstevel@tonic-gate trapped++;
11920Sstevel@tonic-gate continue;
11930Sstevel@tonic-gate }
11940Sstevel@tonic-gate if (match("bs", 2)) { /* block size */
11950Sstevel@tonic-gate acting_on_inode = 1;
11960Sstevel@tonic-gate should_print = 1;
11970Sstevel@tonic-gate if (icheck(cur_ino) == 0)
11980Sstevel@tonic-gate continue;
11991051Smaheshvs addr = (long)&((struct dinode *)
12001051Smaheshvs (uintptr_t)cur_ino)->di_blocks;
12010Sstevel@tonic-gate value = get(LONG);
12020Sstevel@tonic-gate type = NULL;
12030Sstevel@tonic-gate continue;
12040Sstevel@tonic-gate }
12050Sstevel@tonic-gate if (match("base", 2)) { /* change/show base */
12060Sstevel@tonic-gate showbase:
12070Sstevel@tonic-gate if ((c = getachar()) == '\n') {
12080Sstevel@tonic-gate ungetachar(c);
12090Sstevel@tonic-gate printf("base =\t\t");
12100Sstevel@tonic-gate switch (base) {
12110Sstevel@tonic-gate case OCTAL:
12120Sstevel@tonic-gate printf("OCTAL\n");
12130Sstevel@tonic-gate continue;
12140Sstevel@tonic-gate case DECIMAL:
12150Sstevel@tonic-gate printf("DECIMAL\n");
12160Sstevel@tonic-gate continue;
12170Sstevel@tonic-gate case HEX:
12180Sstevel@tonic-gate printf("HEX\n");
12190Sstevel@tonic-gate continue;
12200Sstevel@tonic-gate }
12210Sstevel@tonic-gate }
12220Sstevel@tonic-gate if (c != '=') {
12230Sstevel@tonic-gate printf("missing '='\n");
12240Sstevel@tonic-gate error++;
12250Sstevel@tonic-gate continue;
12260Sstevel@tonic-gate }
12270Sstevel@tonic-gate value = expr();
12280Sstevel@tonic-gate switch (value) {
12290Sstevel@tonic-gate default:
12300Sstevel@tonic-gate printf("invalid base\n");
12310Sstevel@tonic-gate error++;
12320Sstevel@tonic-gate break;
12330Sstevel@tonic-gate case OCTAL:
12340Sstevel@tonic-gate case DECIMAL:
12350Sstevel@tonic-gate case HEX:
12360Sstevel@tonic-gate base = (short)value;
12370Sstevel@tonic-gate }
12380Sstevel@tonic-gate goto showbase;
12390Sstevel@tonic-gate }
12400Sstevel@tonic-gate goto bad_syntax;
12410Sstevel@tonic-gate
12420Sstevel@tonic-gate case 'c':
12430Sstevel@tonic-gate if (colon)
12440Sstevel@tonic-gate colon = 0;
12450Sstevel@tonic-gate else
12460Sstevel@tonic-gate goto no_colon;
12470Sstevel@tonic-gate if (match("cd", 2)) { /* change directory */
12480Sstevel@tonic-gate top = filenames - 1;
12490Sstevel@tonic-gate eat_spaces();
12500Sstevel@tonic-gate if ((c = getachar()) == '\n') {
12510Sstevel@tonic-gate ungetachar(c);
12520Sstevel@tonic-gate current_pathp = -1;
12530Sstevel@tonic-gate restore_inode(2);
12540Sstevel@tonic-gate continue;
12550Sstevel@tonic-gate }
12560Sstevel@tonic-gate ungetachar(c);
12570Sstevel@tonic-gate temp = cur_inum;
12580Sstevel@tonic-gate doing_cd = 1;
12590Sstevel@tonic-gate parse();
12600Sstevel@tonic-gate doing_cd = 0;
12610Sstevel@tonic-gate if (nfiles != 1) {
12620Sstevel@tonic-gate restore_inode((ino_t)temp);
12630Sstevel@tonic-gate if (!error) {
12640Sstevel@tonic-gate print_path(input_path,
12650Sstevel@tonic-gate (int)input_pathp);
12660Sstevel@tonic-gate if (nfiles == 0)
12670Sstevel@tonic-gate printf(" not found\n");
12680Sstevel@tonic-gate else
12690Sstevel@tonic-gate printf(" ambiguous\n");
12700Sstevel@tonic-gate error++;
12710Sstevel@tonic-gate }
12720Sstevel@tonic-gate continue;
12730Sstevel@tonic-gate }
12740Sstevel@tonic-gate restore_inode(filenames->ino);
12750Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
12760Sstevel@tonic-gate continue;
12770Sstevel@tonic-gate if ((mode & IFMT) != IFDIR) {
12780Sstevel@tonic-gate restore_inode((ino_t)temp);
12790Sstevel@tonic-gate print_path(input_path,
12800Sstevel@tonic-gate (int)input_pathp);
12810Sstevel@tonic-gate printf(" not a directory\n");
12820Sstevel@tonic-gate error++;
12830Sstevel@tonic-gate continue;
12840Sstevel@tonic-gate }
12850Sstevel@tonic-gate for (i = 0; i <= top->len; i++)
12860Sstevel@tonic-gate (void) strcpy(current_path[i],
12870Sstevel@tonic-gate top->fname[i]);
12880Sstevel@tonic-gate current_pathp = top->len;
12890Sstevel@tonic-gate continue;
12900Sstevel@tonic-gate }
12910Sstevel@tonic-gate if (match("cg", 2)) { /* cylinder group */
12920Sstevel@tonic-gate if (type == NUMB)
12930Sstevel@tonic-gate value = addr;
12940Sstevel@tonic-gate if (value > fs->fs_ncg - 1) {
12950Sstevel@tonic-gate printf("maximum cylinder group is ");
12960Sstevel@tonic-gate print(fs->fs_ncg - 1, 8, -8, 0);
12970Sstevel@tonic-gate printf("\n");
12980Sstevel@tonic-gate error++;
12990Sstevel@tonic-gate continue;
13000Sstevel@tonic-gate }
13010Sstevel@tonic-gate type = objsz = CGRP;
13020Sstevel@tonic-gate cur_cgrp = (long)value;
13030Sstevel@tonic-gate addr = cgtod(fs, cur_cgrp) << FRGSHIFT;
13040Sstevel@tonic-gate continue;
13050Sstevel@tonic-gate }
13060Sstevel@tonic-gate if (match("ct", 2)) { /* creation time */
13070Sstevel@tonic-gate acting_on_inode = 2;
13080Sstevel@tonic-gate should_print = 1;
13091051Smaheshvs addr = (long)&((struct dinode *)
13101051Smaheshvs (uintptr_t)cur_ino)->di_ctime;
13110Sstevel@tonic-gate value = get(LONG);
13120Sstevel@tonic-gate type = NULL;
13130Sstevel@tonic-gate continue;
13140Sstevel@tonic-gate }
13150Sstevel@tonic-gate goto bad_syntax;
13160Sstevel@tonic-gate
13170Sstevel@tonic-gate case 'd':
13180Sstevel@tonic-gate if (colon)
13190Sstevel@tonic-gate colon = 0;
13200Sstevel@tonic-gate else
13210Sstevel@tonic-gate goto no_colon;
13220Sstevel@tonic-gate if (match("directory", 2)) { /* directory offsets */
13230Sstevel@tonic-gate if (type == NUMB)
13240Sstevel@tonic-gate value = addr;
13250Sstevel@tonic-gate objsz = DIRECTORY;
13260Sstevel@tonic-gate type = DIRECTORY;
13270Sstevel@tonic-gate addr = (u_offset_t)getdirslot((long)value);
13280Sstevel@tonic-gate continue;
13290Sstevel@tonic-gate }
13300Sstevel@tonic-gate if (match("db", 2)) { /* direct block */
13310Sstevel@tonic-gate acting_on_inode = 1;
13320Sstevel@tonic-gate should_print = 1;
13330Sstevel@tonic-gate if (type == NUMB)
13340Sstevel@tonic-gate value = addr;
13350Sstevel@tonic-gate if (value >= NDADDR) {
13360Sstevel@tonic-gate printf("direct blocks are 0 to ");
13370Sstevel@tonic-gate print(NDADDR - 1, 0, 0, 0);
13380Sstevel@tonic-gate printf("\n");
13390Sstevel@tonic-gate error++;
13400Sstevel@tonic-gate continue;
13410Sstevel@tonic-gate }
13420Sstevel@tonic-gate addr = cur_ino;
13430Sstevel@tonic-gate if (!icheck(addr))
13440Sstevel@tonic-gate continue;
13450Sstevel@tonic-gate addr = (long)
13461051Smaheshvs &((struct dinode *)(uintptr_t)cur_ino)->
13470Sstevel@tonic-gate di_db[value];
13480Sstevel@tonic-gate bod_addr = addr;
13490Sstevel@tonic-gate cur_bytes = (value) * BLKSIZE;
13500Sstevel@tonic-gate cur_block = (long)value;
13510Sstevel@tonic-gate type = BLOCK;
13520Sstevel@tonic-gate dirslot = 0;
13530Sstevel@tonic-gate value = get(LONG);
13540Sstevel@tonic-gate if (!value && !override) {
13550Sstevel@tonic-gate printf("non existent block\n");
13560Sstevel@tonic-gate error++;
13570Sstevel@tonic-gate }
13580Sstevel@tonic-gate continue;
13590Sstevel@tonic-gate }
13600Sstevel@tonic-gate goto bad_syntax;
13610Sstevel@tonic-gate
13620Sstevel@tonic-gate case 'f':
13630Sstevel@tonic-gate if (colon)
13640Sstevel@tonic-gate colon = 0;
13650Sstevel@tonic-gate else
13660Sstevel@tonic-gate goto no_colon;
13670Sstevel@tonic-gate if (match("find", 3)) { /* find command */
13680Sstevel@tonic-gate find();
13690Sstevel@tonic-gate continue;
13700Sstevel@tonic-gate }
13710Sstevel@tonic-gate if (match("fragment", 2)) { /* fragment conv. */
13720Sstevel@tonic-gate if (type == NUMB) {
13730Sstevel@tonic-gate value = addr;
13740Sstevel@tonic-gate cur_bytes = 0;
13750Sstevel@tonic-gate blocksize = FRGSIZE;
13760Sstevel@tonic-gate filesize = FRGSIZE * 2;
13770Sstevel@tonic-gate }
13780Sstevel@tonic-gate if (min(blocksize, filesize) - cur_bytes >
13790Sstevel@tonic-gate FRGSIZE) {
13800Sstevel@tonic-gate blocksize = cur_bytes + FRGSIZE;
13810Sstevel@tonic-gate filesize = blocksize * 2;
13820Sstevel@tonic-gate }
13830Sstevel@tonic-gate addr = value << FRGSHIFT;
13840Sstevel@tonic-gate bod_addr = addr;
13850Sstevel@tonic-gate value = get(LONG);
13860Sstevel@tonic-gate type = FRAGMENT;
13870Sstevel@tonic-gate dirslot = 0;
13880Sstevel@tonic-gate trapped++;
13890Sstevel@tonic-gate continue;
13900Sstevel@tonic-gate }
13910Sstevel@tonic-gate if (match("file", 4)) { /* access as file */
13920Sstevel@tonic-gate acting_on_inode = 1;
13930Sstevel@tonic-gate should_print = 1;
13940Sstevel@tonic-gate if (type == NUMB)
13950Sstevel@tonic-gate value = addr;
13960Sstevel@tonic-gate addr = cur_ino;
13970Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
13980Sstevel@tonic-gate continue;
13990Sstevel@tonic-gate if (!override) {
14000Sstevel@tonic-gate switch (mode & IFMT) {
14010Sstevel@tonic-gate case IFCHR:
14020Sstevel@tonic-gate case IFBLK:
14030Sstevel@tonic-gate printf("special device\n");
14040Sstevel@tonic-gate error++;
14050Sstevel@tonic-gate continue;
14060Sstevel@tonic-gate }
14070Sstevel@tonic-gate }
14080Sstevel@tonic-gate if ((addr = (u_offset_t)
14090Sstevel@tonic-gate (bmap((long)value) << FRGSHIFT)) == 0)
14100Sstevel@tonic-gate continue;
14110Sstevel@tonic-gate cur_block = (long)value;
14120Sstevel@tonic-gate bod_addr = addr;
14130Sstevel@tonic-gate type = BLOCK;
14140Sstevel@tonic-gate dirslot = 0;
14150Sstevel@tonic-gate continue;
14160Sstevel@tonic-gate }
14170Sstevel@tonic-gate if (match("fill", 4)) { /* fill */
14180Sstevel@tonic-gate if (getachar() != '=') {
14190Sstevel@tonic-gate printf("missing '='\n");
14200Sstevel@tonic-gate error++;
14210Sstevel@tonic-gate continue;
14220Sstevel@tonic-gate }
14230Sstevel@tonic-gate if (objsz == INODE || objsz == DIRECTORY ||
14240Sstevel@tonic-gate objsz == SHADOW_DATA) {
14250Sstevel@tonic-gate printf(
14260Sstevel@tonic-gate "can't fill inode or directory\n");
14270Sstevel@tonic-gate error++;
14280Sstevel@tonic-gate continue;
14290Sstevel@tonic-gate }
14300Sstevel@tonic-gate fill();
14310Sstevel@tonic-gate continue;
14320Sstevel@tonic-gate }
14330Sstevel@tonic-gate goto bad_syntax;
14340Sstevel@tonic-gate
14350Sstevel@tonic-gate case 'g':
14360Sstevel@tonic-gate if (colon)
14370Sstevel@tonic-gate colon = 0;
14380Sstevel@tonic-gate else
14390Sstevel@tonic-gate goto no_colon;
14400Sstevel@tonic-gate if (match("gid", 1)) { /* group id */
14410Sstevel@tonic-gate acting_on_inode = 1;
14420Sstevel@tonic-gate should_print = 1;
14431051Smaheshvs addr = (long)&((struct dinode *)
14441051Smaheshvs (uintptr_t)cur_ino)->di_gid;
14450Sstevel@tonic-gate value = get(SHORT);
14460Sstevel@tonic-gate type = NULL;
14470Sstevel@tonic-gate continue;
14480Sstevel@tonic-gate }
14490Sstevel@tonic-gate goto bad_syntax;
14500Sstevel@tonic-gate
14510Sstevel@tonic-gate case 'i':
14520Sstevel@tonic-gate if (colon)
14530Sstevel@tonic-gate colon = 0;
14540Sstevel@tonic-gate else
14550Sstevel@tonic-gate goto no_colon;
14560Sstevel@tonic-gate if (match("inode", 2)) { /* i# to inode conversion */
14570Sstevel@tonic-gate if (c_count == 2) {
14580Sstevel@tonic-gate addr = cur_ino;
14590Sstevel@tonic-gate value = get(INODE);
14600Sstevel@tonic-gate type = NULL;
14610Sstevel@tonic-gate laststyle = '=';
14620Sstevel@tonic-gate lastpo = 'i';
14630Sstevel@tonic-gate should_print = 1;
14640Sstevel@tonic-gate continue;
14650Sstevel@tonic-gate }
14660Sstevel@tonic-gate if (type == NUMB)
14670Sstevel@tonic-gate value = addr;
14680Sstevel@tonic-gate addr = itob(value);
14690Sstevel@tonic-gate if (!icheck(addr))
14700Sstevel@tonic-gate continue;
14710Sstevel@tonic-gate cur_ino = addr;
14720Sstevel@tonic-gate cur_inum = (long)value;
14730Sstevel@tonic-gate value = get(INODE);
14740Sstevel@tonic-gate type = NULL;
14750Sstevel@tonic-gate continue;
14760Sstevel@tonic-gate }
14770Sstevel@tonic-gate if (match("ib", 2)) { /* indirect block */
14780Sstevel@tonic-gate acting_on_inode = 1;
14790Sstevel@tonic-gate should_print = 1;
14800Sstevel@tonic-gate if (type == NUMB)
14810Sstevel@tonic-gate value = addr;
14820Sstevel@tonic-gate if (value >= NIADDR) {
14830Sstevel@tonic-gate printf("indirect blocks are 0 to ");
14840Sstevel@tonic-gate print(NIADDR - 1, 0, 0, 0);
14850Sstevel@tonic-gate printf("\n");
14860Sstevel@tonic-gate error++;
14870Sstevel@tonic-gate continue;
14880Sstevel@tonic-gate }
14891051Smaheshvs addr = (long)&((struct dinode *)(uintptr_t)
14901051Smaheshvs cur_ino)->di_ib[value];
14910Sstevel@tonic-gate cur_bytes = (NDADDR - 1) * BLKSIZE;
14920Sstevel@tonic-gate temp = 1;
14930Sstevel@tonic-gate for (i = 0; i < value; i++) {
14940Sstevel@tonic-gate temp *= NINDIR(fs) * BLKSIZE;
14950Sstevel@tonic-gate cur_bytes += temp;
14960Sstevel@tonic-gate }
14970Sstevel@tonic-gate type = BLOCK;
14980Sstevel@tonic-gate dirslot = 0;
14990Sstevel@tonic-gate value = get(LONG);
15000Sstevel@tonic-gate if (!value && !override) {
15010Sstevel@tonic-gate printf("non existent block\n");
15020Sstevel@tonic-gate error++;
15030Sstevel@tonic-gate }
15040Sstevel@tonic-gate continue;
15050Sstevel@tonic-gate }
15060Sstevel@tonic-gate goto bad_syntax;
15070Sstevel@tonic-gate
15080Sstevel@tonic-gate case 'l':
15090Sstevel@tonic-gate if (colon)
15100Sstevel@tonic-gate colon = 0;
15110Sstevel@tonic-gate else
15120Sstevel@tonic-gate goto no_colon;
15130Sstevel@tonic-gate if (match("log_head", 8)) {
15140Sstevel@tonic-gate log_display_header();
15150Sstevel@tonic-gate should_print = 0;
15160Sstevel@tonic-gate continue;
15170Sstevel@tonic-gate }
15180Sstevel@tonic-gate if (match("log_delta", 9)) {
15190Sstevel@tonic-gate log_show(LOG_NDELTAS);
15200Sstevel@tonic-gate should_print = 0;
15210Sstevel@tonic-gate continue;
15220Sstevel@tonic-gate }
15230Sstevel@tonic-gate if (match("log_show", 8)) {
15240Sstevel@tonic-gate log_show(LOG_ALLDELTAS);
15250Sstevel@tonic-gate should_print = 0;
15260Sstevel@tonic-gate continue;
15270Sstevel@tonic-gate }
15280Sstevel@tonic-gate if (match("log_chk", 7)) {
15290Sstevel@tonic-gate log_show(LOG_CHECKSCAN);
15300Sstevel@tonic-gate should_print = 0;
15310Sstevel@tonic-gate continue;
15320Sstevel@tonic-gate }
15330Sstevel@tonic-gate if (match("log_otodb", 9)) {
15340Sstevel@tonic-gate if (log_lodb((u_offset_t)addr, &temp)) {
15350Sstevel@tonic-gate addr = temp;
15360Sstevel@tonic-gate should_print = 1;
15370Sstevel@tonic-gate laststyle = '=';
15380Sstevel@tonic-gate } else
15390Sstevel@tonic-gate error++;
15400Sstevel@tonic-gate continue;
15410Sstevel@tonic-gate }
15420Sstevel@tonic-gate if (match("ls", 2)) { /* ls command */
15430Sstevel@tonic-gate temp = cur_inum;
15440Sstevel@tonic-gate recursive = long_list = 0;
15450Sstevel@tonic-gate top = filenames - 1;
15460Sstevel@tonic-gate for (;;) {
15470Sstevel@tonic-gate eat_spaces();
15480Sstevel@tonic-gate if ((c = getachar()) == '-') {
15490Sstevel@tonic-gate if ((c = getachar()) == 'R') {
15500Sstevel@tonic-gate recursive = 1;
15510Sstevel@tonic-gate continue;
15520Sstevel@tonic-gate } else if (c == 'l') {
15530Sstevel@tonic-gate long_list = 1;
15540Sstevel@tonic-gate } else {
15550Sstevel@tonic-gate printf(
15560Sstevel@tonic-gate "unknown option ");
15570Sstevel@tonic-gate printf("'%c'\n", c);
15580Sstevel@tonic-gate error++;
15590Sstevel@tonic-gate break;
15600Sstevel@tonic-gate }
15610Sstevel@tonic-gate } else
15620Sstevel@tonic-gate ungetachar(c);
15630Sstevel@tonic-gate if ((c = getachar()) == '\n') {
15640Sstevel@tonic-gate if (c_count != 2) {
15650Sstevel@tonic-gate ungetachar(c);
15660Sstevel@tonic-gate break;
15670Sstevel@tonic-gate }
15680Sstevel@tonic-gate }
15690Sstevel@tonic-gate c_count++;
15700Sstevel@tonic-gate ungetachar(c);
15710Sstevel@tonic-gate parse();
15720Sstevel@tonic-gate restore_inode((ino_t)temp);
15730Sstevel@tonic-gate if (error)
15740Sstevel@tonic-gate break;
15750Sstevel@tonic-gate }
15760Sstevel@tonic-gate recursive = 0;
15770Sstevel@tonic-gate if (error || nfiles == 0) {
15780Sstevel@tonic-gate if (!error) {
15790Sstevel@tonic-gate print_path(input_path,
15800Sstevel@tonic-gate (int)input_pathp);
15810Sstevel@tonic-gate printf(" not found\n");
15820Sstevel@tonic-gate }
15830Sstevel@tonic-gate continue;
15840Sstevel@tonic-gate }
15850Sstevel@tonic-gate if (nfiles) {
15860Sstevel@tonic-gate cmp_level = 0;
15870Sstevel@tonic-gate qsort((char *)filenames, nfiles,
15880Sstevel@tonic-gate sizeof (struct filenames), ffcmp);
15890Sstevel@tonic-gate ls(filenames, filenames + (nfiles - 1), 0);
15900Sstevel@tonic-gate } else {
15910Sstevel@tonic-gate printf("no match\n");
15920Sstevel@tonic-gate error++;
15930Sstevel@tonic-gate }
15940Sstevel@tonic-gate restore_inode((ino_t)temp);
15950Sstevel@tonic-gate continue;
15960Sstevel@tonic-gate }
15970Sstevel@tonic-gate if (match("ln", 2)) { /* link count */
15980Sstevel@tonic-gate acting_on_inode = 1;
15990Sstevel@tonic-gate should_print = 1;
16001051Smaheshvs addr = (long)&((struct dinode *)
16011051Smaheshvs (uintptr_t)cur_ino)->di_nlink;
16020Sstevel@tonic-gate value = get(SHORT);
16030Sstevel@tonic-gate type = NULL;
16040Sstevel@tonic-gate continue;
16050Sstevel@tonic-gate }
16060Sstevel@tonic-gate goto bad_syntax;
16070Sstevel@tonic-gate
16080Sstevel@tonic-gate case 'm':
16090Sstevel@tonic-gate if (colon)
16100Sstevel@tonic-gate colon = 0;
16110Sstevel@tonic-gate else
16120Sstevel@tonic-gate goto no_colon;
16130Sstevel@tonic-gate addr = cur_ino;
16140Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
16150Sstevel@tonic-gate continue;
16160Sstevel@tonic-gate if (match("mt", 2)) { /* modification time */
16170Sstevel@tonic-gate acting_on_inode = 2;
16180Sstevel@tonic-gate should_print = 1;
16191051Smaheshvs addr = (long)&((struct dinode *)
16201051Smaheshvs (uintptr_t)cur_ino)->di_mtime;
16210Sstevel@tonic-gate value = get(LONG);
16220Sstevel@tonic-gate type = NULL;
16230Sstevel@tonic-gate continue;
16240Sstevel@tonic-gate }
16250Sstevel@tonic-gate if (match("md", 2)) { /* mode */
16260Sstevel@tonic-gate acting_on_inode = 1;
16270Sstevel@tonic-gate should_print = 1;
16281051Smaheshvs addr = (long)&((struct dinode *)
16291051Smaheshvs (uintptr_t)cur_ino)->di_mode;
16300Sstevel@tonic-gate value = get(SHORT);
16310Sstevel@tonic-gate type = NULL;
16320Sstevel@tonic-gate continue;
16330Sstevel@tonic-gate }
16340Sstevel@tonic-gate if (match("maj", 2)) { /* major device number */
16350Sstevel@tonic-gate acting_on_inode = 1;
16360Sstevel@tonic-gate should_print = 1;
16370Sstevel@tonic-gate if (devcheck(mode))
16380Sstevel@tonic-gate continue;
16391051Smaheshvs addr = (uintptr_t)&((struct dinode *)(uintptr_t)
16401051Smaheshvs cur_ino)->di_ordev;
16410Sstevel@tonic-gate {
16420Sstevel@tonic-gate long dvalue;
16430Sstevel@tonic-gate dvalue = get(LONG);
16440Sstevel@tonic-gate value = major(dvalue);
16450Sstevel@tonic-gate }
16460Sstevel@tonic-gate type = NULL;
16470Sstevel@tonic-gate continue;
16480Sstevel@tonic-gate }
16490Sstevel@tonic-gate if (match("min", 2)) { /* minor device number */
16500Sstevel@tonic-gate acting_on_inode = 1;
16510Sstevel@tonic-gate should_print = 1;
16520Sstevel@tonic-gate if (devcheck(mode))
16530Sstevel@tonic-gate continue;
16541051Smaheshvs addr = (uintptr_t)&((struct dinode *)(uintptr_t)
16551051Smaheshvs cur_ino)->di_ordev;
16560Sstevel@tonic-gate {
16570Sstevel@tonic-gate long dvalue;
16580Sstevel@tonic-gate dvalue = (long)get(LONG);
16590Sstevel@tonic-gate value = minor(dvalue);
16600Sstevel@tonic-gate }
16610Sstevel@tonic-gate type = NULL;
16620Sstevel@tonic-gate continue;
16630Sstevel@tonic-gate }
16640Sstevel@tonic-gate goto bad_syntax;
16650Sstevel@tonic-gate
16660Sstevel@tonic-gate case 'n':
16670Sstevel@tonic-gate if (colon)
16680Sstevel@tonic-gate colon = 0;
16690Sstevel@tonic-gate else
16700Sstevel@tonic-gate goto no_colon;
16710Sstevel@tonic-gate if (match("nm", 1)) { /* directory name */
16720Sstevel@tonic-gate objsz = DIRECTORY;
16730Sstevel@tonic-gate acting_on_directory = 1;
16740Sstevel@tonic-gate cur_dir = addr;
16750Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
16760Sstevel@tonic-gate continue;
16770Sstevel@tonic-gate /*LINTED*/
16780Sstevel@tonic-gate dirp = (struct direct *)(cptr+blkoff(fs, addr));
16790Sstevel@tonic-gate stringsize = (long)dirp->d_reclen -
16800Sstevel@tonic-gate ((long)&dirp->d_name[0] -
16810Sstevel@tonic-gate (long)&dirp->d_ino);
16821051Smaheshvs addr = (long)&((struct direct *)
16831051Smaheshvs (uintptr_t)addr)->d_name[0];
16840Sstevel@tonic-gate type = NULL;
16850Sstevel@tonic-gate continue;
16860Sstevel@tonic-gate }
16870Sstevel@tonic-gate goto bad_syntax;
16880Sstevel@tonic-gate
16890Sstevel@tonic-gate case 'o':
16900Sstevel@tonic-gate if (colon)
16910Sstevel@tonic-gate colon = 0;
16920Sstevel@tonic-gate else
16930Sstevel@tonic-gate goto no_colon;
16940Sstevel@tonic-gate if (match("override", 1)) { /* override flip flop */
16950Sstevel@tonic-gate override = !override;
16960Sstevel@tonic-gate if (override)
16970Sstevel@tonic-gate printf("error checking off\n");
16980Sstevel@tonic-gate else
16990Sstevel@tonic-gate printf("error checking on\n");
17000Sstevel@tonic-gate continue;
17010Sstevel@tonic-gate }
17020Sstevel@tonic-gate goto bad_syntax;
17030Sstevel@tonic-gate
17040Sstevel@tonic-gate case 'p':
17050Sstevel@tonic-gate if (colon)
17060Sstevel@tonic-gate colon = 0;
17070Sstevel@tonic-gate else
17080Sstevel@tonic-gate goto no_colon;
17090Sstevel@tonic-gate if (match("pwd", 2)) { /* print working dir */
17100Sstevel@tonic-gate print_path(current_path, (int)current_pathp);
17110Sstevel@tonic-gate printf("\n");
17120Sstevel@tonic-gate continue;
17130Sstevel@tonic-gate }
17140Sstevel@tonic-gate if (match("prompt", 2)) { /* change prompt */
17150Sstevel@tonic-gate if ((c = getachar()) != '=') {
17160Sstevel@tonic-gate printf("missing '='\n");
17170Sstevel@tonic-gate error++;
17180Sstevel@tonic-gate continue;
17190Sstevel@tonic-gate }
17200Sstevel@tonic-gate if ((c = getachar()) != '"') {
17210Sstevel@tonic-gate printf("missing '\"'\n");
17220Sstevel@tonic-gate error++;
17230Sstevel@tonic-gate continue;
17240Sstevel@tonic-gate }
17250Sstevel@tonic-gate i = 0;
17260Sstevel@tonic-gate prompt = &prompt[0];
17270Sstevel@tonic-gate while ((c = getachar()) != '"' && c != '\n') {
17280Sstevel@tonic-gate prompt[i++] = c;
17290Sstevel@tonic-gate if (i >= PROMPTSIZE) {
17300Sstevel@tonic-gate printf("string too long\n");
17310Sstevel@tonic-gate error++;
17320Sstevel@tonic-gate break;
17330Sstevel@tonic-gate }
17340Sstevel@tonic-gate }
17350Sstevel@tonic-gate prompt[i] = '\0';
17360Sstevel@tonic-gate continue;
17370Sstevel@tonic-gate }
17380Sstevel@tonic-gate goto bad_syntax;
17390Sstevel@tonic-gate
17400Sstevel@tonic-gate case 'q':
17410Sstevel@tonic-gate if (!colon)
17420Sstevel@tonic-gate goto no_colon;
17430Sstevel@tonic-gate if (match("quit", 1)) { /* quit */
17440Sstevel@tonic-gate if ((c = getachar()) != '\n') {
17450Sstevel@tonic-gate error++;
17460Sstevel@tonic-gate continue;
17470Sstevel@tonic-gate }
17480Sstevel@tonic-gate exit(0);
17490Sstevel@tonic-gate }
17500Sstevel@tonic-gate goto bad_syntax;
17510Sstevel@tonic-gate
17520Sstevel@tonic-gate case 's':
17530Sstevel@tonic-gate if (colon)
17540Sstevel@tonic-gate colon = 0;
17550Sstevel@tonic-gate else
17560Sstevel@tonic-gate goto no_colon;
17570Sstevel@tonic-gate if (match("sb", 2)) { /* super block */
17580Sstevel@tonic-gate if (c_count == 2) {
17590Sstevel@tonic-gate cur_cgrp = -1;
17600Sstevel@tonic-gate type = objsz = SB;
17610Sstevel@tonic-gate laststyle = '=';
17620Sstevel@tonic-gate lastpo = 's';
17630Sstevel@tonic-gate should_print = 1;
17640Sstevel@tonic-gate continue;
17650Sstevel@tonic-gate }
17660Sstevel@tonic-gate if (type == NUMB)
17670Sstevel@tonic-gate value = addr;
17680Sstevel@tonic-gate if (value > fs->fs_ncg - 1) {
17690Sstevel@tonic-gate printf("maximum super block is ");
17700Sstevel@tonic-gate print(fs->fs_ncg - 1, 8, -8, 0);
17710Sstevel@tonic-gate printf("\n");
17720Sstevel@tonic-gate error++;
17730Sstevel@tonic-gate continue;
17740Sstevel@tonic-gate }
17750Sstevel@tonic-gate type = objsz = SB;
17760Sstevel@tonic-gate cur_cgrp = (long)value;
17770Sstevel@tonic-gate addr = cgsblock(fs, cur_cgrp) << FRGSHIFT;
17780Sstevel@tonic-gate continue;
17790Sstevel@tonic-gate }
17800Sstevel@tonic-gate if (match("shadow", 2)) { /* shadow inode data */
17810Sstevel@tonic-gate if (type == NUMB)
17820Sstevel@tonic-gate value = addr;
17830Sstevel@tonic-gate objsz = SHADOW_DATA;
17840Sstevel@tonic-gate type = SHADOW_DATA;
17850Sstevel@tonic-gate addr = getshadowslot(value);
17860Sstevel@tonic-gate continue;
17870Sstevel@tonic-gate }
17880Sstevel@tonic-gate if (match("si", 2)) { /* shadow inode field */
17890Sstevel@tonic-gate acting_on_inode = 1;
17900Sstevel@tonic-gate should_print = 1;
17911051Smaheshvs addr = (long)&((struct dinode *)
17921051Smaheshvs (uintptr_t)cur_ino)->di_shadow;
17930Sstevel@tonic-gate value = get(LONG);
17940Sstevel@tonic-gate type = NULL;
17950Sstevel@tonic-gate continue;
17960Sstevel@tonic-gate }
17970Sstevel@tonic-gate
17980Sstevel@tonic-gate if (match("sz", 2)) { /* file size */
17990Sstevel@tonic-gate acting_on_inode = 1;
18000Sstevel@tonic-gate should_print = 1;
18011051Smaheshvs addr = (long)&((struct dinode *)
18021051Smaheshvs (uintptr_t)cur_ino)->di_size;
18030Sstevel@tonic-gate value = get(U_OFFSET_T);
18040Sstevel@tonic-gate type = NULL;
18050Sstevel@tonic-gate objsz = U_OFFSET_T;
18060Sstevel@tonic-gate laststyle = '=';
18070Sstevel@tonic-gate lastpo = 'X';
18080Sstevel@tonic-gate continue;
18090Sstevel@tonic-gate }
18100Sstevel@tonic-gate goto bad_syntax;
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate case 'u':
18130Sstevel@tonic-gate if (colon)
18140Sstevel@tonic-gate colon = 0;
18150Sstevel@tonic-gate else
18160Sstevel@tonic-gate goto no_colon;
18170Sstevel@tonic-gate if (match("uid", 1)) { /* user id */
18180Sstevel@tonic-gate acting_on_inode = 1;
18190Sstevel@tonic-gate should_print = 1;
18201051Smaheshvs addr = (long)&((struct dinode *)
18211051Smaheshvs (uintptr_t)cur_ino)->di_uid;
18220Sstevel@tonic-gate value = get(SHORT);
18230Sstevel@tonic-gate type = NULL;
18240Sstevel@tonic-gate continue;
18250Sstevel@tonic-gate }
18260Sstevel@tonic-gate goto bad_syntax;
18270Sstevel@tonic-gate
18280Sstevel@tonic-gate case 'F': /* buffer status (internal use only) */
18290Sstevel@tonic-gate if (colon)
18300Sstevel@tonic-gate colon = 0;
18310Sstevel@tonic-gate else
18320Sstevel@tonic-gate goto no_colon;
18330Sstevel@tonic-gate for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd)
18340Sstevel@tonic-gate printf("%8" PRIx64 " %d\n",
18350Sstevel@tonic-gate bp->blkno, bp->valid);
18360Sstevel@tonic-gate printf("\n");
18370Sstevel@tonic-gate printf("# commands\t\t%ld\n", commands);
18380Sstevel@tonic-gate printf("# read requests\t\t%ld\n", read_requests);
18390Sstevel@tonic-gate printf("# actual disk reads\t%ld\n", actual_disk_reads);
18400Sstevel@tonic-gate continue;
18410Sstevel@tonic-gate no_colon:
18420Sstevel@tonic-gate printf("a colon should precede a command\n");
18430Sstevel@tonic-gate error++;
18440Sstevel@tonic-gate continue;
18450Sstevel@tonic-gate bad_syntax:
18460Sstevel@tonic-gate printf("more letters needed to distinguish command\n");
18470Sstevel@tonic-gate error++;
18480Sstevel@tonic-gate continue;
18490Sstevel@tonic-gate }
18500Sstevel@tonic-gate }
18510Sstevel@tonic-gate }
18520Sstevel@tonic-gate
18530Sstevel@tonic-gate /*
18540Sstevel@tonic-gate * usage - print usage and exit
18550Sstevel@tonic-gate */
18560Sstevel@tonic-gate static void
usage(char * progname)18571051Smaheshvs usage(char *progname)
18580Sstevel@tonic-gate {
18590Sstevel@tonic-gate printf("usage: %s [options] special\n", progname);
18600Sstevel@tonic-gate printf("options:\n");
18610Sstevel@tonic-gate printf("\t-o Specify ufs filesystem sepcific options\n");
18620Sstevel@tonic-gate printf(" Available suboptions are:\n");
18630Sstevel@tonic-gate printf("\t\t? display usage\n");
18640Sstevel@tonic-gate printf("\t\to override some error conditions\n");
18650Sstevel@tonic-gate printf("\t\tp=\"string\" set prompt to string\n");
18660Sstevel@tonic-gate printf("\t\tw open for write\n");
18670Sstevel@tonic-gate exit(1);
18680Sstevel@tonic-gate }
18690Sstevel@tonic-gate
18700Sstevel@tonic-gate /*
18710Sstevel@tonic-gate * getachar - get next character from input buffer.
18720Sstevel@tonic-gate */
18730Sstevel@tonic-gate static char
getachar()18740Sstevel@tonic-gate getachar()
18750Sstevel@tonic-gate {
18760Sstevel@tonic-gate return (input_buffer[input_pointer++]);
18770Sstevel@tonic-gate }
18780Sstevel@tonic-gate
18790Sstevel@tonic-gate /*
18800Sstevel@tonic-gate * ungetachar - return character to input buffer.
18810Sstevel@tonic-gate */
18820Sstevel@tonic-gate static void
ungetachar(char c)18831051Smaheshvs ungetachar(char c)
18840Sstevel@tonic-gate {
18850Sstevel@tonic-gate if (input_pointer == 0) {
18860Sstevel@tonic-gate printf("internal problem maintaining input buffer\n");
18870Sstevel@tonic-gate error++;
18880Sstevel@tonic-gate return;
18890Sstevel@tonic-gate }
18900Sstevel@tonic-gate input_buffer[--input_pointer] = c;
18910Sstevel@tonic-gate }
18920Sstevel@tonic-gate
18930Sstevel@tonic-gate /*
18940Sstevel@tonic-gate * getnextinput - display the prompt and read an input line.
18950Sstevel@tonic-gate * An input line is up to 128 characters terminated by the newline
18960Sstevel@tonic-gate * character. Handle overflow, shell escape, and eof.
18970Sstevel@tonic-gate */
18980Sstevel@tonic-gate static void
getnextinput()18990Sstevel@tonic-gate getnextinput()
19000Sstevel@tonic-gate {
19011051Smaheshvs int i;
19021051Smaheshvs char c;
19031051Smaheshvs short pid, rpid;
19041051Smaheshvs int retcode;
19050Sstevel@tonic-gate
19060Sstevel@tonic-gate newline:
19070Sstevel@tonic-gate i = 0;
19080Sstevel@tonic-gate printf("%s", prompt);
19090Sstevel@tonic-gate ignore_eol:
19100Sstevel@tonic-gate while ((c = getc(stdin)) != '\n' && !(c == '!' && i == 0) &&
19110Sstevel@tonic-gate !feof(stdin) && i <= INPUTBUFFER - 2)
19120Sstevel@tonic-gate input_buffer[i++] = c;
19130Sstevel@tonic-gate if (i > 0 && input_buffer[i - 1] == '\\') {
19140Sstevel@tonic-gate input_buffer[i++] = c;
19150Sstevel@tonic-gate goto ignore_eol;
19160Sstevel@tonic-gate }
19170Sstevel@tonic-gate if (feof(stdin)) {
19180Sstevel@tonic-gate printf("\n");
19190Sstevel@tonic-gate exit(0);
19200Sstevel@tonic-gate }
19210Sstevel@tonic-gate if (c == '!') {
19220Sstevel@tonic-gate if ((pid = fork()) == 0) {
19230Sstevel@tonic-gate (void) execl(_PATH_BSHELL, "sh", "-t", 0);
19240Sstevel@tonic-gate error++;
19250Sstevel@tonic-gate return;
19260Sstevel@tonic-gate }
19270Sstevel@tonic-gate while ((rpid = wait(&retcode)) != pid && rpid != -1)
19280Sstevel@tonic-gate ;
19290Sstevel@tonic-gate printf("!\n");
19300Sstevel@tonic-gate goto newline;
19310Sstevel@tonic-gate }
19320Sstevel@tonic-gate if (c != '\n')
19330Sstevel@tonic-gate printf("input truncated to 128 characters\n");
19340Sstevel@tonic-gate input_buffer[i] = '\n';
19350Sstevel@tonic-gate input_pointer = 0;
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate
19380Sstevel@tonic-gate /*
19390Sstevel@tonic-gate * eat_spaces - read extraneous spaces.
19400Sstevel@tonic-gate */
19410Sstevel@tonic-gate static void
eat_spaces()19420Sstevel@tonic-gate eat_spaces()
19430Sstevel@tonic-gate {
19441051Smaheshvs char c;
19450Sstevel@tonic-gate
19460Sstevel@tonic-gate while ((c = getachar()) == ' ')
19470Sstevel@tonic-gate ;
19480Sstevel@tonic-gate ungetachar(c);
19490Sstevel@tonic-gate }
19500Sstevel@tonic-gate
19510Sstevel@tonic-gate /*
19520Sstevel@tonic-gate * restore_inode - set up all inode indicators so inum is now
19530Sstevel@tonic-gate * the current inode.
19540Sstevel@tonic-gate */
19550Sstevel@tonic-gate static void
restore_inode(ino_t inum)19561051Smaheshvs restore_inode(ino_t inum)
19570Sstevel@tonic-gate {
19580Sstevel@tonic-gate errinum = cur_inum = inum;
19590Sstevel@tonic-gate addr = errino = cur_ino = itob(inum);
19600Sstevel@tonic-gate }
19610Sstevel@tonic-gate
19620Sstevel@tonic-gate /*
19630Sstevel@tonic-gate * match - return false if the input does not match string up to
19640Sstevel@tonic-gate * upto letters. Then proceed to chew up extraneous letters.
19650Sstevel@tonic-gate */
19660Sstevel@tonic-gate static int
match(char * string,int upto)19671051Smaheshvs match(char *string, int upto)
19680Sstevel@tonic-gate {
19691051Smaheshvs int i, length = strlen(string) - 1;
19701051Smaheshvs char c;
19711051Smaheshvs int save_upto = upto;
19720Sstevel@tonic-gate
19730Sstevel@tonic-gate while (--upto) {
19740Sstevel@tonic-gate string++;
19750Sstevel@tonic-gate if ((c = getachar()) != *string) {
19760Sstevel@tonic-gate for (i = save_upto - upto; i; i--) {
19770Sstevel@tonic-gate ungetachar(c);
19780Sstevel@tonic-gate c = *--string;
19790Sstevel@tonic-gate }
19800Sstevel@tonic-gate return (0);
19810Sstevel@tonic-gate }
19820Sstevel@tonic-gate length--;
19830Sstevel@tonic-gate }
19840Sstevel@tonic-gate while (length--) {
19850Sstevel@tonic-gate string++;
19860Sstevel@tonic-gate if ((c = getachar()) != *string) {
19870Sstevel@tonic-gate ungetachar(c);
19880Sstevel@tonic-gate return (1);
19890Sstevel@tonic-gate }
19900Sstevel@tonic-gate }
19910Sstevel@tonic-gate return (1);
19920Sstevel@tonic-gate }
19930Sstevel@tonic-gate
19940Sstevel@tonic-gate /*
19950Sstevel@tonic-gate * expr - expression evaluator. Will evaluate expressions from
19960Sstevel@tonic-gate * left to right with no operator precedence. Parentheses may
19970Sstevel@tonic-gate * be used.
19980Sstevel@tonic-gate */
19990Sstevel@tonic-gate static long
expr()20000Sstevel@tonic-gate expr()
20010Sstevel@tonic-gate {
20021051Smaheshvs long numb = 0, temp;
20031051Smaheshvs char c;
20040Sstevel@tonic-gate
20050Sstevel@tonic-gate numb = term();
20060Sstevel@tonic-gate for (;;) {
20070Sstevel@tonic-gate if (error)
20080Sstevel@tonic-gate return (~0); /* error is set so value is ignored */
20090Sstevel@tonic-gate c = getachar();
20100Sstevel@tonic-gate switch (c) {
20110Sstevel@tonic-gate
20120Sstevel@tonic-gate case '+':
20130Sstevel@tonic-gate numb += term();
20140Sstevel@tonic-gate continue;
20150Sstevel@tonic-gate
20160Sstevel@tonic-gate case '-':
20170Sstevel@tonic-gate numb -= term();
20180Sstevel@tonic-gate continue;
20190Sstevel@tonic-gate
20200Sstevel@tonic-gate case '*':
20210Sstevel@tonic-gate numb *= term();
20220Sstevel@tonic-gate continue;
20230Sstevel@tonic-gate
20240Sstevel@tonic-gate case '%':
20250Sstevel@tonic-gate temp = term();
20260Sstevel@tonic-gate if (!temp) {
20270Sstevel@tonic-gate printf("divide by zero\n");
20280Sstevel@tonic-gate error++;
20290Sstevel@tonic-gate return (~0);
20300Sstevel@tonic-gate }
20310Sstevel@tonic-gate numb /= temp;
20320Sstevel@tonic-gate continue;
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate case ')':
20350Sstevel@tonic-gate paren--;
20360Sstevel@tonic-gate return (numb);
20370Sstevel@tonic-gate
20380Sstevel@tonic-gate default:
20390Sstevel@tonic-gate ungetachar(c);
20400Sstevel@tonic-gate if (paren && !error) {
20410Sstevel@tonic-gate printf("missing ')'\n");
20420Sstevel@tonic-gate error++;
20430Sstevel@tonic-gate }
20440Sstevel@tonic-gate return (numb);
20450Sstevel@tonic-gate }
20460Sstevel@tonic-gate }
20470Sstevel@tonic-gate }
20480Sstevel@tonic-gate
20490Sstevel@tonic-gate /*
20500Sstevel@tonic-gate * term - used by expression evaluator to get an operand.
20510Sstevel@tonic-gate */
20520Sstevel@tonic-gate static long
term()20530Sstevel@tonic-gate term()
20540Sstevel@tonic-gate {
20551051Smaheshvs char c;
20560Sstevel@tonic-gate
20570Sstevel@tonic-gate switch (c = getachar()) {
20580Sstevel@tonic-gate
20590Sstevel@tonic-gate default:
20600Sstevel@tonic-gate ungetachar(c);
20610Sstevel@tonic-gate /*FALLTHRU*/
20620Sstevel@tonic-gate case '+':
20630Sstevel@tonic-gate return (getnumb());
20640Sstevel@tonic-gate
20650Sstevel@tonic-gate case '-':
20660Sstevel@tonic-gate return (-getnumb());
20670Sstevel@tonic-gate
20680Sstevel@tonic-gate case '(':
20690Sstevel@tonic-gate paren++;
20700Sstevel@tonic-gate return (expr());
20710Sstevel@tonic-gate }
20720Sstevel@tonic-gate }
20730Sstevel@tonic-gate
20740Sstevel@tonic-gate /*
20750Sstevel@tonic-gate * getnumb - read a number from the input stream. A leading
20760Sstevel@tonic-gate * zero signifies octal interpretation, a leading '0x'
20770Sstevel@tonic-gate * signifies hexadecimal, and a leading '0t' signifies
20780Sstevel@tonic-gate * decimal. If the first character is a character,
20790Sstevel@tonic-gate * return an error.
20800Sstevel@tonic-gate */
20810Sstevel@tonic-gate static long
getnumb()20820Sstevel@tonic-gate getnumb()
20830Sstevel@tonic-gate {
20840Sstevel@tonic-gate
20851051Smaheshvs char c, savec;
20860Sstevel@tonic-gate long number = 0, tbase, num;
20870Sstevel@tonic-gate extern short error;
20880Sstevel@tonic-gate
20890Sstevel@tonic-gate c = getachar();
20900Sstevel@tonic-gate if (!digit(c)) {
20910Sstevel@tonic-gate error++;
20920Sstevel@tonic-gate ungetachar(c);
20930Sstevel@tonic-gate return (-1);
20940Sstevel@tonic-gate }
20950Sstevel@tonic-gate if (c == '0') {
20960Sstevel@tonic-gate tbase = OCTAL;
20970Sstevel@tonic-gate if ((c = getachar()) == 'x')
20980Sstevel@tonic-gate tbase = HEX;
20990Sstevel@tonic-gate else if (c == 't')
21000Sstevel@tonic-gate tbase = DECIMAL;
21010Sstevel@tonic-gate else ungetachar(c);
21020Sstevel@tonic-gate } else {
21030Sstevel@tonic-gate tbase = base;
21040Sstevel@tonic-gate ungetachar(c);
21050Sstevel@tonic-gate }
21060Sstevel@tonic-gate for (;;) {
21070Sstevel@tonic-gate num = tbase;
21080Sstevel@tonic-gate c = savec = getachar();
21090Sstevel@tonic-gate if (HEXLETTER(c))
21100Sstevel@tonic-gate c = uppertolower(c);
21110Sstevel@tonic-gate switch (tbase) {
21120Sstevel@tonic-gate case HEX:
21130Sstevel@tonic-gate if (hexletter(c)) {
21140Sstevel@tonic-gate num = hextodigit(c);
21150Sstevel@tonic-gate break;
21160Sstevel@tonic-gate }
21170Sstevel@tonic-gate /*FALLTHRU*/
21180Sstevel@tonic-gate case DECIMAL:
21190Sstevel@tonic-gate if (digit(c))
21200Sstevel@tonic-gate num = numtodigit(c);
21210Sstevel@tonic-gate break;
21220Sstevel@tonic-gate case OCTAL:
21230Sstevel@tonic-gate if (octaldigit(c))
21240Sstevel@tonic-gate num = numtodigit(c);
21250Sstevel@tonic-gate }
21260Sstevel@tonic-gate if (num == tbase)
21270Sstevel@tonic-gate break;
21280Sstevel@tonic-gate number = number * tbase + num;
21290Sstevel@tonic-gate }
21300Sstevel@tonic-gate ungetachar(savec);
21310Sstevel@tonic-gate return (number);
21320Sstevel@tonic-gate }
21330Sstevel@tonic-gate
21340Sstevel@tonic-gate /*
21350Sstevel@tonic-gate * find - the syntax is almost identical to the unix command.
21360Sstevel@tonic-gate * find dir [-name pattern] [-inum number]
21370Sstevel@tonic-gate * Note: only one of -name or -inum may be used at a time.
21380Sstevel@tonic-gate * Also, the -print is not needed (implied).
21390Sstevel@tonic-gate */
21400Sstevel@tonic-gate static void
find()21410Sstevel@tonic-gate find()
21420Sstevel@tonic-gate {
21431051Smaheshvs struct filenames *fn;
21441051Smaheshvs char c;
21451051Smaheshvs long temp;
21461051Smaheshvs short mode;
21470Sstevel@tonic-gate
21480Sstevel@tonic-gate eat_spaces();
21490Sstevel@tonic-gate temp = cur_inum;
21500Sstevel@tonic-gate top = filenames - 1;
21510Sstevel@tonic-gate doing_cd = 1;
21520Sstevel@tonic-gate parse();
21530Sstevel@tonic-gate doing_cd = 0;
21540Sstevel@tonic-gate if (nfiles != 1) {
21550Sstevel@tonic-gate restore_inode((ino_t)temp);
21560Sstevel@tonic-gate if (!error) {
21570Sstevel@tonic-gate print_path(input_path, (int)input_pathp);
21580Sstevel@tonic-gate if (nfiles == 0)
21590Sstevel@tonic-gate printf(" not found\n");
21600Sstevel@tonic-gate else
21610Sstevel@tonic-gate printf(" ambiguous\n");
21620Sstevel@tonic-gate error++;
21630Sstevel@tonic-gate return;
21640Sstevel@tonic-gate }
21650Sstevel@tonic-gate }
21660Sstevel@tonic-gate restore_inode(filenames->ino);
21670Sstevel@tonic-gate freemem(filenames, nfiles);
21680Sstevel@tonic-gate nfiles = 0;
21690Sstevel@tonic-gate top = filenames - 1;
21700Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
21710Sstevel@tonic-gate return;
21720Sstevel@tonic-gate if ((mode & IFMT) != IFDIR) {
21730Sstevel@tonic-gate print_path(input_path, (int)input_pathp);
21740Sstevel@tonic-gate printf(" not a directory\n");
21750Sstevel@tonic-gate error++;
21760Sstevel@tonic-gate return;
21770Sstevel@tonic-gate }
21780Sstevel@tonic-gate eat_spaces();
21790Sstevel@tonic-gate if ((c = getachar()) != '-') {
21800Sstevel@tonic-gate restore_inode((ino_t)temp);
21810Sstevel@tonic-gate printf("missing '-'\n");
21820Sstevel@tonic-gate error++;
21830Sstevel@tonic-gate return;
21840Sstevel@tonic-gate }
21850Sstevel@tonic-gate find_by_name = find_by_inode = 0;
21860Sstevel@tonic-gate c = getachar();
21870Sstevel@tonic-gate if (match("name", 4)) {
21880Sstevel@tonic-gate eat_spaces();
21890Sstevel@tonic-gate find_by_name = 1;
21900Sstevel@tonic-gate } else if (match("inum", 4)) {
21910Sstevel@tonic-gate eat_spaces();
21920Sstevel@tonic-gate find_ino = expr();
21930Sstevel@tonic-gate if (error) {
21940Sstevel@tonic-gate restore_inode((ino_t)temp);
21950Sstevel@tonic-gate return;
21960Sstevel@tonic-gate }
21970Sstevel@tonic-gate while ((c = getachar()) != '\n')
21980Sstevel@tonic-gate ;
21990Sstevel@tonic-gate ungetachar(c);
22000Sstevel@tonic-gate find_by_inode = 1;
22010Sstevel@tonic-gate } else {
22020Sstevel@tonic-gate restore_inode((ino_t)temp);
22030Sstevel@tonic-gate printf("use -name or -inum with find\n");
22040Sstevel@tonic-gate error++;
22050Sstevel@tonic-gate return;
22060Sstevel@tonic-gate }
22070Sstevel@tonic-gate doing_find = 1;
22080Sstevel@tonic-gate parse();
22090Sstevel@tonic-gate doing_find = 0;
22100Sstevel@tonic-gate if (error) {
22110Sstevel@tonic-gate restore_inode((ino_t)temp);
22120Sstevel@tonic-gate return;
22130Sstevel@tonic-gate }
22140Sstevel@tonic-gate for (fn = filenames; fn <= top; fn++) {
22150Sstevel@tonic-gate if (fn->find == 0)
22160Sstevel@tonic-gate continue;
22170Sstevel@tonic-gate printf("i#: ");
22180Sstevel@tonic-gate print(fn->ino, 12, -8, 0);
22190Sstevel@tonic-gate print_path(fn->fname, (int)fn->len);
22200Sstevel@tonic-gate printf("\n");
22210Sstevel@tonic-gate }
22220Sstevel@tonic-gate restore_inode((ino_t)temp);
22230Sstevel@tonic-gate }
22240Sstevel@tonic-gate
22250Sstevel@tonic-gate /*
22260Sstevel@tonic-gate * ls - do an ls. Should behave exactly as ls(1).
22270Sstevel@tonic-gate * Only -R and -l is supported and -l gives different results.
22280Sstevel@tonic-gate */
22290Sstevel@tonic-gate static void
ls(struct filenames * fn0,struct filenames * fnlast,short level)22301051Smaheshvs ls(struct filenames *fn0, struct filenames *fnlast, short level)
22310Sstevel@tonic-gate {
22321051Smaheshvs struct filenames *fn, *fnn;
22330Sstevel@tonic-gate
22340Sstevel@tonic-gate fn = fn0;
22350Sstevel@tonic-gate for (;;) {
22360Sstevel@tonic-gate fn0 = fn;
22370Sstevel@tonic-gate if (fn0->len) {
22380Sstevel@tonic-gate cmp_level = level;
22390Sstevel@tonic-gate qsort((char *)fn0, fnlast - fn0 + 1,
22400Sstevel@tonic-gate sizeof (struct filenames), fcmp);
22410Sstevel@tonic-gate }
22420Sstevel@tonic-gate for (fnn = fn, fn++; fn <= fnlast; fnn = fn, fn++) {
22430Sstevel@tonic-gate if (fnn->len != fn->len && level == fnn->len - 1)
22440Sstevel@tonic-gate break;
22450Sstevel@tonic-gate if (fnn->len == 0)
22460Sstevel@tonic-gate continue;
22470Sstevel@tonic-gate if (strcmp(fn->fname[level], fnn->fname[level]))
22480Sstevel@tonic-gate break;
22490Sstevel@tonic-gate }
22500Sstevel@tonic-gate if (fn0->len && level != fn0->len - 1)
22510Sstevel@tonic-gate ls(fn0, fnn, level + 1);
22520Sstevel@tonic-gate else {
22530Sstevel@tonic-gate if (fn0 != filenames)
22540Sstevel@tonic-gate printf("\n");
22550Sstevel@tonic-gate print_path(fn0->fname, (int)(fn0->len - 1));
22560Sstevel@tonic-gate printf(":\n");
22570Sstevel@tonic-gate if (fn0->len == 0)
22580Sstevel@tonic-gate cmp_level = level;
22590Sstevel@tonic-gate else
22600Sstevel@tonic-gate cmp_level = level + 1;
22610Sstevel@tonic-gate qsort((char *)fn0, fnn - fn0 + 1,
22620Sstevel@tonic-gate sizeof (struct filenames), fcmp);
22630Sstevel@tonic-gate formatf(fn0, fnn);
22640Sstevel@tonic-gate nfiles -= fnn - fn0 + 1;
22650Sstevel@tonic-gate }
22660Sstevel@tonic-gate if (fn > fnlast)
22670Sstevel@tonic-gate return;
22680Sstevel@tonic-gate }
22690Sstevel@tonic-gate }
22700Sstevel@tonic-gate
22710Sstevel@tonic-gate /*
22720Sstevel@tonic-gate * formatf - code lifted from ls.
22730Sstevel@tonic-gate */
22740Sstevel@tonic-gate static void
formatf(struct filenames * fn0,struct filenames * fnlast)22751051Smaheshvs formatf(struct filenames *fn0, struct filenames *fnlast)
22760Sstevel@tonic-gate {
22771051Smaheshvs struct filenames *fn;
22781051Smaheshvs int width = 0, w, nentry = fnlast - fn0 + 1;
22791051Smaheshvs int i, j, columns, lines;
22801051Smaheshvs char *cp;
22810Sstevel@tonic-gate
22820Sstevel@tonic-gate if (long_list) {
22830Sstevel@tonic-gate columns = 1;
22840Sstevel@tonic-gate } else {
22850Sstevel@tonic-gate for (fn = fn0; fn <= fnlast; fn++) {
22860Sstevel@tonic-gate int len = strlen(fn->fname[cmp_level]) + 2;
22870Sstevel@tonic-gate
22880Sstevel@tonic-gate if (len > width)
22890Sstevel@tonic-gate width = len;
22900Sstevel@tonic-gate }
22910Sstevel@tonic-gate width = (width + 8) &~ 7;
22920Sstevel@tonic-gate columns = 80 / width;
22930Sstevel@tonic-gate if (columns == 0)
22940Sstevel@tonic-gate columns = 1;
22950Sstevel@tonic-gate }
22960Sstevel@tonic-gate lines = (nentry + columns - 1) / columns;
22970Sstevel@tonic-gate for (i = 0; i < lines; i++) {
22980Sstevel@tonic-gate for (j = 0; j < columns; j++) {
22990Sstevel@tonic-gate fn = fn0 + j * lines + i;
23000Sstevel@tonic-gate if (long_list) {
23010Sstevel@tonic-gate printf("i#: ");
23020Sstevel@tonic-gate print(fn->ino, 12, -8, 0);
23030Sstevel@tonic-gate }
23040Sstevel@tonic-gate if ((cp = fmtentry(fn)) == NULL) {
23050Sstevel@tonic-gate printf("cannot read inode %ld\n", fn->ino);
23060Sstevel@tonic-gate return;
23070Sstevel@tonic-gate }
23080Sstevel@tonic-gate printf("%s", cp);
23090Sstevel@tonic-gate if (fn + lines > fnlast) {
23100Sstevel@tonic-gate printf("\n");
23110Sstevel@tonic-gate break;
23120Sstevel@tonic-gate }
23130Sstevel@tonic-gate w = strlen(cp);
23140Sstevel@tonic-gate while (w < width) {
23150Sstevel@tonic-gate w = (w + 8) &~ 7;
23160Sstevel@tonic-gate (void) putchar('\t');
23170Sstevel@tonic-gate }
23180Sstevel@tonic-gate }
23190Sstevel@tonic-gate }
23200Sstevel@tonic-gate }
23210Sstevel@tonic-gate
23220Sstevel@tonic-gate /*
23230Sstevel@tonic-gate * fmtentry - code lifted from ls.
23240Sstevel@tonic-gate */
23250Sstevel@tonic-gate static char *
fmtentry(struct filenames * fn)23261051Smaheshvs fmtentry(struct filenames *fn)
23270Sstevel@tonic-gate {
23281051Smaheshvs static char fmtres[BUFSIZ];
23291051Smaheshvs struct dinode *ip;
23301051Smaheshvs char *cptr, *cp, *dp;
23310Sstevel@tonic-gate
23320Sstevel@tonic-gate dp = &fmtres[0];
23330Sstevel@tonic-gate for (cp = fn->fname[cmp_level]; *cp; cp++) {
23340Sstevel@tonic-gate if (*cp < ' ' || *cp >= 0177)
23350Sstevel@tonic-gate *dp++ = '?';
23360Sstevel@tonic-gate else
23370Sstevel@tonic-gate *dp++ = *cp;
23380Sstevel@tonic-gate }
23390Sstevel@tonic-gate addr = itob(fn->ino);
23400Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
23410Sstevel@tonic-gate return (NULL);
23420Sstevel@tonic-gate cptr += blkoff(fs, addr);
23430Sstevel@tonic-gate /*LINTED*/
23440Sstevel@tonic-gate ip = (struct dinode *)cptr;
23450Sstevel@tonic-gate switch (ip->di_mode & IFMT) {
23460Sstevel@tonic-gate case IFDIR:
23470Sstevel@tonic-gate *dp++ = '/';
23480Sstevel@tonic-gate break;
23490Sstevel@tonic-gate case IFLNK:
23500Sstevel@tonic-gate *dp++ = '@';
23510Sstevel@tonic-gate break;
23520Sstevel@tonic-gate case IFSOCK:
23530Sstevel@tonic-gate *dp++ = '=';
23540Sstevel@tonic-gate break;
23550Sstevel@tonic-gate #ifdef IFIFO
23560Sstevel@tonic-gate case IFIFO:
23570Sstevel@tonic-gate *dp++ = 'p';
23580Sstevel@tonic-gate break;
23590Sstevel@tonic-gate #endif
23600Sstevel@tonic-gate case IFCHR:
23610Sstevel@tonic-gate case IFBLK:
23620Sstevel@tonic-gate case IFREG:
23630Sstevel@tonic-gate if (ip->di_mode & 0111)
23640Sstevel@tonic-gate *dp++ = '*';
23650Sstevel@tonic-gate else
23660Sstevel@tonic-gate *dp++ = ' ';
23670Sstevel@tonic-gate break;
23680Sstevel@tonic-gate default:
23690Sstevel@tonic-gate *dp++ = '?';
23700Sstevel@tonic-gate
23710Sstevel@tonic-gate }
23720Sstevel@tonic-gate *dp++ = 0;
23730Sstevel@tonic-gate return (fmtres);
23740Sstevel@tonic-gate }
23750Sstevel@tonic-gate
23760Sstevel@tonic-gate /*
23770Sstevel@tonic-gate * fcmp - routine used by qsort. Will sort first by name, then
23780Sstevel@tonic-gate * then by pathname length if names are equal. Uses global
23790Sstevel@tonic-gate * cmp_level to tell what component of the path name we are comparing.
23800Sstevel@tonic-gate */
23810Sstevel@tonic-gate static int
fcmp(struct filenames * f1,struct filenames * f2)23821051Smaheshvs fcmp(struct filenames *f1, struct filenames *f2)
23830Sstevel@tonic-gate {
23841051Smaheshvs int value;
23850Sstevel@tonic-gate
23860Sstevel@tonic-gate if ((value = strcmp(f1->fname[cmp_level], f2->fname[cmp_level])))
23870Sstevel@tonic-gate return (value);
23880Sstevel@tonic-gate return (f1->len - f2->len);
23890Sstevel@tonic-gate }
23900Sstevel@tonic-gate
23910Sstevel@tonic-gate /*
23920Sstevel@tonic-gate * ffcmp - routine used by qsort. Sort only by pathname length.
23930Sstevel@tonic-gate */
23940Sstevel@tonic-gate static int
ffcmp(struct filenames * f1,struct filenames * f2)23951051Smaheshvs ffcmp(struct filenames *f1, struct filenames *f2)
23960Sstevel@tonic-gate {
23970Sstevel@tonic-gate return (f1->len - f2->len);
23980Sstevel@tonic-gate }
23990Sstevel@tonic-gate
24000Sstevel@tonic-gate /*
24010Sstevel@tonic-gate * parse - set up the call to follow_path.
24020Sstevel@tonic-gate */
24030Sstevel@tonic-gate static void
parse()24040Sstevel@tonic-gate parse()
24050Sstevel@tonic-gate {
24061051Smaheshvs int i;
24071051Smaheshvs char c;
24080Sstevel@tonic-gate
24090Sstevel@tonic-gate stack_pathp = input_pathp = -1;
24100Sstevel@tonic-gate if ((c = getachar()) == '/') {
24110Sstevel@tonic-gate while ((c = getachar()) == '/')
24120Sstevel@tonic-gate ;
24130Sstevel@tonic-gate ungetachar(c);
24140Sstevel@tonic-gate cur_inum = 2;
24150Sstevel@tonic-gate c = getachar();
24160Sstevel@tonic-gate if ((c == '\n') || ((doing_cd) && (c == ' '))) {
24170Sstevel@tonic-gate ungetachar(c);
24180Sstevel@tonic-gate if (doing_cd) {
24190Sstevel@tonic-gate top++;
24200Sstevel@tonic-gate top->ino = 2;
24210Sstevel@tonic-gate top->len = -1;
24220Sstevel@tonic-gate nfiles = 1;
24230Sstevel@tonic-gate return;
24240Sstevel@tonic-gate }
24250Sstevel@tonic-gate } else
24260Sstevel@tonic-gate ungetachar(c);
24270Sstevel@tonic-gate } else {
24280Sstevel@tonic-gate ungetachar(c);
24290Sstevel@tonic-gate stack_pathp = current_pathp;
24300Sstevel@tonic-gate if (!doing_find)
24310Sstevel@tonic-gate input_pathp = current_pathp;
24320Sstevel@tonic-gate for (i = 0; i <= current_pathp; i++) {
24330Sstevel@tonic-gate if (!doing_find)
24340Sstevel@tonic-gate (void) strcpy(input_path[i], current_path[i]);
24350Sstevel@tonic-gate (void) strcpy(stack_path[i], current_path[i]);
24360Sstevel@tonic-gate }
24370Sstevel@tonic-gate }
24380Sstevel@tonic-gate getname();
24390Sstevel@tonic-gate follow_path((long)(stack_pathp + 1), cur_inum);
24400Sstevel@tonic-gate }
24410Sstevel@tonic-gate
24420Sstevel@tonic-gate /*
24430Sstevel@tonic-gate * follow_path - called by cd, find, and ls.
24440Sstevel@tonic-gate * input_path holds the name typed by the user.
24450Sstevel@tonic-gate * stack_path holds the name at the current depth.
24460Sstevel@tonic-gate */
24470Sstevel@tonic-gate static void
follow_path(long level,long inum)24481051Smaheshvs follow_path(long level, long inum)
24490Sstevel@tonic-gate {
24501051Smaheshvs struct direct *dirp;
24511051Smaheshvs char **ccptr, *cptr;
24521051Smaheshvs int i;
24530Sstevel@tonic-gate struct filenames *tos, *bos, *fn, *fnn, *fnnn;
24540Sstevel@tonic-gate long block;
24550Sstevel@tonic-gate short mode;
24560Sstevel@tonic-gate
24570Sstevel@tonic-gate tos = top + 1;
24580Sstevel@tonic-gate restore_inode((ino_t)inum);
24590Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
24600Sstevel@tonic-gate return;
24610Sstevel@tonic-gate if ((mode & IFMT) != IFDIR)
24620Sstevel@tonic-gate return;
24630Sstevel@tonic-gate block = cur_bytes = 0;
24640Sstevel@tonic-gate while (cur_bytes < filesize) {
24650Sstevel@tonic-gate if (block == 0 || bcomp(addr)) {
24660Sstevel@tonic-gate error = 0;
24670Sstevel@tonic-gate if ((addr = ((u_offset_t)bmap(block++) <<
24680Sstevel@tonic-gate (u_offset_t)FRGSHIFT)) == 0)
24690Sstevel@tonic-gate break;
24700Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
24710Sstevel@tonic-gate break;
24720Sstevel@tonic-gate cptr += blkoff(fs, addr);
24730Sstevel@tonic-gate }
24740Sstevel@tonic-gate /*LINTED*/
24750Sstevel@tonic-gate dirp = (struct direct *)cptr;
24760Sstevel@tonic-gate if (dirp->d_ino) {
24770Sstevel@tonic-gate if (level > input_pathp || doing_find ||
24780Sstevel@tonic-gate compare(input_path[level], &dirp->d_name[0], 1)) {
24790Sstevel@tonic-gate if ((doing_find) &&
24800Sstevel@tonic-gate ((strcmp(dirp->d_name, ".") == 0 ||
24810Sstevel@tonic-gate strcmp(dirp->d_name, "..") == 0)))
24820Sstevel@tonic-gate goto duplicate;
24830Sstevel@tonic-gate if (++top - filenames >= maxfiles) {
24840Sstevel@tonic-gate printf("too many files\n");
24850Sstevel@tonic-gate error++;
24860Sstevel@tonic-gate return;
24870Sstevel@tonic-gate }
24880Sstevel@tonic-gate top->fname = (char **)calloc(FIRST_DEPTH, sizeof (char **));
24890Sstevel@tonic-gate top->flag = 0;
24900Sstevel@tonic-gate if (top->fname == 0) {
24910Sstevel@tonic-gate printf("out of memory\n");
24920Sstevel@tonic-gate error++;
24930Sstevel@tonic-gate return;
24940Sstevel@tonic-gate }
24950Sstevel@tonic-gate nfiles++;
24960Sstevel@tonic-gate top->ino = dirp->d_ino;
24970Sstevel@tonic-gate top->len = stack_pathp;
24980Sstevel@tonic-gate top->find = 0;
24990Sstevel@tonic-gate if (doing_find) {
25000Sstevel@tonic-gate if (find_by_name) {
25010Sstevel@tonic-gate if (compare(input_path[0], &dirp->d_name[0], 1))
25020Sstevel@tonic-gate top->find = 1;
25030Sstevel@tonic-gate } else if (find_by_inode)
25040Sstevel@tonic-gate if (find_ino == dirp->d_ino)
25050Sstevel@tonic-gate top->find = 1;
25060Sstevel@tonic-gate }
25070Sstevel@tonic-gate if (top->len + 1 >= FIRST_DEPTH && top->flag == 0) {
25080Sstevel@tonic-gate ccptr = (char **)calloc(SECOND_DEPTH, sizeof (char **));
25090Sstevel@tonic-gate if (ccptr == 0) {
25100Sstevel@tonic-gate printf("out of memory\n");
25110Sstevel@tonic-gate error++;
25120Sstevel@tonic-gate return;
25130Sstevel@tonic-gate }
25140Sstevel@tonic-gate for (i = 0; i < FIRST_DEPTH; i++)
25150Sstevel@tonic-gate ccptr[i] = top->fname[i];
25160Sstevel@tonic-gate free((char *)top->fname);
25170Sstevel@tonic-gate top->fname = ccptr;
25180Sstevel@tonic-gate top->flag = 1;
25190Sstevel@tonic-gate }
25200Sstevel@tonic-gate if (top->len >= SECOND_DEPTH) {
25210Sstevel@tonic-gate printf("maximum depth exceeded, try to cd lower\n");
25220Sstevel@tonic-gate error++;
25230Sstevel@tonic-gate return;
25240Sstevel@tonic-gate }
25250Sstevel@tonic-gate /*
25260Sstevel@tonic-gate * Copy current depth.
25270Sstevel@tonic-gate */
25280Sstevel@tonic-gate for (i = 0; i <= stack_pathp; i++) {
25290Sstevel@tonic-gate top->fname[i] = calloc(1, strlen(stack_path[i])+1);
25300Sstevel@tonic-gate if (top->fname[i] == 0) {
25310Sstevel@tonic-gate printf("out of memory\n");
25320Sstevel@tonic-gate error++;
25330Sstevel@tonic-gate return;
25340Sstevel@tonic-gate }
25350Sstevel@tonic-gate (void) strcpy(top->fname[i], stack_path[i]);
25360Sstevel@tonic-gate }
25370Sstevel@tonic-gate /*
25380Sstevel@tonic-gate * Check for '.' or '..' typed.
25390Sstevel@tonic-gate */
25400Sstevel@tonic-gate if ((level <= input_pathp) &&
25410Sstevel@tonic-gate (strcmp(input_path[level], ".") == 0 ||
25420Sstevel@tonic-gate strcmp(input_path[level], "..") == 0)) {
25430Sstevel@tonic-gate if (strcmp(input_path[level], "..") == 0 &&
25440Sstevel@tonic-gate top->len >= 0) {
25450Sstevel@tonic-gate free(top->fname[top->len]);
25460Sstevel@tonic-gate top->len -= 1;
25470Sstevel@tonic-gate }
25480Sstevel@tonic-gate } else {
25490Sstevel@tonic-gate /*
25500Sstevel@tonic-gate * Check for duplicates.
25510Sstevel@tonic-gate */
25520Sstevel@tonic-gate if (!doing_cd && !doing_find) {
25530Sstevel@tonic-gate for (fn = filenames; fn < top; fn++) {
25540Sstevel@tonic-gate if (fn->ino == dirp->d_ino &&
25550Sstevel@tonic-gate fn->len == stack_pathp + 1) {
25560Sstevel@tonic-gate for (i = 0; i < fn->len; i++)
25570Sstevel@tonic-gate if (strcmp(fn->fname[i], stack_path[i]))
25580Sstevel@tonic-gate break;
25590Sstevel@tonic-gate if (i != fn->len ||
25600Sstevel@tonic-gate strcmp(fn->fname[i], dirp->d_name))
25610Sstevel@tonic-gate continue;
25620Sstevel@tonic-gate freemem(top, 1);
25630Sstevel@tonic-gate if (top == filenames)
25640Sstevel@tonic-gate top = NULL;
25650Sstevel@tonic-gate else
25660Sstevel@tonic-gate top--;
25670Sstevel@tonic-gate nfiles--;
25680Sstevel@tonic-gate goto duplicate;
25690Sstevel@tonic-gate }
25700Sstevel@tonic-gate }
25710Sstevel@tonic-gate }
25720Sstevel@tonic-gate top->len += 1;
25730Sstevel@tonic-gate top->fname[top->len] = calloc(1,
25740Sstevel@tonic-gate strlen(&dirp->d_name[0])+1);
25750Sstevel@tonic-gate if (top->fname[top->len] == 0) {
25760Sstevel@tonic-gate printf("out of memory\n");
25770Sstevel@tonic-gate error++;
25780Sstevel@tonic-gate return;
25790Sstevel@tonic-gate }
25800Sstevel@tonic-gate (void) strcpy(top->fname[top->len], &dirp->d_name[0]);
25810Sstevel@tonic-gate }
25820Sstevel@tonic-gate }
25830Sstevel@tonic-gate }
25840Sstevel@tonic-gate duplicate:
25850Sstevel@tonic-gate addr += dirp->d_reclen;
25860Sstevel@tonic-gate cptr += dirp->d_reclen;
25870Sstevel@tonic-gate cur_bytes += dirp->d_reclen;
25880Sstevel@tonic-gate }
25890Sstevel@tonic-gate if (top < filenames)
25900Sstevel@tonic-gate return;
25910Sstevel@tonic-gate if ((doing_cd && level == input_pathp) ||
25920Sstevel@tonic-gate (!recursive && !doing_find && level > input_pathp))
25930Sstevel@tonic-gate return;
25940Sstevel@tonic-gate bos = top;
25950Sstevel@tonic-gate /*
25960Sstevel@tonic-gate * Check newly added entries to determine if further expansion
25970Sstevel@tonic-gate * is required.
25980Sstevel@tonic-gate */
25990Sstevel@tonic-gate for (fn = tos; fn <= bos; fn++) {
26000Sstevel@tonic-gate /*
26010Sstevel@tonic-gate * Avoid '.' and '..' if beyond input.
26020Sstevel@tonic-gate */
26030Sstevel@tonic-gate if ((recursive || doing_find) && (level > input_pathp) &&
26040Sstevel@tonic-gate (strcmp(fn->fname[fn->len], ".") == 0 ||
26050Sstevel@tonic-gate strcmp(fn->fname[fn->len], "..") == 0))
26060Sstevel@tonic-gate continue;
26070Sstevel@tonic-gate restore_inode(fn->ino);
26080Sstevel@tonic-gate if ((mode = icheck(cur_ino)) == 0)
26090Sstevel@tonic-gate return;
26100Sstevel@tonic-gate if ((mode & IFMT) == IFDIR || level < input_pathp) {
26110Sstevel@tonic-gate /*
26120Sstevel@tonic-gate * Set up current depth, remove current entry and
26130Sstevel@tonic-gate * continue recursion.
26140Sstevel@tonic-gate */
26150Sstevel@tonic-gate for (i = 0; i <= fn->len; i++)
26160Sstevel@tonic-gate (void) strcpy(stack_path[i], fn->fname[i]);
26170Sstevel@tonic-gate stack_pathp = fn->len;
26180Sstevel@tonic-gate if (!doing_find &&
26190Sstevel@tonic-gate (!recursive || (recursive && level <= input_pathp))) {
26200Sstevel@tonic-gate /*
26210Sstevel@tonic-gate * Remove current entry by moving others up.
26220Sstevel@tonic-gate */
26230Sstevel@tonic-gate freemem(fn, 1);
26240Sstevel@tonic-gate fnn = fn;
26250Sstevel@tonic-gate for (fnnn = fnn, fnn++; fnn <= top; fnnn = fnn, fnn++) {
26260Sstevel@tonic-gate fnnn->ino = fnn->ino;
26270Sstevel@tonic-gate fnnn->len = fnn->len;
26280Sstevel@tonic-gate if (fnnn->len + 1 < FIRST_DEPTH) {
26290Sstevel@tonic-gate fnnn->fname = (char **)calloc(FIRST_DEPTH,
26300Sstevel@tonic-gate sizeof (char **));
26310Sstevel@tonic-gate fnnn->flag = 0;
26320Sstevel@tonic-gate } else if (fnnn->len < SECOND_DEPTH) {
26330Sstevel@tonic-gate fnnn->fname = (char **)calloc(SECOND_DEPTH,
26340Sstevel@tonic-gate sizeof (char **));
26350Sstevel@tonic-gate fnnn->flag = 1;
26360Sstevel@tonic-gate } else {
26370Sstevel@tonic-gate printf("maximum depth exceeded, ");
26380Sstevel@tonic-gate printf("try to cd lower\n");
26390Sstevel@tonic-gate error++;
26400Sstevel@tonic-gate return;
26410Sstevel@tonic-gate }
26420Sstevel@tonic-gate for (i = 0; i <= fnn->len; i++)
26430Sstevel@tonic-gate fnnn->fname[i] = fnn->fname[i];
26440Sstevel@tonic-gate }
26450Sstevel@tonic-gate if (fn == tos)
26460Sstevel@tonic-gate fn--;
26470Sstevel@tonic-gate top--;
26480Sstevel@tonic-gate bos--;
26490Sstevel@tonic-gate nfiles--;
26500Sstevel@tonic-gate }
26510Sstevel@tonic-gate follow_path(level + 1, cur_inum);
26520Sstevel@tonic-gate if (error)
26530Sstevel@tonic-gate return;
26540Sstevel@tonic-gate }
26550Sstevel@tonic-gate }
26560Sstevel@tonic-gate }
26570Sstevel@tonic-gate
26580Sstevel@tonic-gate /*
26590Sstevel@tonic-gate * getname - break up the pathname entered by the user into components.
26600Sstevel@tonic-gate */
26610Sstevel@tonic-gate static void
getname()26620Sstevel@tonic-gate getname()
26630Sstevel@tonic-gate {
26641051Smaheshvs int i;
26651051Smaheshvs char c;
26660Sstevel@tonic-gate
26670Sstevel@tonic-gate if ((c = getachar()) == '\n') {
26680Sstevel@tonic-gate ungetachar(c);
26690Sstevel@tonic-gate return;
26700Sstevel@tonic-gate }
26710Sstevel@tonic-gate ungetachar(c);
26720Sstevel@tonic-gate input_pathp++;
26730Sstevel@tonic-gate clear:
26740Sstevel@tonic-gate for (i = 0; i < MAXNAMLEN; i++)
26750Sstevel@tonic-gate input_path[input_pathp][i] = '\0';
26760Sstevel@tonic-gate for (;;) {
26770Sstevel@tonic-gate c = getachar();
26780Sstevel@tonic-gate if (c == '\\') {
26790Sstevel@tonic-gate if ((int)strlen(input_path[input_pathp]) + 1 >= MAXNAMLEN) {
26800Sstevel@tonic-gate printf("maximum name length exceeded, ");
26810Sstevel@tonic-gate printf("truncating\n");
26820Sstevel@tonic-gate return;
26830Sstevel@tonic-gate }
26840Sstevel@tonic-gate input_path[input_pathp][strlen(input_path[input_pathp])] = c;
26850Sstevel@tonic-gate input_path[input_pathp][strlen(input_path[input_pathp])] =
26860Sstevel@tonic-gate getachar();
26870Sstevel@tonic-gate continue;
26880Sstevel@tonic-gate }
26890Sstevel@tonic-gate if (c == ' ' || c == '\n') {
26900Sstevel@tonic-gate ungetachar(c);
26910Sstevel@tonic-gate return;
26920Sstevel@tonic-gate }
26930Sstevel@tonic-gate if (!doing_find && c == '/') {
26940Sstevel@tonic-gate if (++input_pathp >= MAXPATHLEN) {
26950Sstevel@tonic-gate printf("maximum path length exceeded, ");
26960Sstevel@tonic-gate printf("truncating\n");
26970Sstevel@tonic-gate input_pathp--;
26980Sstevel@tonic-gate return;
26990Sstevel@tonic-gate }
27000Sstevel@tonic-gate goto clear;
27010Sstevel@tonic-gate }
27020Sstevel@tonic-gate if ((int)strlen(input_path[input_pathp]) >= MAXNAMLEN) {
27030Sstevel@tonic-gate printf("maximum name length exceeded, truncating\n");
27040Sstevel@tonic-gate return;
27050Sstevel@tonic-gate }
27060Sstevel@tonic-gate input_path[input_pathp][strlen(input_path[input_pathp])] = c;
27070Sstevel@tonic-gate }
27080Sstevel@tonic-gate }
27090Sstevel@tonic-gate
27100Sstevel@tonic-gate /*
27110Sstevel@tonic-gate * compare - check if a filename matches the pattern entered by the user.
27120Sstevel@tonic-gate * Handles '*', '?', and '[]'.
27130Sstevel@tonic-gate */
27140Sstevel@tonic-gate static int
compare(char * s1,char * s2,short at_start)27151051Smaheshvs compare(char *s1, char *s2, short at_start)
27160Sstevel@tonic-gate {
27171051Smaheshvs char c, *s;
27180Sstevel@tonic-gate
27190Sstevel@tonic-gate s = s2;
27200Sstevel@tonic-gate while ((c = *s1) != NULL) {
27210Sstevel@tonic-gate if (c == '*') {
27220Sstevel@tonic-gate if (at_start && s == s2 && !letter(*s2) && !digit(*s2))
27230Sstevel@tonic-gate return (0);
27240Sstevel@tonic-gate if (*++s1 == 0)
27250Sstevel@tonic-gate return (1);
27260Sstevel@tonic-gate while (*s2) {
27270Sstevel@tonic-gate if (compare(s1, s2, 0))
27280Sstevel@tonic-gate return (1);
27290Sstevel@tonic-gate if (error)
27300Sstevel@tonic-gate return (0);
27310Sstevel@tonic-gate s2++;
27320Sstevel@tonic-gate }
27330Sstevel@tonic-gate }
27340Sstevel@tonic-gate if (*s2 == 0)
27350Sstevel@tonic-gate return (0);
27360Sstevel@tonic-gate if (c == '\\') {
27370Sstevel@tonic-gate s1++;
27380Sstevel@tonic-gate goto compare_chars;
27390Sstevel@tonic-gate }
27400Sstevel@tonic-gate if (c == '?') {
27410Sstevel@tonic-gate if (at_start && s == s2 && !letter(*s2) && !digit(*s2))
27420Sstevel@tonic-gate return (0);
27430Sstevel@tonic-gate s1++;
27440Sstevel@tonic-gate s2++;
27450Sstevel@tonic-gate continue;
27460Sstevel@tonic-gate }
27470Sstevel@tonic-gate if (c == '[') {
27480Sstevel@tonic-gate s1++;
27490Sstevel@tonic-gate if (*s2 >= *s1++) {
27500Sstevel@tonic-gate if (*s1++ != '-') {
27510Sstevel@tonic-gate printf("missing '-'\n");
27520Sstevel@tonic-gate error++;
27530Sstevel@tonic-gate return (0);
27540Sstevel@tonic-gate }
27550Sstevel@tonic-gate if (*s2 <= *s1++) {
27560Sstevel@tonic-gate if (*s1++ != ']') {
27570Sstevel@tonic-gate printf("missing ']'");
27580Sstevel@tonic-gate error++;
27590Sstevel@tonic-gate return (0);
27600Sstevel@tonic-gate }
27610Sstevel@tonic-gate s2++;
27620Sstevel@tonic-gate continue;
27630Sstevel@tonic-gate }
27640Sstevel@tonic-gate }
27650Sstevel@tonic-gate }
27660Sstevel@tonic-gate compare_chars:
27670Sstevel@tonic-gate if (*s1++ == *s2++)
27680Sstevel@tonic-gate continue;
27690Sstevel@tonic-gate else
27700Sstevel@tonic-gate return (0);
27710Sstevel@tonic-gate }
27720Sstevel@tonic-gate if (*s1 == *s2)
27730Sstevel@tonic-gate return (1);
27740Sstevel@tonic-gate return (0);
27750Sstevel@tonic-gate }
27760Sstevel@tonic-gate
27770Sstevel@tonic-gate /*
27780Sstevel@tonic-gate * freemem - free the memory allocated to the filenames structure.
27790Sstevel@tonic-gate */
27800Sstevel@tonic-gate static void
freemem(struct filenames * p,int numb)27811051Smaheshvs freemem(struct filenames *p, int numb)
27820Sstevel@tonic-gate {
27831051Smaheshvs int i, j;
27840Sstevel@tonic-gate
27850Sstevel@tonic-gate if (numb == 0)
27860Sstevel@tonic-gate return;
27870Sstevel@tonic-gate for (i = 0; i < numb; i++, p++) {
27880Sstevel@tonic-gate for (j = 0; j <= p->len; j++)
27890Sstevel@tonic-gate free(p->fname[j]);
27900Sstevel@tonic-gate free((char *)p->fname);
27910Sstevel@tonic-gate }
27920Sstevel@tonic-gate }
27930Sstevel@tonic-gate
27940Sstevel@tonic-gate /*
27950Sstevel@tonic-gate * print_path - print the pathname held in p.
27960Sstevel@tonic-gate */
27970Sstevel@tonic-gate static void
print_path(char * p[],int pntr)27981051Smaheshvs print_path(char *p[], int pntr)
27990Sstevel@tonic-gate {
28001051Smaheshvs int i;
28010Sstevel@tonic-gate
28020Sstevel@tonic-gate printf("/");
28030Sstevel@tonic-gate if (pntr >= 0) {
28040Sstevel@tonic-gate for (i = 0; i < pntr; i++)
28050Sstevel@tonic-gate printf("%s/", p[i]);
28060Sstevel@tonic-gate printf("%s", p[pntr]);
28070Sstevel@tonic-gate }
28080Sstevel@tonic-gate }
28090Sstevel@tonic-gate
28100Sstevel@tonic-gate /*
28110Sstevel@tonic-gate * fill - fill a section with a value or string.
28120Sstevel@tonic-gate * addr,count:fill=[value, "string"].
28130Sstevel@tonic-gate */
28140Sstevel@tonic-gate static void
fill()28150Sstevel@tonic-gate fill()
28160Sstevel@tonic-gate {
28171051Smaheshvs char *cptr;
28181051Smaheshvs int i;
28190Sstevel@tonic-gate short eof_flag, end = 0, eof = 0;
28200Sstevel@tonic-gate long temp, tcount;
28210Sstevel@tonic-gate u_offset_t taddr;
28220Sstevel@tonic-gate
28230Sstevel@tonic-gate if (wrtflag == O_RDONLY) {
28240Sstevel@tonic-gate printf("not opened for write '-w'\n");
28250Sstevel@tonic-gate error++;
28260Sstevel@tonic-gate return;
28270Sstevel@tonic-gate }
28280Sstevel@tonic-gate temp = expr();
28290Sstevel@tonic-gate if (error)
28300Sstevel@tonic-gate return;
28310Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
28320Sstevel@tonic-gate return;
28330Sstevel@tonic-gate if (type == NUMB)
28340Sstevel@tonic-gate eof_flag = 0;
28350Sstevel@tonic-gate else
28360Sstevel@tonic-gate eof_flag = 1;
28370Sstevel@tonic-gate taddr = addr;
28380Sstevel@tonic-gate switch (objsz) {
28390Sstevel@tonic-gate case LONG:
28400Sstevel@tonic-gate addr &= ~(LONG - 1);
28410Sstevel@tonic-gate break;
28420Sstevel@tonic-gate case SHORT:
28430Sstevel@tonic-gate addr &= ~(SHORT - 1);
28440Sstevel@tonic-gate temp &= 0177777L;
28450Sstevel@tonic-gate break;
28460Sstevel@tonic-gate case CHAR:
28470Sstevel@tonic-gate temp &= 0377;
28480Sstevel@tonic-gate }
28490Sstevel@tonic-gate cur_bytes -= taddr - addr;
28500Sstevel@tonic-gate cptr += blkoff(fs, addr);
28510Sstevel@tonic-gate tcount = check_addr(eof_flag, &end, &eof, 0);
28520Sstevel@tonic-gate for (i = 0; i < tcount; i++) {
28530Sstevel@tonic-gate switch (objsz) {
28540Sstevel@tonic-gate case LONG:
28550Sstevel@tonic-gate /*LINTED*/
28560Sstevel@tonic-gate *(long *)cptr = temp;
28570Sstevel@tonic-gate break;
28580Sstevel@tonic-gate case SHORT:
28590Sstevel@tonic-gate /*LINTED*/
28600Sstevel@tonic-gate *(short *)cptr = temp;
28610Sstevel@tonic-gate break;
28620Sstevel@tonic-gate case CHAR:
28630Sstevel@tonic-gate *cptr = temp;
28640Sstevel@tonic-gate }
28650Sstevel@tonic-gate cptr += objsz;
28660Sstevel@tonic-gate }
28670Sstevel@tonic-gate addr += (tcount - 1) * objsz;
28680Sstevel@tonic-gate cur_bytes += (tcount - 1) * objsz;
28690Sstevel@tonic-gate put((u_offset_t)temp, objsz);
28700Sstevel@tonic-gate if (eof) {
28710Sstevel@tonic-gate printf("end of file\n");
28720Sstevel@tonic-gate error++;
28730Sstevel@tonic-gate } else if (end) {
28740Sstevel@tonic-gate printf("end of block\n");
28750Sstevel@tonic-gate error++;
28760Sstevel@tonic-gate }
28770Sstevel@tonic-gate }
28780Sstevel@tonic-gate
28790Sstevel@tonic-gate /*
28800Sstevel@tonic-gate * get - read a byte, short or long from the file system.
28810Sstevel@tonic-gate * The entire block containing the desired item is read
28820Sstevel@tonic-gate * and the appropriate data is extracted and returned.
28830Sstevel@tonic-gate */
28840Sstevel@tonic-gate static offset_t
get(short lngth)28851051Smaheshvs get(short lngth)
28860Sstevel@tonic-gate {
28870Sstevel@tonic-gate
28881051Smaheshvs char *bptr;
28890Sstevel@tonic-gate u_offset_t temp = addr;
28900Sstevel@tonic-gate
28910Sstevel@tonic-gate objsz = lngth;
28920Sstevel@tonic-gate if (objsz == INODE || objsz == SHORT)
28930Sstevel@tonic-gate temp &= ~(SHORT - 1);
28940Sstevel@tonic-gate else if (objsz == DIRECTORY || objsz == LONG || objsz == SHADOW_DATA)
28950Sstevel@tonic-gate temp &= ~(LONG - 1);
28960Sstevel@tonic-gate if ((bptr = getblk(temp)) == 0)
28970Sstevel@tonic-gate return (-1);
28980Sstevel@tonic-gate bptr += blkoff(fs, temp);
28990Sstevel@tonic-gate switch (objsz) {
29000Sstevel@tonic-gate case CHAR:
29010Sstevel@tonic-gate return ((offset_t)*bptr);
29020Sstevel@tonic-gate case SHORT:
29030Sstevel@tonic-gate case INODE:
29040Sstevel@tonic-gate /*LINTED*/
29050Sstevel@tonic-gate return ((offset_t)(*(short *)bptr));
29060Sstevel@tonic-gate case LONG:
29070Sstevel@tonic-gate case DIRECTORY:
29080Sstevel@tonic-gate case SHADOW_DATA:
29090Sstevel@tonic-gate /*LINTED*/
29100Sstevel@tonic-gate return ((offset_t)(*(long *)bptr));
29110Sstevel@tonic-gate case U_OFFSET_T:
29120Sstevel@tonic-gate /*LINTED*/
29130Sstevel@tonic-gate return (*(offset_t *)bptr);
29140Sstevel@tonic-gate }
29150Sstevel@tonic-gate return (0);
29160Sstevel@tonic-gate }
29170Sstevel@tonic-gate
29180Sstevel@tonic-gate /*
29190Sstevel@tonic-gate * cgrp_check - make sure that we don't bump the cylinder group
29200Sstevel@tonic-gate * beyond the total number of cylinder groups or before the start.
29210Sstevel@tonic-gate */
29220Sstevel@tonic-gate static int
cgrp_check(long cgrp)29231051Smaheshvs cgrp_check(long cgrp)
29240Sstevel@tonic-gate {
29250Sstevel@tonic-gate if (cgrp < 0) {
29260Sstevel@tonic-gate if (objsz == CGRP)
29270Sstevel@tonic-gate printf("beginning of cylinder groups\n");
29280Sstevel@tonic-gate else
29290Sstevel@tonic-gate printf("beginning of super blocks\n");
29300Sstevel@tonic-gate error++;
29310Sstevel@tonic-gate return (0);
29320Sstevel@tonic-gate }
29330Sstevel@tonic-gate if (cgrp >= fs->fs_ncg) {
29340Sstevel@tonic-gate if (objsz == CGRP)
29350Sstevel@tonic-gate printf("end of cylinder groups\n");
29360Sstevel@tonic-gate else
29370Sstevel@tonic-gate printf("end of super blocks\n");
29380Sstevel@tonic-gate error++;
29390Sstevel@tonic-gate return (0);
29400Sstevel@tonic-gate }
29410Sstevel@tonic-gate if (objsz == CGRP)
29420Sstevel@tonic-gate return (cgtod(fs, cgrp) << FRGSHIFT);
29430Sstevel@tonic-gate else
29440Sstevel@tonic-gate return (cgsblock(fs, cgrp) << FRGSHIFT);
29450Sstevel@tonic-gate }
29460Sstevel@tonic-gate
29470Sstevel@tonic-gate /*
29480Sstevel@tonic-gate * icheck - make sure we can read the block containing the inode
29490Sstevel@tonic-gate * and determine the filesize (0 if inode not allocated). Return
29500Sstevel@tonic-gate * 0 if error otherwise return the mode.
29510Sstevel@tonic-gate */
29521051Smaheshvs int
icheck(u_offset_t address)29531051Smaheshvs icheck(u_offset_t address)
29540Sstevel@tonic-gate {
29551051Smaheshvs char *cptr;
29561051Smaheshvs struct dinode *ip;
29570Sstevel@tonic-gate
29580Sstevel@tonic-gate if ((cptr = getblk(address)) == 0)
29590Sstevel@tonic-gate return (0);
29600Sstevel@tonic-gate cptr += blkoff(fs, address);
29610Sstevel@tonic-gate /*LINTED*/
29620Sstevel@tonic-gate ip = (struct dinode *)cptr;
29630Sstevel@tonic-gate if ((ip->di_mode & IFMT) == 0) {
29640Sstevel@tonic-gate if (!override) {
29650Sstevel@tonic-gate printf("inode not allocated\n");
29660Sstevel@tonic-gate error++;
29670Sstevel@tonic-gate return (0);
29680Sstevel@tonic-gate }
29690Sstevel@tonic-gate blocksize = filesize = 0;
29700Sstevel@tonic-gate } else {
29710Sstevel@tonic-gate trapped++;
29720Sstevel@tonic-gate filesize = ip->di_size;
29730Sstevel@tonic-gate blocksize = filesize * 2;
29740Sstevel@tonic-gate }
29750Sstevel@tonic-gate return (ip->di_mode);
29760Sstevel@tonic-gate }
29770Sstevel@tonic-gate
29780Sstevel@tonic-gate /*
29790Sstevel@tonic-gate * getdirslot - get the address of the directory slot desired.
29800Sstevel@tonic-gate */
29810Sstevel@tonic-gate static u_offset_t
getdirslot(long slot)29821051Smaheshvs getdirslot(long slot)
29830Sstevel@tonic-gate {
29841051Smaheshvs char *cptr;
29851051Smaheshvs struct direct *dirp;
29861051Smaheshvs short i;
29871051Smaheshvs char *string = &scratch[0];
29881051Smaheshvs short bod = 0, mode, temp;
29890Sstevel@tonic-gate
29900Sstevel@tonic-gate if (slot < 0) {
29910Sstevel@tonic-gate slot = 0;
29920Sstevel@tonic-gate bod++;
29930Sstevel@tonic-gate }
29940Sstevel@tonic-gate if (type != DIRECTORY) {
29950Sstevel@tonic-gate if (type == BLOCK)
29960Sstevel@tonic-gate string = "block";
29970Sstevel@tonic-gate else
29980Sstevel@tonic-gate string = "fragment";
29990Sstevel@tonic-gate addr = bod_addr;
30000Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
30010Sstevel@tonic-gate return (0);
30020Sstevel@tonic-gate cptr += blkoff(fs, addr);
30030Sstevel@tonic-gate cur_bytes = 0;
30040Sstevel@tonic-gate /*LINTED*/
30050Sstevel@tonic-gate dirp = (struct direct *)cptr;
30060Sstevel@tonic-gate for (dirslot = 0; dirslot < slot; dirslot++) {
30070Sstevel@tonic-gate /*LINTED*/
30080Sstevel@tonic-gate dirp = (struct direct *)cptr;
30090Sstevel@tonic-gate if (blocksize > filesize) {
30100Sstevel@tonic-gate if (cur_bytes + (long)dirp->d_reclen >=
30110Sstevel@tonic-gate filesize) {
30120Sstevel@tonic-gate printf("end of file\n");
30130Sstevel@tonic-gate erraddr = addr;
30140Sstevel@tonic-gate errcur_bytes = cur_bytes;
30150Sstevel@tonic-gate stringsize = STRINGSIZE(dirp);
30160Sstevel@tonic-gate error++;
30170Sstevel@tonic-gate return (addr);
30180Sstevel@tonic-gate }
30190Sstevel@tonic-gate } else {
30200Sstevel@tonic-gate if (cur_bytes + (long)dirp->d_reclen >=
30210Sstevel@tonic-gate blocksize) {
30220Sstevel@tonic-gate printf("end of %s\n", string);
30230Sstevel@tonic-gate erraddr = addr;
30240Sstevel@tonic-gate errcur_bytes = cur_bytes;
30250Sstevel@tonic-gate stringsize = STRINGSIZE(dirp);
30260Sstevel@tonic-gate error++;
30270Sstevel@tonic-gate return (addr);
30280Sstevel@tonic-gate }
30290Sstevel@tonic-gate }
30300Sstevel@tonic-gate cptr += dirp->d_reclen;
30310Sstevel@tonic-gate addr += dirp->d_reclen;
30320Sstevel@tonic-gate cur_bytes += dirp->d_reclen;
30330Sstevel@tonic-gate }
30340Sstevel@tonic-gate if (bod) {
30350Sstevel@tonic-gate if (blocksize > filesize)
30360Sstevel@tonic-gate printf("beginning of file\n");
30370Sstevel@tonic-gate else
30380Sstevel@tonic-gate printf("beginning of %s\n", string);
30390Sstevel@tonic-gate erraddr = addr;
30400Sstevel@tonic-gate errcur_bytes = cur_bytes;
30410Sstevel@tonic-gate error++;
30420Sstevel@tonic-gate }
30430Sstevel@tonic-gate stringsize = STRINGSIZE(dirp);
30440Sstevel@tonic-gate return (addr);
30450Sstevel@tonic-gate } else {
30460Sstevel@tonic-gate addr = cur_ino;
30470Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
30480Sstevel@tonic-gate return (0);
30490Sstevel@tonic-gate if (!override && (mode & IFDIR) == 0) {
30500Sstevel@tonic-gate printf("inode is not a directory\n");
30510Sstevel@tonic-gate error++;
30520Sstevel@tonic-gate return (0);
30530Sstevel@tonic-gate }
30540Sstevel@tonic-gate temp = slot;
30550Sstevel@tonic-gate i = cur_bytes = 0;
30560Sstevel@tonic-gate for (;;) {
30570Sstevel@tonic-gate if (i == 0 || bcomp(addr)) {
30580Sstevel@tonic-gate error = 0;
30590Sstevel@tonic-gate if ((addr = (bmap((long)i++) << FRGSHIFT)) == 0)
30600Sstevel@tonic-gate break;
30610Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
30620Sstevel@tonic-gate break;
30630Sstevel@tonic-gate cptr += blkoff(fs, addr);
30640Sstevel@tonic-gate }
30650Sstevel@tonic-gate /*LINTED*/
30660Sstevel@tonic-gate dirp = (struct direct *)cptr;
30670Sstevel@tonic-gate value = dirp->d_ino;
30680Sstevel@tonic-gate if (!temp--)
30690Sstevel@tonic-gate break;
30700Sstevel@tonic-gate if (cur_bytes + (long)dirp->d_reclen >= filesize) {
30710Sstevel@tonic-gate printf("end of file\n");
30720Sstevel@tonic-gate dirslot = slot - temp - 1;
30730Sstevel@tonic-gate objsz = DIRECTORY;
30740Sstevel@tonic-gate erraddr = addr;
30750Sstevel@tonic-gate errcur_bytes = cur_bytes;
30760Sstevel@tonic-gate stringsize = STRINGSIZE(dirp);
30770Sstevel@tonic-gate error++;
30780Sstevel@tonic-gate return (addr);
30790Sstevel@tonic-gate }
30800Sstevel@tonic-gate addr += dirp->d_reclen;
30810Sstevel@tonic-gate cptr += dirp->d_reclen;
30820Sstevel@tonic-gate cur_bytes += dirp->d_reclen;
30830Sstevel@tonic-gate }
30840Sstevel@tonic-gate dirslot = slot;
30850Sstevel@tonic-gate objsz = DIRECTORY;
30860Sstevel@tonic-gate if (bod) {
30870Sstevel@tonic-gate printf("beginning of file\n");
30880Sstevel@tonic-gate erraddr = addr;
30890Sstevel@tonic-gate errcur_bytes = cur_bytes;
30900Sstevel@tonic-gate error++;
30910Sstevel@tonic-gate }
30920Sstevel@tonic-gate stringsize = STRINGSIZE(dirp);
30930Sstevel@tonic-gate return (addr);
30940Sstevel@tonic-gate }
30950Sstevel@tonic-gate }
30960Sstevel@tonic-gate
30970Sstevel@tonic-gate
30980Sstevel@tonic-gate /*
30990Sstevel@tonic-gate * getshadowslot - get the address of the shadow data desired
31000Sstevel@tonic-gate */
31010Sstevel@tonic-gate static int
getshadowslot(long shadow)31021051Smaheshvs getshadowslot(long shadow)
31030Sstevel@tonic-gate {
31040Sstevel@tonic-gate struct ufs_fsd fsd;
31050Sstevel@tonic-gate short bod = 0, mode;
31060Sstevel@tonic-gate long taddr, tcurbytes;
31070Sstevel@tonic-gate
31080Sstevel@tonic-gate if (shadow < 0) {
31090Sstevel@tonic-gate shadow = 0;
31100Sstevel@tonic-gate bod++;
31110Sstevel@tonic-gate }
31120Sstevel@tonic-gate if (type != SHADOW_DATA) {
31130Sstevel@tonic-gate if (shadow < cur_shad) {
31140Sstevel@tonic-gate printf("can't scan shadow data in reverse\n");
31150Sstevel@tonic-gate error++;
31160Sstevel@tonic-gate return (0);
31170Sstevel@tonic-gate }
31180Sstevel@tonic-gate } else {
31190Sstevel@tonic-gate addr = cur_ino;
31200Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
31210Sstevel@tonic-gate return (0);
31220Sstevel@tonic-gate if (!override && (mode & IFMT) != IFSHAD) {
31230Sstevel@tonic-gate printf("inode is not a shadow\n");
31240Sstevel@tonic-gate error++;
31250Sstevel@tonic-gate return (0);
31260Sstevel@tonic-gate }
31270Sstevel@tonic-gate cur_bytes = 0;
31280Sstevel@tonic-gate cur_shad = 0;
31290Sstevel@tonic-gate syncshadowscan(1); /* force synchronization */
31300Sstevel@tonic-gate }
31310Sstevel@tonic-gate
31320Sstevel@tonic-gate for (; cur_shad < shadow; cur_shad++) {
31330Sstevel@tonic-gate taddr = addr;
31340Sstevel@tonic-gate tcurbytes = cur_bytes;
31350Sstevel@tonic-gate getshadowdata((long *)&fsd, LONG + LONG);
31360Sstevel@tonic-gate addr = taddr;
31370Sstevel@tonic-gate cur_bytes = tcurbytes;
31380Sstevel@tonic-gate if (cur_bytes + (long)fsd.fsd_size > filesize) {
31390Sstevel@tonic-gate syncshadowscan(0);
31400Sstevel@tonic-gate printf("end of file\n");
31410Sstevel@tonic-gate erraddr = addr;
31420Sstevel@tonic-gate errcur_bytes = cur_bytes;
31430Sstevel@tonic-gate error++;
31440Sstevel@tonic-gate return (addr);
31450Sstevel@tonic-gate }
31460Sstevel@tonic-gate addr += fsd.fsd_size;
31470Sstevel@tonic-gate cur_bytes += fsd.fsd_size;
31480Sstevel@tonic-gate syncshadowscan(0);
31490Sstevel@tonic-gate }
31500Sstevel@tonic-gate if (type == SHADOW_DATA)
31510Sstevel@tonic-gate objsz = SHADOW_DATA;
31520Sstevel@tonic-gate if (bod) {
31530Sstevel@tonic-gate printf("beginning of file\n");
31540Sstevel@tonic-gate erraddr = addr;
31550Sstevel@tonic-gate errcur_bytes = cur_bytes;
31560Sstevel@tonic-gate error++;
31570Sstevel@tonic-gate }
31580Sstevel@tonic-gate return (addr);
31590Sstevel@tonic-gate }
31600Sstevel@tonic-gate
31610Sstevel@tonic-gate static void
getshadowdata(long * buf,int len)31621051Smaheshvs getshadowdata(long *buf, int len)
31630Sstevel@tonic-gate {
31640Sstevel@tonic-gate long tfsd;
31650Sstevel@tonic-gate
31660Sstevel@tonic-gate len /= LONG;
31670Sstevel@tonic-gate for (tfsd = 0; tfsd < len; tfsd++) {
31680Sstevel@tonic-gate buf[tfsd] = get(SHADOW_DATA);
31690Sstevel@tonic-gate addr += LONG;
31700Sstevel@tonic-gate cur_bytes += LONG;
31710Sstevel@tonic-gate syncshadowscan(0);
31720Sstevel@tonic-gate }
31730Sstevel@tonic-gate }
31740Sstevel@tonic-gate
31750Sstevel@tonic-gate static void
syncshadowscan(int force)31761051Smaheshvs syncshadowscan(int force)
31770Sstevel@tonic-gate {
31780Sstevel@tonic-gate long curblkoff;
31790Sstevel@tonic-gate if (type == SHADOW_DATA && (force ||
31800Sstevel@tonic-gate lblkno(fs, addr) != (bhdr.fwd)->blkno)) {
31810Sstevel@tonic-gate curblkoff = blkoff(fs, cur_bytes);
31820Sstevel@tonic-gate addr = bmap(lblkno(fs, cur_bytes)) << FRGSHIFT;
31830Sstevel@tonic-gate addr += curblkoff;
31840Sstevel@tonic-gate cur_bytes += curblkoff;
31850Sstevel@tonic-gate (void) getblk(addr);
31860Sstevel@tonic-gate objsz = SHADOW_DATA;
31870Sstevel@tonic-gate }
31880Sstevel@tonic-gate }
31890Sstevel@tonic-gate
31900Sstevel@tonic-gate
31910Sstevel@tonic-gate
31920Sstevel@tonic-gate /*
31930Sstevel@tonic-gate * putf - print a byte as an ascii character if possible.
31940Sstevel@tonic-gate * The exceptions are tabs, newlines, backslashes
31950Sstevel@tonic-gate * and nulls which are printed as the standard C
31960Sstevel@tonic-gate * language escapes. Characters which are not
31970Sstevel@tonic-gate * recognized are printed as \?.
31980Sstevel@tonic-gate */
31990Sstevel@tonic-gate static void
putf(char c)32001051Smaheshvs putf(char c)
32010Sstevel@tonic-gate {
32020Sstevel@tonic-gate
32030Sstevel@tonic-gate if (c <= 037 || c >= 0177 || c == '\\') {
32040Sstevel@tonic-gate printf("\\");
32050Sstevel@tonic-gate switch (c) {
32060Sstevel@tonic-gate case '\\':
32070Sstevel@tonic-gate printf("\\");
32080Sstevel@tonic-gate break;
32090Sstevel@tonic-gate case '\t':
32100Sstevel@tonic-gate printf("t");
32110Sstevel@tonic-gate break;
32120Sstevel@tonic-gate case '\n':
32130Sstevel@tonic-gate printf("n");
32140Sstevel@tonic-gate break;
32150Sstevel@tonic-gate case '\0':
32160Sstevel@tonic-gate printf("0");
32170Sstevel@tonic-gate break;
32180Sstevel@tonic-gate default:
32190Sstevel@tonic-gate printf("?");
32200Sstevel@tonic-gate }
32210Sstevel@tonic-gate } else {
32220Sstevel@tonic-gate printf("%c", c);
32230Sstevel@tonic-gate printf(" ");
32240Sstevel@tonic-gate }
32250Sstevel@tonic-gate }
32260Sstevel@tonic-gate
32270Sstevel@tonic-gate /*
32280Sstevel@tonic-gate * put - write an item into the buffer for the current address
32290Sstevel@tonic-gate * block. The value is checked to make sure that it will
32300Sstevel@tonic-gate * fit in the size given without truncation. If successful,
32310Sstevel@tonic-gate * the entire block is written back to the file system.
32320Sstevel@tonic-gate */
32330Sstevel@tonic-gate static void
put(u_offset_t item,short lngth)32341051Smaheshvs put(u_offset_t item, short lngth)
32350Sstevel@tonic-gate {
32360Sstevel@tonic-gate
32371051Smaheshvs char *bptr, *sbptr;
32381051Smaheshvs long s_err, nbytes;
32391051Smaheshvs long olditem;
32400Sstevel@tonic-gate
32410Sstevel@tonic-gate if (wrtflag == O_RDONLY) {
32420Sstevel@tonic-gate printf("not opened for write '-w'\n");
32430Sstevel@tonic-gate error++;
32440Sstevel@tonic-gate return;
32450Sstevel@tonic-gate }
32460Sstevel@tonic-gate objsz = lngth;
32470Sstevel@tonic-gate if ((sbptr = getblk(addr)) == 0)
32480Sstevel@tonic-gate return;
32490Sstevel@tonic-gate bptr = sbptr + blkoff(fs, addr);
32500Sstevel@tonic-gate switch (objsz) {
32510Sstevel@tonic-gate case LONG:
32520Sstevel@tonic-gate case DIRECTORY:
32530Sstevel@tonic-gate /*LINTED*/
32540Sstevel@tonic-gate olditem = *(long *)bptr;
32550Sstevel@tonic-gate /*LINTED*/
32560Sstevel@tonic-gate *(long *)bptr = item;
32570Sstevel@tonic-gate break;
32580Sstevel@tonic-gate case SHORT:
32590Sstevel@tonic-gate case INODE:
32600Sstevel@tonic-gate /*LINTED*/
32610Sstevel@tonic-gate olditem = (long)*(short *)bptr;
32620Sstevel@tonic-gate item &= 0177777L;
32630Sstevel@tonic-gate /*LINTED*/
32640Sstevel@tonic-gate *(short *)bptr = item;
32650Sstevel@tonic-gate break;
32660Sstevel@tonic-gate case CHAR:
32670Sstevel@tonic-gate olditem = (long)*bptr;
32680Sstevel@tonic-gate item &= 0377;
32690Sstevel@tonic-gate *bptr = lobyte(loword(item));
32700Sstevel@tonic-gate break;
32710Sstevel@tonic-gate default:
32720Sstevel@tonic-gate error++;
32730Sstevel@tonic-gate return;
32740Sstevel@tonic-gate }
32750Sstevel@tonic-gate if ((s_err = llseek(fd, (offset_t)(addr & fs->fs_bmask), 0)) == -1) {
32760Sstevel@tonic-gate error++;
32770Sstevel@tonic-gate printf("seek error : %" PRIx64 "\n", addr);
32780Sstevel@tonic-gate return;
32790Sstevel@tonic-gate }
32800Sstevel@tonic-gate if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) {
32810Sstevel@tonic-gate error++;
32820Sstevel@tonic-gate printf("write error : addr = %" PRIx64 "\n", addr);
32830Sstevel@tonic-gate printf(" : s_err = %lx\n", s_err);
32840Sstevel@tonic-gate printf(" : nbytes = %lx\n", nbytes);
32850Sstevel@tonic-gate return;
32860Sstevel@tonic-gate }
32870Sstevel@tonic-gate if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) {
32880Sstevel@tonic-gate index(base);
32890Sstevel@tonic-gate print(olditem, 8, -8, 0);
32900Sstevel@tonic-gate printf("\t=\t");
32910Sstevel@tonic-gate print(item, 8, -8, 0);
32920Sstevel@tonic-gate printf("\n");
32930Sstevel@tonic-gate } else {
32940Sstevel@tonic-gate if (objsz == DIRECTORY) {
32950Sstevel@tonic-gate addr = cur_dir;
32960Sstevel@tonic-gate fprnt('?', 'd');
32970Sstevel@tonic-gate } else {
32980Sstevel@tonic-gate addr = cur_ino;
32990Sstevel@tonic-gate objsz = INODE;
33000Sstevel@tonic-gate fprnt('?', 'i');
33010Sstevel@tonic-gate }
33020Sstevel@tonic-gate }
33030Sstevel@tonic-gate }
33040Sstevel@tonic-gate
33050Sstevel@tonic-gate /*
33060Sstevel@tonic-gate * getblk - check if the desired block is in the file system.
33070Sstevel@tonic-gate * Search the incore buffers to see if the block is already
33080Sstevel@tonic-gate * available. If successful, unlink the buffer control block
33090Sstevel@tonic-gate * from its position in the buffer list and re-insert it at
33100Sstevel@tonic-gate * the head of the list. If failure, use the last buffer
33110Sstevel@tonic-gate * in the list for the desired block. Again, this control
33120Sstevel@tonic-gate * block is placed at the head of the list. This process
33130Sstevel@tonic-gate * will leave commonly requested blocks in the in-core buffers.
33140Sstevel@tonic-gate * Finally, a pointer to the buffer is returned.
33150Sstevel@tonic-gate */
33160Sstevel@tonic-gate static char *
getblk(u_offset_t address)33171051Smaheshvs getblk(u_offset_t address)
33180Sstevel@tonic-gate {
33190Sstevel@tonic-gate
33201051Smaheshvs struct lbuf *bp;
33211051Smaheshvs long s_err, nbytes;
33221051Smaheshvs unsigned long block;
33230Sstevel@tonic-gate
33240Sstevel@tonic-gate read_requests++;
33250Sstevel@tonic-gate block = lblkno(fs, address);
33260Sstevel@tonic-gate if (block >= fragstoblks(fs, fs->fs_size)) {
33270Sstevel@tonic-gate printf("cannot read block %lu\n", block);
33280Sstevel@tonic-gate error++;
33290Sstevel@tonic-gate return (0);
33300Sstevel@tonic-gate }
33310Sstevel@tonic-gate for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd)
33320Sstevel@tonic-gate if (bp->valid && bp->blkno == block)
33330Sstevel@tonic-gate goto xit;
33340Sstevel@tonic-gate actual_disk_reads++;
33350Sstevel@tonic-gate bp = bhdr.back;
33360Sstevel@tonic-gate bp->blkno = block;
33370Sstevel@tonic-gate bp->valid = 0;
33380Sstevel@tonic-gate if ((s_err = llseek(fd, (offset_t)(address & fs->fs_bmask), 0)) == -1) {
33390Sstevel@tonic-gate error++;
33400Sstevel@tonic-gate printf("seek error : %" PRIx64 "\n", address);
33410Sstevel@tonic-gate return (0);
33420Sstevel@tonic-gate }
33430Sstevel@tonic-gate if ((nbytes = read(fd, bp->blkaddr, BLKSIZE)) != BLKSIZE) {
33440Sstevel@tonic-gate error++;
33450Sstevel@tonic-gate printf("read error : addr = %" PRIx64 "\n", address);
33460Sstevel@tonic-gate printf(" : s_err = %lx\n", s_err);
33470Sstevel@tonic-gate printf(" : nbytes = %lx\n", nbytes);
33480Sstevel@tonic-gate return (0);
33490Sstevel@tonic-gate }
33500Sstevel@tonic-gate bp->valid++;
33510Sstevel@tonic-gate xit: bp->back->fwd = bp->fwd;
33520Sstevel@tonic-gate bp->fwd->back = bp->back;
33530Sstevel@tonic-gate insert(bp);
33540Sstevel@tonic-gate return (bp->blkaddr);
33550Sstevel@tonic-gate }
33560Sstevel@tonic-gate
33570Sstevel@tonic-gate /*
33580Sstevel@tonic-gate * insert - place the designated buffer control block
33590Sstevel@tonic-gate * at the head of the linked list of buffers.
33600Sstevel@tonic-gate */
33610Sstevel@tonic-gate static void
insert(struct lbuf * bp)33621051Smaheshvs insert(struct lbuf *bp)
33630Sstevel@tonic-gate {
33640Sstevel@tonic-gate
33650Sstevel@tonic-gate bp->back = &bhdr;
33660Sstevel@tonic-gate bp->fwd = bhdr.fwd;
33670Sstevel@tonic-gate bhdr.fwd->back = bp;
33680Sstevel@tonic-gate bhdr.fwd = bp;
33690Sstevel@tonic-gate }
33700Sstevel@tonic-gate
33710Sstevel@tonic-gate /*
33720Sstevel@tonic-gate * err - called on interrupts. Set the current address
33730Sstevel@tonic-gate * back to the last address stored in erraddr. Reset all
33740Sstevel@tonic-gate * appropriate flags. A reset call is made to return
33750Sstevel@tonic-gate * to the main loop;
33760Sstevel@tonic-gate */
33770Sstevel@tonic-gate #ifdef sun
33780Sstevel@tonic-gate /*ARGSUSED*/
33790Sstevel@tonic-gate static void
err(int sig)33801051Smaheshvs err(int sig)
33810Sstevel@tonic-gate #else
33820Sstevel@tonic-gate err()
33830Sstevel@tonic-gate #endif /* sun */
33840Sstevel@tonic-gate {
33850Sstevel@tonic-gate freemem(filenames, nfiles);
33860Sstevel@tonic-gate nfiles = 0;
33870Sstevel@tonic-gate (void) signal(2, err);
33880Sstevel@tonic-gate addr = erraddr;
33890Sstevel@tonic-gate cur_ino = errino;
33900Sstevel@tonic-gate cur_inum = errinum;
33910Sstevel@tonic-gate cur_bytes = errcur_bytes;
33920Sstevel@tonic-gate error = 0;
33930Sstevel@tonic-gate c_count = 0;
33940Sstevel@tonic-gate printf("\n?\n");
33950Sstevel@tonic-gate (void) fseek(stdin, 0L, 2);
33960Sstevel@tonic-gate longjmp(env, 0);
33970Sstevel@tonic-gate }
33980Sstevel@tonic-gate
33990Sstevel@tonic-gate /*
34000Sstevel@tonic-gate * devcheck - check that the given mode represents a
34010Sstevel@tonic-gate * special device. The IFCHR bit is on for both
34020Sstevel@tonic-gate * character and block devices.
34030Sstevel@tonic-gate */
34040Sstevel@tonic-gate static int
devcheck(short md)34051051Smaheshvs devcheck(short md)
34060Sstevel@tonic-gate {
34070Sstevel@tonic-gate if (override)
34080Sstevel@tonic-gate return (0);
34090Sstevel@tonic-gate switch (md & IFMT) {
34100Sstevel@tonic-gate case IFCHR:
34110Sstevel@tonic-gate case IFBLK:
34120Sstevel@tonic-gate return (0);
34130Sstevel@tonic-gate }
34140Sstevel@tonic-gate
34150Sstevel@tonic-gate printf("not character or block device\n");
34160Sstevel@tonic-gate error++;
34170Sstevel@tonic-gate return (1);
34180Sstevel@tonic-gate }
34190Sstevel@tonic-gate
34200Sstevel@tonic-gate /*
34210Sstevel@tonic-gate * nullblk - return error if address is zero. This is done
34220Sstevel@tonic-gate * to prevent block 0 from being used as an indirect block
34230Sstevel@tonic-gate * for a large file or as a data block for a small file.
34240Sstevel@tonic-gate */
34250Sstevel@tonic-gate static int
nullblk(long bn)34261051Smaheshvs nullblk(long bn)
34270Sstevel@tonic-gate {
34280Sstevel@tonic-gate if (bn != 0)
34290Sstevel@tonic-gate return (0);
34300Sstevel@tonic-gate printf("non existent block\n");
34310Sstevel@tonic-gate error++;
34320Sstevel@tonic-gate return (1);
34330Sstevel@tonic-gate }
34340Sstevel@tonic-gate
34350Sstevel@tonic-gate /*
34360Sstevel@tonic-gate * puta - put ascii characters into a buffer. The string
34370Sstevel@tonic-gate * terminates with a quote or newline. The leading quote,
34380Sstevel@tonic-gate * which is optional for directory names, was stripped off
34390Sstevel@tonic-gate * by the assignment case in the main loop.
34400Sstevel@tonic-gate */
34410Sstevel@tonic-gate static void
puta()34420Sstevel@tonic-gate puta()
34430Sstevel@tonic-gate {
34441051Smaheshvs char *cptr, c;
34451051Smaheshvs int i;
34461051Smaheshvs char *sbptr;
34471051Smaheshvs short terror = 0;
34481051Smaheshvs long maxchars, s_err, nbytes, temp;
34491051Smaheshvs u_offset_t taddr = addr;
34501051Smaheshvs long tcount = 0, item, olditem = 0;
34510Sstevel@tonic-gate
34520Sstevel@tonic-gate if (wrtflag == O_RDONLY) {
34530Sstevel@tonic-gate printf("not opened for write '-w'\n");
34540Sstevel@tonic-gate error++;
34550Sstevel@tonic-gate return;
34560Sstevel@tonic-gate }
34570Sstevel@tonic-gate if ((sbptr = getblk(addr)) == 0)
34580Sstevel@tonic-gate return;
34590Sstevel@tonic-gate cptr = sbptr + blkoff(fs, addr);
34600Sstevel@tonic-gate if (objsz == DIRECTORY) {
34610Sstevel@tonic-gate if (acting_on_directory)
34620Sstevel@tonic-gate maxchars = stringsize - 1;
34630Sstevel@tonic-gate else
34640Sstevel@tonic-gate maxchars = LONG;
34650Sstevel@tonic-gate } else if (objsz == INODE)
34660Sstevel@tonic-gate maxchars = objsz - (addr - cur_ino);
34670Sstevel@tonic-gate else
34680Sstevel@tonic-gate maxchars = min(blocksize - cur_bytes, filesize - cur_bytes);
34690Sstevel@tonic-gate while ((c = getachar()) != '"') {
34700Sstevel@tonic-gate if (tcount >= maxchars) {
34710Sstevel@tonic-gate printf("string too long\n");
34720Sstevel@tonic-gate if (objsz == DIRECTORY)
34730Sstevel@tonic-gate addr = cur_dir;
34740Sstevel@tonic-gate else if (acting_on_inode || objsz == INODE)
34750Sstevel@tonic-gate addr = cur_ino;
34760Sstevel@tonic-gate else
34770Sstevel@tonic-gate addr = taddr;
34780Sstevel@tonic-gate erraddr = addr;
34790Sstevel@tonic-gate errcur_bytes = cur_bytes;
34800Sstevel@tonic-gate terror++;
34810Sstevel@tonic-gate break;
34820Sstevel@tonic-gate }
34830Sstevel@tonic-gate tcount++;
34840Sstevel@tonic-gate if (c == '\n') {
34850Sstevel@tonic-gate ungetachar(c);
34860Sstevel@tonic-gate break;
34870Sstevel@tonic-gate }
34880Sstevel@tonic-gate temp = (long)*cptr;
34890Sstevel@tonic-gate olditem <<= BITSPERCHAR;
34900Sstevel@tonic-gate olditem += temp & 0xff;
34910Sstevel@tonic-gate if (c == '\\') {
34920Sstevel@tonic-gate switch (c = getachar()) {
34930Sstevel@tonic-gate case 't':
34940Sstevel@tonic-gate *cptr++ = '\t';
34950Sstevel@tonic-gate break;
34960Sstevel@tonic-gate case 'n':
34970Sstevel@tonic-gate *cptr++ = '\n';
34980Sstevel@tonic-gate break;
34990Sstevel@tonic-gate case '0':
35000Sstevel@tonic-gate *cptr++ = '\0';
35010Sstevel@tonic-gate break;
35020Sstevel@tonic-gate default:
35030Sstevel@tonic-gate *cptr++ = c;
35040Sstevel@tonic-gate break;
35050Sstevel@tonic-gate }
35060Sstevel@tonic-gate }
35070Sstevel@tonic-gate else
35080Sstevel@tonic-gate *cptr++ = c;
35090Sstevel@tonic-gate }
35100Sstevel@tonic-gate if (objsz == DIRECTORY && acting_on_directory)
35110Sstevel@tonic-gate for (i = tcount; i <= maxchars; i++)
35120Sstevel@tonic-gate *cptr++ = '\0';
35130Sstevel@tonic-gate if ((s_err = llseek(fd, (offset_t)(addr & fs->fs_bmask), 0)) == -1) {
35140Sstevel@tonic-gate error++;
35150Sstevel@tonic-gate printf("seek error : %" PRIx64 "\n", addr);
35160Sstevel@tonic-gate return;
35170Sstevel@tonic-gate }
35180Sstevel@tonic-gate if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) {
35190Sstevel@tonic-gate error++;
35200Sstevel@tonic-gate printf("write error : addr = %" PRIx64 "\n", addr);
35210Sstevel@tonic-gate printf(" : s_err = %lx\n", s_err);
35220Sstevel@tonic-gate printf(" : nbytes = %lx\n", nbytes);
35230Sstevel@tonic-gate return;
35240Sstevel@tonic-gate }
35250Sstevel@tonic-gate if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) {
35260Sstevel@tonic-gate addr += tcount;
35270Sstevel@tonic-gate cur_bytes += tcount;
35280Sstevel@tonic-gate taddr = addr;
35290Sstevel@tonic-gate if (objsz != CHAR) {
35300Sstevel@tonic-gate addr &= ~(objsz - 1);
35310Sstevel@tonic-gate cur_bytes -= taddr - addr;
35320Sstevel@tonic-gate }
35330Sstevel@tonic-gate if (addr == taddr) {
35340Sstevel@tonic-gate addr -= objsz;
35350Sstevel@tonic-gate taddr = addr;
35360Sstevel@tonic-gate }
35370Sstevel@tonic-gate tcount = LONG - (taddr - addr);
35380Sstevel@tonic-gate index(base);
35390Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
35400Sstevel@tonic-gate return;
35410Sstevel@tonic-gate cptr += blkoff(fs, addr);
35420Sstevel@tonic-gate switch (objsz) {
35430Sstevel@tonic-gate case LONG:
35440Sstevel@tonic-gate /*LINTED*/
35450Sstevel@tonic-gate item = *(long *)cptr;
35460Sstevel@tonic-gate if (tcount < LONG) {
35470Sstevel@tonic-gate olditem <<= tcount * BITSPERCHAR;
35480Sstevel@tonic-gate temp = 1;
35490Sstevel@tonic-gate for (i = 0; i < (tcount*BITSPERCHAR); i++)
35500Sstevel@tonic-gate temp <<= 1;
35510Sstevel@tonic-gate olditem += item & (temp - 1);
35520Sstevel@tonic-gate }
35530Sstevel@tonic-gate break;
35540Sstevel@tonic-gate case SHORT:
35550Sstevel@tonic-gate /*LINTED*/
35560Sstevel@tonic-gate item = (long)*(short *)cptr;
35570Sstevel@tonic-gate if (tcount < SHORT) {
35580Sstevel@tonic-gate olditem <<= tcount * BITSPERCHAR;
35590Sstevel@tonic-gate temp = 1;
35600Sstevel@tonic-gate for (i = 0; i < (tcount * BITSPERCHAR); i++)
35610Sstevel@tonic-gate temp <<= 1;
35620Sstevel@tonic-gate olditem += item & (temp - 1);
35630Sstevel@tonic-gate }
35640Sstevel@tonic-gate olditem &= 0177777L;
35650Sstevel@tonic-gate break;
35660Sstevel@tonic-gate case CHAR:
35670Sstevel@tonic-gate item = (long)*cptr;
35680Sstevel@tonic-gate olditem &= 0377;
35690Sstevel@tonic-gate }
35700Sstevel@tonic-gate print(olditem, 8, -8, 0);
35710Sstevel@tonic-gate printf("\t=\t");
35720Sstevel@tonic-gate print(item, 8, -8, 0);
35730Sstevel@tonic-gate printf("\n");
35740Sstevel@tonic-gate } else {
35750Sstevel@tonic-gate if (objsz == DIRECTORY) {
35760Sstevel@tonic-gate addr = cur_dir;
35770Sstevel@tonic-gate fprnt('?', 'd');
35780Sstevel@tonic-gate } else {
35790Sstevel@tonic-gate addr = cur_ino;
35800Sstevel@tonic-gate objsz = INODE;
35810Sstevel@tonic-gate fprnt('?', 'i');
35820Sstevel@tonic-gate }
35830Sstevel@tonic-gate }
35840Sstevel@tonic-gate if (terror)
35850Sstevel@tonic-gate error++;
35860Sstevel@tonic-gate }
35870Sstevel@tonic-gate
35880Sstevel@tonic-gate /*
35890Sstevel@tonic-gate * fprnt - print data. 'count' elements are printed where '*' will
35900Sstevel@tonic-gate * print an entire blocks worth or up to the eof, whichever
35910Sstevel@tonic-gate * occurs first. An error will occur if crossing a block boundary
35920Sstevel@tonic-gate * is attempted since consecutive blocks don't usually have
35930Sstevel@tonic-gate * meaning. Current print types:
35940Sstevel@tonic-gate * / b - print as bytes (base sensitive)
35950Sstevel@tonic-gate * c - print as characters
35960Sstevel@tonic-gate * o O - print as octal shorts (longs)
35970Sstevel@tonic-gate * d D - print as decimal shorts (longs)
35980Sstevel@tonic-gate * x X - print as hexadecimal shorts (longs)
35990Sstevel@tonic-gate * ? c - print as cylinder groups
36000Sstevel@tonic-gate * d - print as directories
36010Sstevel@tonic-gate * i - print as inodes
36020Sstevel@tonic-gate * s - print as super blocks
36030Sstevel@tonic-gate * S - print as shadow data
36040Sstevel@tonic-gate */
36050Sstevel@tonic-gate static void
fprnt(char style,char po)36061051Smaheshvs fprnt(char style, char po)
36070Sstevel@tonic-gate {
36081051Smaheshvs int i;
36091051Smaheshvs struct fs *sb;
36101051Smaheshvs struct cg *cg;
36111051Smaheshvs struct direct *dirp;
36121051Smaheshvs struct dinode *ip;
36131051Smaheshvs int tbase;
36141051Smaheshvs char c, *cptr, *p;
36151051Smaheshvs long tinode, tcount, temp;
36161051Smaheshvs u_offset_t taddr;
36171051Smaheshvs short offset, mode, end = 0, eof = 0, eof_flag;
36181051Smaheshvs unsigned short *sptr;
36191051Smaheshvs unsigned long *lptr;
36201051Smaheshvs offset_t curoff, curioff;
36210Sstevel@tonic-gate
36220Sstevel@tonic-gate laststyle = style;
36230Sstevel@tonic-gate lastpo = po;
36240Sstevel@tonic-gate should_print = 0;
36250Sstevel@tonic-gate if (count != 1) {
36260Sstevel@tonic-gate if (clear) {
36270Sstevel@tonic-gate count = 1;
36280Sstevel@tonic-gate star = 0;
36290Sstevel@tonic-gate clear = 0;
36300Sstevel@tonic-gate } else
36310Sstevel@tonic-gate clear = 1;
36320Sstevel@tonic-gate }
36330Sstevel@tonic-gate tcount = count;
36340Sstevel@tonic-gate offset = blkoff(fs, addr);
36350Sstevel@tonic-gate
36360Sstevel@tonic-gate if (style == '/') {
36370Sstevel@tonic-gate if (type == NUMB)
36380Sstevel@tonic-gate eof_flag = 0;
36390Sstevel@tonic-gate else
36400Sstevel@tonic-gate eof_flag = 1;
36410Sstevel@tonic-gate switch (po) {
36420Sstevel@tonic-gate
36430Sstevel@tonic-gate case 'c': /* print as characters */
36440Sstevel@tonic-gate case 'b': /* or bytes */
36450Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
36460Sstevel@tonic-gate return;
36470Sstevel@tonic-gate cptr += offset;
36480Sstevel@tonic-gate objsz = CHAR;
36490Sstevel@tonic-gate tcount = check_addr(eof_flag, &end, &eof, 0);
36500Sstevel@tonic-gate if (tcount) {
36510Sstevel@tonic-gate for (i = 0; tcount--; i++) {
36520Sstevel@tonic-gate if (i % 16 == 0) {
36530Sstevel@tonic-gate if (i)
36540Sstevel@tonic-gate printf("\n");
36550Sstevel@tonic-gate index(base);
36560Sstevel@tonic-gate }
36570Sstevel@tonic-gate if (po == 'c') {
36580Sstevel@tonic-gate putf(*cptr++);
36590Sstevel@tonic-gate if ((i + 1) % 16)
36600Sstevel@tonic-gate printf(" ");
36610Sstevel@tonic-gate } else {
36620Sstevel@tonic-gate if ((i + 1) % 16 == 0)
36630Sstevel@tonic-gate print(*cptr++ & 0377L,
36640Sstevel@tonic-gate 2, -2, 0);
36650Sstevel@tonic-gate else
36660Sstevel@tonic-gate print(*cptr++ & 0377L,
36670Sstevel@tonic-gate 4, -2, 0);
36680Sstevel@tonic-gate }
36690Sstevel@tonic-gate addr += CHAR;
36700Sstevel@tonic-gate cur_bytes += CHAR;
36710Sstevel@tonic-gate }
36720Sstevel@tonic-gate printf("\n");
36730Sstevel@tonic-gate }
36740Sstevel@tonic-gate addr -= CHAR;
36750Sstevel@tonic-gate erraddr = addr;
36760Sstevel@tonic-gate cur_bytes -= CHAR;
36770Sstevel@tonic-gate errcur_bytes = cur_bytes;
36780Sstevel@tonic-gate if (eof) {
36790Sstevel@tonic-gate printf("end of file\n");
36800Sstevel@tonic-gate error++;
36810Sstevel@tonic-gate } else if (end) {
36820Sstevel@tonic-gate if (type == BLOCK)
36830Sstevel@tonic-gate printf("end of block\n");
36840Sstevel@tonic-gate else
36850Sstevel@tonic-gate printf("end of fragment\n");
36860Sstevel@tonic-gate error++;
36870Sstevel@tonic-gate }
36880Sstevel@tonic-gate return;
36890Sstevel@tonic-gate
36900Sstevel@tonic-gate case 'o': /* print as octal shorts */
36910Sstevel@tonic-gate tbase = OCTAL;
36920Sstevel@tonic-gate goto otx;
36930Sstevel@tonic-gate case 'd': /* print as decimal shorts */
36940Sstevel@tonic-gate tbase = DECIMAL;
36950Sstevel@tonic-gate goto otx;
36960Sstevel@tonic-gate case 'x': /* print as hex shorts */
36970Sstevel@tonic-gate tbase = HEX;
36980Sstevel@tonic-gate otx:
36990Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
37000Sstevel@tonic-gate return;
37010Sstevel@tonic-gate taddr = addr;
37020Sstevel@tonic-gate addr &= ~(SHORT - 1);
37030Sstevel@tonic-gate cur_bytes -= taddr - addr;
37040Sstevel@tonic-gate cptr += blkoff(fs, addr);
37050Sstevel@tonic-gate /*LINTED*/
37060Sstevel@tonic-gate sptr = (unsigned short *)cptr;
37070Sstevel@tonic-gate objsz = SHORT;
37080Sstevel@tonic-gate tcount = check_addr(eof_flag, &end, &eof, 0);
37090Sstevel@tonic-gate if (tcount) {
37100Sstevel@tonic-gate for (i = 0; tcount--; i++) {
37110Sstevel@tonic-gate sptr = (unsigned short *)print_check(
37120Sstevel@tonic-gate /*LINTED*/
37130Sstevel@tonic-gate (unsigned long *)sptr,
37140Sstevel@tonic-gate &tcount, tbase, i);
37150Sstevel@tonic-gate switch (po) {
37160Sstevel@tonic-gate case 'o':
37170Sstevel@tonic-gate printf("%06o ", *sptr++);
37180Sstevel@tonic-gate break;
37190Sstevel@tonic-gate case 'd':
37200Sstevel@tonic-gate printf("%05d ", *sptr++);
37210Sstevel@tonic-gate break;
37220Sstevel@tonic-gate case 'x':
37230Sstevel@tonic-gate printf("%04x ", *sptr++);
37240Sstevel@tonic-gate }
37250Sstevel@tonic-gate addr += SHORT;
37260Sstevel@tonic-gate cur_bytes += SHORT;
37270Sstevel@tonic-gate }
37280Sstevel@tonic-gate printf("\n");
37290Sstevel@tonic-gate }
37300Sstevel@tonic-gate addr -= SHORT;
37310Sstevel@tonic-gate erraddr = addr;
37320Sstevel@tonic-gate cur_bytes -= SHORT;
37330Sstevel@tonic-gate errcur_bytes = cur_bytes;
37340Sstevel@tonic-gate if (eof) {
37350Sstevel@tonic-gate printf("end of file\n");
37360Sstevel@tonic-gate error++;
37370Sstevel@tonic-gate } else if (end) {
37380Sstevel@tonic-gate if (type == BLOCK)
37390Sstevel@tonic-gate printf("end of block\n");
37400Sstevel@tonic-gate else
37410Sstevel@tonic-gate printf("end of fragment\n");
37420Sstevel@tonic-gate error++;
37430Sstevel@tonic-gate }
37440Sstevel@tonic-gate return;
37450Sstevel@tonic-gate
37460Sstevel@tonic-gate case 'O': /* print as octal longs */
37470Sstevel@tonic-gate tbase = OCTAL;
37480Sstevel@tonic-gate goto OTX;
37490Sstevel@tonic-gate case 'D': /* print as decimal longs */
37500Sstevel@tonic-gate tbase = DECIMAL;
37510Sstevel@tonic-gate goto OTX;
37520Sstevel@tonic-gate case 'X': /* print as hex longs */
37530Sstevel@tonic-gate tbase = HEX;
37540Sstevel@tonic-gate OTX:
37550Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
37560Sstevel@tonic-gate return;
37570Sstevel@tonic-gate taddr = addr;
37580Sstevel@tonic-gate addr &= ~(LONG - 1);
37590Sstevel@tonic-gate cur_bytes -= taddr - addr;
37600Sstevel@tonic-gate cptr += blkoff(fs, addr);
37610Sstevel@tonic-gate /*LINTED*/
37620Sstevel@tonic-gate lptr = (unsigned long *)cptr;
37630Sstevel@tonic-gate objsz = LONG;
37640Sstevel@tonic-gate tcount = check_addr(eof_flag, &end, &eof, 0);
37650Sstevel@tonic-gate if (tcount) {
37660Sstevel@tonic-gate for (i = 0; tcount--; i++) {
37670Sstevel@tonic-gate lptr = print_check(lptr, &tcount,
37680Sstevel@tonic-gate tbase, i);
37690Sstevel@tonic-gate switch (po) {
37700Sstevel@tonic-gate case 'O':
37710Sstevel@tonic-gate printf("%011lo ", *lptr++);
37720Sstevel@tonic-gate break;
37730Sstevel@tonic-gate case 'D':
37740Sstevel@tonic-gate printf("%010lu ", *lptr++);
37750Sstevel@tonic-gate break;
37760Sstevel@tonic-gate case 'X':
37770Sstevel@tonic-gate printf("%08lx ", *lptr++);
37780Sstevel@tonic-gate }
37790Sstevel@tonic-gate addr += LONG;
37800Sstevel@tonic-gate cur_bytes += LONG;
37810Sstevel@tonic-gate }
37820Sstevel@tonic-gate printf("\n");
37830Sstevel@tonic-gate }
37840Sstevel@tonic-gate addr -= LONG;
37850Sstevel@tonic-gate erraddr = addr;
37860Sstevel@tonic-gate cur_bytes -= LONG;
37870Sstevel@tonic-gate errcur_bytes = cur_bytes;
37880Sstevel@tonic-gate if (eof) {
37890Sstevel@tonic-gate printf("end of file\n");
37900Sstevel@tonic-gate error++;
37910Sstevel@tonic-gate } else if (end) {
37920Sstevel@tonic-gate if (type == BLOCK)
37930Sstevel@tonic-gate printf("end of block\n");
37940Sstevel@tonic-gate else
37950Sstevel@tonic-gate printf("end of fragment\n");
37960Sstevel@tonic-gate error++;
37970Sstevel@tonic-gate }
37980Sstevel@tonic-gate return;
37990Sstevel@tonic-gate
38000Sstevel@tonic-gate default:
38010Sstevel@tonic-gate error++;
38020Sstevel@tonic-gate printf("no such print option\n");
38030Sstevel@tonic-gate return;
38040Sstevel@tonic-gate }
38050Sstevel@tonic-gate } else
38060Sstevel@tonic-gate switch (po) {
38070Sstevel@tonic-gate
38080Sstevel@tonic-gate case 'c': /* print as cylinder group */
38090Sstevel@tonic-gate if (type != NUMB)
38100Sstevel@tonic-gate if (cur_cgrp + count > fs->fs_ncg) {
38110Sstevel@tonic-gate tcount = fs->fs_ncg - cur_cgrp;
38120Sstevel@tonic-gate if (!star)
38130Sstevel@tonic-gate end++;
38140Sstevel@tonic-gate }
38150Sstevel@tonic-gate addr &= ~(LONG - 1);
38160Sstevel@tonic-gate for (/* void */; tcount--; /* void */) {
38170Sstevel@tonic-gate erraddr = addr;
38180Sstevel@tonic-gate errcur_bytes = cur_bytes;
38190Sstevel@tonic-gate if (type != NUMB) {
38200Sstevel@tonic-gate addr = cgtod(fs, cur_cgrp)
38210Sstevel@tonic-gate << FRGSHIFT;
38220Sstevel@tonic-gate cur_cgrp++;
38230Sstevel@tonic-gate }
38240Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0) {
38250Sstevel@tonic-gate if (cur_cgrp)
38260Sstevel@tonic-gate cur_cgrp--;
38270Sstevel@tonic-gate return;
38280Sstevel@tonic-gate }
38290Sstevel@tonic-gate cptr += blkoff(fs, addr);
38300Sstevel@tonic-gate /*LINTED*/
38310Sstevel@tonic-gate cg = (struct cg *)cptr;
38320Sstevel@tonic-gate if (type == NUMB) {
38330Sstevel@tonic-gate cur_cgrp = cg->cg_cgx + 1;
38340Sstevel@tonic-gate type = objsz = CGRP;
38350Sstevel@tonic-gate if (cur_cgrp + count - 1 > fs->fs_ncg) {
38360Sstevel@tonic-gate tcount = fs->fs_ncg - cur_cgrp;
38370Sstevel@tonic-gate if (!star)
38380Sstevel@tonic-gate end++;
38390Sstevel@tonic-gate }
38400Sstevel@tonic-gate }
38410Sstevel@tonic-gate if (! override && !cg_chkmagic(cg)) {
38420Sstevel@tonic-gate printf("invalid cylinder group ");
38430Sstevel@tonic-gate printf("magic word\n");
38440Sstevel@tonic-gate if (cur_cgrp)
38450Sstevel@tonic-gate cur_cgrp--;
38460Sstevel@tonic-gate error++;
38470Sstevel@tonic-gate return;
38480Sstevel@tonic-gate }
38490Sstevel@tonic-gate printcg(cg);
38500Sstevel@tonic-gate if (tcount)
38510Sstevel@tonic-gate printf("\n");
38520Sstevel@tonic-gate }
38530Sstevel@tonic-gate cur_cgrp--;
38540Sstevel@tonic-gate if (end) {
38550Sstevel@tonic-gate printf("end of cylinder groups\n");
38560Sstevel@tonic-gate error++;
38570Sstevel@tonic-gate }
38580Sstevel@tonic-gate return;
38590Sstevel@tonic-gate
38600Sstevel@tonic-gate case 'd': /* print as directories */
38610Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0)
38620Sstevel@tonic-gate return;
38630Sstevel@tonic-gate if (type == NUMB) {
38640Sstevel@tonic-gate if (fragoff(fs, addr)) {
38650Sstevel@tonic-gate printf("address must be at the ");
38660Sstevel@tonic-gate printf("beginning of a fragment\n");
38670Sstevel@tonic-gate error++;
38680Sstevel@tonic-gate return;
38690Sstevel@tonic-gate }
38700Sstevel@tonic-gate bod_addr = addr;
38710Sstevel@tonic-gate type = FRAGMENT;
38720Sstevel@tonic-gate dirslot = 0;
38730Sstevel@tonic-gate cur_bytes = 0;
38740Sstevel@tonic-gate blocksize = FRGSIZE;
38750Sstevel@tonic-gate filesize = FRGSIZE * 2;
38760Sstevel@tonic-gate }
38770Sstevel@tonic-gate cptr += offset;
38780Sstevel@tonic-gate objsz = DIRECTORY;
38790Sstevel@tonic-gate while (tcount-- && cur_bytes < filesize &&
38800Sstevel@tonic-gate cur_bytes < blocksize && !bcomp(addr)) {
38810Sstevel@tonic-gate /*LINTED*/
38820Sstevel@tonic-gate dirp = (struct direct *)cptr;
38830Sstevel@tonic-gate tinode = dirp->d_ino;
38840Sstevel@tonic-gate printf("i#: ");
38850Sstevel@tonic-gate if (tinode == 0)
38860Sstevel@tonic-gate printf("free\t");
38870Sstevel@tonic-gate else
38880Sstevel@tonic-gate print(tinode, 12, -8, 0);
38890Sstevel@tonic-gate printf("%s\n", &dirp->d_name[0]);
38900Sstevel@tonic-gate erraddr = addr;
38910Sstevel@tonic-gate errcur_bytes = cur_bytes;
38920Sstevel@tonic-gate addr += dirp->d_reclen;
38930Sstevel@tonic-gate cptr += dirp->d_reclen;
38940Sstevel@tonic-gate cur_bytes += dirp->d_reclen;
38950Sstevel@tonic-gate dirslot++;
38960Sstevel@tonic-gate stringsize = STRINGSIZE(dirp);
38970Sstevel@tonic-gate }
38980Sstevel@tonic-gate addr = erraddr;
38990Sstevel@tonic-gate cur_dir = addr;
39000Sstevel@tonic-gate cur_bytes = errcur_bytes;
39010Sstevel@tonic-gate dirslot--;
39020Sstevel@tonic-gate if (tcount >= 0 && !star) {
39030Sstevel@tonic-gate switch (type) {
39040Sstevel@tonic-gate case FRAGMENT:
39050Sstevel@tonic-gate printf("end of fragment\n");
39060Sstevel@tonic-gate break;
39070Sstevel@tonic-gate case BLOCK:
39080Sstevel@tonic-gate printf("end of block\n");
39090Sstevel@tonic-gate break;
39100Sstevel@tonic-gate default:
39110Sstevel@tonic-gate printf("end of directory\n");
39120Sstevel@tonic-gate }
39130Sstevel@tonic-gate error++;
39140Sstevel@tonic-gate } else
39150Sstevel@tonic-gate error = 0;
39160Sstevel@tonic-gate return;
39170Sstevel@tonic-gate
39180Sstevel@tonic-gate case 'i': /* print as inodes */
39190Sstevel@tonic-gate /*LINTED*/
39200Sstevel@tonic-gate if ((ip = (struct dinode *)getblk(addr)) == 0)
39210Sstevel@tonic-gate return;
39220Sstevel@tonic-gate for (i = 1; i < fs->fs_ncg; i++)
39230Sstevel@tonic-gate if (addr < (cgimin(fs, i) << FRGSHIFT))
39240Sstevel@tonic-gate break;
39250Sstevel@tonic-gate i--;
39260Sstevel@tonic-gate offset /= INODE;
39270Sstevel@tonic-gate temp = (addr - (cgimin(fs, i) << FRGSHIFT)) >> FRGSHIFT;
39280Sstevel@tonic-gate temp = (i * fs->fs_ipg) + fragstoblks(fs, temp) *
39290Sstevel@tonic-gate INOPB(fs) + offset;
39300Sstevel@tonic-gate if (count + offset > INOPB(fs)) {
39310Sstevel@tonic-gate tcount = INOPB(fs) - offset;
39320Sstevel@tonic-gate if (!star)
39330Sstevel@tonic-gate end++;
39340Sstevel@tonic-gate }
39350Sstevel@tonic-gate objsz = INODE;
39360Sstevel@tonic-gate ip += offset;
39370Sstevel@tonic-gate for (i = 0; tcount--; ip++, temp++) {
39380Sstevel@tonic-gate if ((mode = icheck(addr)) == 0)
39390Sstevel@tonic-gate if (!override)
39400Sstevel@tonic-gate continue;
39410Sstevel@tonic-gate p = " ugtrwxrwxrwx";
39420Sstevel@tonic-gate
39430Sstevel@tonic-gate switch (mode & IFMT) {
39440Sstevel@tonic-gate case IFDIR:
39450Sstevel@tonic-gate c = 'd';
39460Sstevel@tonic-gate break;
39470Sstevel@tonic-gate case IFCHR:
39480Sstevel@tonic-gate c = 'c';
39490Sstevel@tonic-gate break;
39500Sstevel@tonic-gate case IFBLK:
39510Sstevel@tonic-gate c = 'b';
39520Sstevel@tonic-gate break;
39530Sstevel@tonic-gate case IFREG:
39540Sstevel@tonic-gate c = '-';
39550Sstevel@tonic-gate break;
39560Sstevel@tonic-gate case IFLNK:
39570Sstevel@tonic-gate c = 'l';
39580Sstevel@tonic-gate break;
39590Sstevel@tonic-gate case IFSOCK:
39600Sstevel@tonic-gate c = 's';
39610Sstevel@tonic-gate break;
39620Sstevel@tonic-gate case IFSHAD:
39630Sstevel@tonic-gate c = 'S';
39640Sstevel@tonic-gate break;
39650Sstevel@tonic-gate case IFATTRDIR:
39660Sstevel@tonic-gate c = 'A';
39670Sstevel@tonic-gate break;
39680Sstevel@tonic-gate default:
39690Sstevel@tonic-gate c = '?';
39700Sstevel@tonic-gate if (!override)
39710Sstevel@tonic-gate goto empty;
39720Sstevel@tonic-gate
39730Sstevel@tonic-gate }
39740Sstevel@tonic-gate printf("i#: ");
39750Sstevel@tonic-gate print(temp, 12, -8, 0);
39760Sstevel@tonic-gate printf(" md: ");
39770Sstevel@tonic-gate printf("%c", c);
39780Sstevel@tonic-gate for (mode = mode << 4; *++p; mode = mode << 1) {
39790Sstevel@tonic-gate if (mode & IFREG)
39800Sstevel@tonic-gate printf("%c", *p);
39810Sstevel@tonic-gate else
39820Sstevel@tonic-gate printf("-");
39830Sstevel@tonic-gate }
39840Sstevel@tonic-gate printf(" uid: ");
39850Sstevel@tonic-gate print(ip->di_uid, 8, -4, 0);
39860Sstevel@tonic-gate printf(" gid: ");
39870Sstevel@tonic-gate print(ip->di_gid, 8, -4, 0);
39880Sstevel@tonic-gate printf("\n");
39890Sstevel@tonic-gate printf("ln: ");
39900Sstevel@tonic-gate print((long)ip->di_nlink, 8, -4, 0);
39910Sstevel@tonic-gate printf(" bs: ");
39920Sstevel@tonic-gate print(ip->di_blocks, 12, -8, 0);
39930Sstevel@tonic-gate printf("c_flags : ");
39940Sstevel@tonic-gate print(ip->di_cflags, 12, -8, 0);
3995*12875SJohn.Zolnowsky@Sun.COM printf(" sz : ");
39960Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
39970Sstevel@tonic-gate printll(ip->di_size, 20, -16, 0);
39980Sstevel@tonic-gate #else /* !_LARGEFILE64_SOURCE */
39990Sstevel@tonic-gate print(ip->di_size, 12, -8, 0);
40000Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
40010Sstevel@tonic-gate if (ip->di_shadow) {
40020Sstevel@tonic-gate printf(" si: ");
40030Sstevel@tonic-gate print(ip->di_shadow, 12, -8, 0);
40040Sstevel@tonic-gate }
40050Sstevel@tonic-gate printf("\n");
40060Sstevel@tonic-gate if (ip->di_oeftflag) {
40070Sstevel@tonic-gate printf("ai: ");
40080Sstevel@tonic-gate print(ip->di_oeftflag, 12, -8, 0);
40090Sstevel@tonic-gate printf("\n");
40100Sstevel@tonic-gate }
40110Sstevel@tonic-gate printf("\n");
40120Sstevel@tonic-gate switch (ip->di_mode & IFMT) {
40130Sstevel@tonic-gate case IFBLK:
40140Sstevel@tonic-gate case IFCHR:
40150Sstevel@tonic-gate printf("maj: ");
40160Sstevel@tonic-gate print(major(ip->di_ordev), 4, -2, 0);
40170Sstevel@tonic-gate printf(" min: ");
40180Sstevel@tonic-gate print(minor(ip->di_ordev), 4, -2, 0);
40190Sstevel@tonic-gate printf("\n");
40200Sstevel@tonic-gate break;
40210Sstevel@tonic-gate default:
40220Sstevel@tonic-gate /*
40230Sstevel@tonic-gate * only display blocks below the
40240Sstevel@tonic-gate * current file size
40250Sstevel@tonic-gate */
40260Sstevel@tonic-gate curoff = 0LL;
40270Sstevel@tonic-gate for (i = 0; i < NDADDR; ) {
40280Sstevel@tonic-gate if (ip->di_size <= curoff)
40290Sstevel@tonic-gate break;
40300Sstevel@tonic-gate printf("db#%x: ", i);
40310Sstevel@tonic-gate print(ip->di_db[i], 11, -8, 0);
40320Sstevel@tonic-gate
40330Sstevel@tonic-gate if (++i % 4 == 0)
40340Sstevel@tonic-gate printf("\n");
40350Sstevel@tonic-gate else
40360Sstevel@tonic-gate printf(" ");
40370Sstevel@tonic-gate curoff += fs->fs_bsize;
40380Sstevel@tonic-gate }
40390Sstevel@tonic-gate if (i % 4)
40400Sstevel@tonic-gate printf("\n");
40410Sstevel@tonic-gate
40420Sstevel@tonic-gate /*
40430Sstevel@tonic-gate * curioff keeps track of the number
40440Sstevel@tonic-gate * of bytes covered by each indirect
40450Sstevel@tonic-gate * pointer in the inode, and is added
40460Sstevel@tonic-gate * to curoff each time to get the
40470Sstevel@tonic-gate * actual offset into the file.
40480Sstevel@tonic-gate */
40490Sstevel@tonic-gate curioff = fs->fs_bsize *
40500Sstevel@tonic-gate (fs->fs_bsize / sizeof (daddr_t));
40510Sstevel@tonic-gate for (i = 0; i < NIADDR; i++) {
40520Sstevel@tonic-gate if (ip->di_size <= curoff)
40530Sstevel@tonic-gate break;
40540Sstevel@tonic-gate printf("ib#%x: ", i);
40550Sstevel@tonic-gate print(ip->di_ib[i], 11, -8, 0);
40560Sstevel@tonic-gate printf(" ");
40570Sstevel@tonic-gate curoff += curioff;
40580Sstevel@tonic-gate curioff *= (fs->fs_bsize /
40590Sstevel@tonic-gate sizeof (daddr_t));
40600Sstevel@tonic-gate }
40610Sstevel@tonic-gate if (i)
40620Sstevel@tonic-gate printf("\n");
40630Sstevel@tonic-gate break;
40640Sstevel@tonic-gate }
40650Sstevel@tonic-gate if (count == 1) {
40660Sstevel@tonic-gate time_t t;
40670Sstevel@tonic-gate
40680Sstevel@tonic-gate t = ip->di_atime;
40690Sstevel@tonic-gate printf("\taccessed: %s", ctime(&t));
40700Sstevel@tonic-gate t = ip->di_mtime;
40710Sstevel@tonic-gate printf("\tmodified: %s", ctime(&t));
40720Sstevel@tonic-gate t = ip->di_ctime;
40730Sstevel@tonic-gate printf("\tcreated : %s", ctime(&t));
40740Sstevel@tonic-gate }
40750Sstevel@tonic-gate if (tcount)
40760Sstevel@tonic-gate printf("\n");
40770Sstevel@tonic-gate empty:
40780Sstevel@tonic-gate if (c == '?' && !override) {
40790Sstevel@tonic-gate printf("i#: ");
40800Sstevel@tonic-gate print(temp, 12, -8, 0);
40810Sstevel@tonic-gate printf(" is unallocated\n");
40820Sstevel@tonic-gate if (count != 1)
40830Sstevel@tonic-gate printf("\n");
40840Sstevel@tonic-gate }
40850Sstevel@tonic-gate cur_ino = erraddr = addr;
40860Sstevel@tonic-gate errcur_bytes = cur_bytes;
40870Sstevel@tonic-gate cur_inum++;
40880Sstevel@tonic-gate addr = addr + INODE;
40890Sstevel@tonic-gate }
40900Sstevel@tonic-gate addr = erraddr;
40910Sstevel@tonic-gate cur_bytes = errcur_bytes;
40920Sstevel@tonic-gate cur_inum--;
40930Sstevel@tonic-gate if (end) {
40940Sstevel@tonic-gate printf("end of block\n");
40950Sstevel@tonic-gate error++;
40960Sstevel@tonic-gate }
40970Sstevel@tonic-gate return;
40980Sstevel@tonic-gate
40990Sstevel@tonic-gate case 's': /* print as super block */
41000Sstevel@tonic-gate if (cur_cgrp == -1) {
41010Sstevel@tonic-gate addr = SBLOCK * DEV_BSIZE;
41020Sstevel@tonic-gate type = NUMB;
41030Sstevel@tonic-gate }
41040Sstevel@tonic-gate addr &= ~(LONG - 1);
41050Sstevel@tonic-gate if (type != NUMB)
41060Sstevel@tonic-gate if (cur_cgrp + count > fs->fs_ncg) {
41070Sstevel@tonic-gate tcount = fs->fs_ncg - cur_cgrp;
41080Sstevel@tonic-gate if (!star)
41090Sstevel@tonic-gate end++;
41100Sstevel@tonic-gate }
41110Sstevel@tonic-gate for (/* void */; tcount--; /* void */) {
41120Sstevel@tonic-gate erraddr = addr;
41130Sstevel@tonic-gate cur_bytes = errcur_bytes;
41140Sstevel@tonic-gate if (type != NUMB) {
41150Sstevel@tonic-gate addr = cgsblock(fs, cur_cgrp)
41160Sstevel@tonic-gate << FRGSHIFT;
41170Sstevel@tonic-gate cur_cgrp++;
41180Sstevel@tonic-gate }
41190Sstevel@tonic-gate if ((cptr = getblk(addr)) == 0) {
41200Sstevel@tonic-gate if (cur_cgrp)
41210Sstevel@tonic-gate cur_cgrp--;
41220Sstevel@tonic-gate return;
41230Sstevel@tonic-gate }
41240Sstevel@tonic-gate cptr += blkoff(fs, addr);
41250Sstevel@tonic-gate /*LINTED*/
41260Sstevel@tonic-gate sb = (struct fs *)cptr;
41270Sstevel@tonic-gate if (type == NUMB) {
41280Sstevel@tonic-gate for (i = 0; i < fs->fs_ncg; i++)
41290Sstevel@tonic-gate if (addr == cgsblock(fs, i) <<
41300Sstevel@tonic-gate FRGSHIFT)
41310Sstevel@tonic-gate break;
41320Sstevel@tonic-gate if (i == fs->fs_ncg)
41330Sstevel@tonic-gate cur_cgrp = 0;
41340Sstevel@tonic-gate else
41350Sstevel@tonic-gate cur_cgrp = i + 1;
41360Sstevel@tonic-gate type = objsz = SB;
41370Sstevel@tonic-gate if (cur_cgrp + count - 1 > fs->fs_ncg) {
41380Sstevel@tonic-gate tcount = fs->fs_ncg - cur_cgrp;
41390Sstevel@tonic-gate if (!star)
41400Sstevel@tonic-gate end++;
41410Sstevel@tonic-gate }
41420Sstevel@tonic-gate }
41430Sstevel@tonic-gate if ((sb->fs_magic != FS_MAGIC) &&
41440Sstevel@tonic-gate (sb->fs_magic != MTB_UFS_MAGIC)) {
41450Sstevel@tonic-gate cur_cgrp = 0;
41460Sstevel@tonic-gate if (!override) {
41470Sstevel@tonic-gate printf("invalid super block ");
41480Sstevel@tonic-gate printf("magic word\n");
41490Sstevel@tonic-gate cur_cgrp--;
41500Sstevel@tonic-gate error++;
41510Sstevel@tonic-gate return;
41520Sstevel@tonic-gate }
41530Sstevel@tonic-gate }
4154757Svsakar if (sb->fs_magic == FS_MAGIC &&
4155757Svsakar (sb->fs_version !=
4156757Svsakar UFS_EFISTYLE4NONEFI_VERSION_2 &&
4157757Svsakar sb->fs_version != UFS_VERSION_MIN)) {
4158757Svsakar cur_cgrp = 0;
4159757Svsakar if (!override) {
4160757Svsakar printf("invalid super block ");
4161757Svsakar printf("version number\n");
4162757Svsakar cur_cgrp--;
4163757Svsakar error++;
4164757Svsakar return;
4165757Svsakar }
4166757Svsakar }
41670Sstevel@tonic-gate if (sb->fs_magic == MTB_UFS_MAGIC &&
41680Sstevel@tonic-gate (sb->fs_version > MTB_UFS_VERSION_1 ||
41690Sstevel@tonic-gate sb->fs_version < MTB_UFS_VERSION_MIN)) {
41700Sstevel@tonic-gate cur_cgrp = 0;
41710Sstevel@tonic-gate if (!override) {
41720Sstevel@tonic-gate printf("invalid super block ");
4173757Svsakar printf("version number\n");
41740Sstevel@tonic-gate cur_cgrp--;
41750Sstevel@tonic-gate error++;
41760Sstevel@tonic-gate return;
41770Sstevel@tonic-gate }
41780Sstevel@tonic-gate }
41790Sstevel@tonic-gate if (cur_cgrp == 0)
41800Sstevel@tonic-gate printf("\tsuper block:\n");
41810Sstevel@tonic-gate else {
41820Sstevel@tonic-gate printf("\tsuper block in cylinder ");
41830Sstevel@tonic-gate printf("group ");
41840Sstevel@tonic-gate print(cur_cgrp - 1, 0, 0, 0);
41850Sstevel@tonic-gate printf(":\n");
41860Sstevel@tonic-gate }
41870Sstevel@tonic-gate printsb(sb);
41880Sstevel@tonic-gate if (tcount)
41890Sstevel@tonic-gate printf("\n");
41900Sstevel@tonic-gate }
41910Sstevel@tonic-gate cur_cgrp--;
41920Sstevel@tonic-gate if (end) {
41930Sstevel@tonic-gate printf("end of super blocks\n");
41940Sstevel@tonic-gate error++;
41950Sstevel@tonic-gate }
41960Sstevel@tonic-gate return;
41970Sstevel@tonic-gate
41980Sstevel@tonic-gate case 'S': /* print as shadow data */
41990Sstevel@tonic-gate if (type == NUMB) {
42000Sstevel@tonic-gate type = FRAGMENT;
42010Sstevel@tonic-gate cur_shad = 0;
42020Sstevel@tonic-gate cur_bytes = fragoff(fs, addr);
42030Sstevel@tonic-gate bod_addr = addr - cur_bytes;
42040Sstevel@tonic-gate /* no more than two fragments */
42050Sstevel@tonic-gate filesize = fragroundup(fs,
42060Sstevel@tonic-gate bod_addr + FRGSIZE + 1);
42070Sstevel@tonic-gate }
42080Sstevel@tonic-gate objsz = SHADOW_DATA;
42090Sstevel@tonic-gate while (tcount-- &&
42100Sstevel@tonic-gate (cur_bytes + SHADOW_DATA) <= filesize &&
42110Sstevel@tonic-gate (type != SHADOW_DATA ||
42120Sstevel@tonic-gate (cur_bytes + SHADOW_DATA)) <= blocksize) {
42130Sstevel@tonic-gate /*LINTED*/
42140Sstevel@tonic-gate struct ufs_fsd fsd;
42150Sstevel@tonic-gate long tcur_bytes;
42160Sstevel@tonic-gate
42170Sstevel@tonic-gate taddr = addr;
42180Sstevel@tonic-gate tcur_bytes = cur_bytes;
42190Sstevel@tonic-gate index(base);
42200Sstevel@tonic-gate getshadowdata((long *)&fsd, LONG + LONG);
42210Sstevel@tonic-gate printf(" type: ");
42220Sstevel@tonic-gate print((long)fsd.fsd_type, 8, -8, 0);
42230Sstevel@tonic-gate printf(" size: ");
42240Sstevel@tonic-gate print((long)fsd.fsd_size, 8, -8, 0);
42250Sstevel@tonic-gate tbase = fsd.fsd_size - LONG - LONG;
42260Sstevel@tonic-gate if (tbase > 256)
42270Sstevel@tonic-gate tbase = 256;
42280Sstevel@tonic-gate for (i = 0; i < tbase; i++) {
42290Sstevel@tonic-gate if (i % LONG == 0) {
42300Sstevel@tonic-gate if (i % 16 == 0) {
42310Sstevel@tonic-gate printf("\n");
42320Sstevel@tonic-gate index(base);
42330Sstevel@tonic-gate } else
42340Sstevel@tonic-gate printf(" ");
42350Sstevel@tonic-gate getshadowdata(&temp, LONG);
42360Sstevel@tonic-gate p = (char *)&temp;
42370Sstevel@tonic-gate } else
42380Sstevel@tonic-gate printf(" ");
42390Sstevel@tonic-gate printf("%02x", (int)(*p++ & 0377L));
42400Sstevel@tonic-gate }
42410Sstevel@tonic-gate printf("\n");
42420Sstevel@tonic-gate addr = taddr;
42430Sstevel@tonic-gate cur_bytes = tcur_bytes;
42440Sstevel@tonic-gate erraddr = addr;
42450Sstevel@tonic-gate errcur_bytes = cur_bytes;
42460Sstevel@tonic-gate addr += FSD_RECSZ((&fsd), fsd.fsd_size);
42470Sstevel@tonic-gate cur_bytes += FSD_RECSZ((&fsd), fsd.fsd_size);
42480Sstevel@tonic-gate cur_shad++;
42490Sstevel@tonic-gate syncshadowscan(0);
42500Sstevel@tonic-gate }
42510Sstevel@tonic-gate addr = erraddr;
42520Sstevel@tonic-gate cur_bytes = errcur_bytes;
42530Sstevel@tonic-gate cur_shad--;
42540Sstevel@tonic-gate if (tcount >= 0 && !star) {
42550Sstevel@tonic-gate switch (type) {
42560Sstevel@tonic-gate case FRAGMENT:
42570Sstevel@tonic-gate printf("end of fragment\n");
42580Sstevel@tonic-gate break;
42590Sstevel@tonic-gate default:
42600Sstevel@tonic-gate printf("end of shadow data\n");
42610Sstevel@tonic-gate }
42620Sstevel@tonic-gate error++;
42630Sstevel@tonic-gate } else
42640Sstevel@tonic-gate error = 0;
42650Sstevel@tonic-gate return;
42660Sstevel@tonic-gate default:
42670Sstevel@tonic-gate error++;
42680Sstevel@tonic-gate printf("no such print option\n");
42690Sstevel@tonic-gate return;
42700Sstevel@tonic-gate }
42710Sstevel@tonic-gate }
42720Sstevel@tonic-gate
42730Sstevel@tonic-gate /*
42740Sstevel@tonic-gate * valid_addr - call check_addr to validate the current address.
42750Sstevel@tonic-gate */
42760Sstevel@tonic-gate static int
valid_addr()42770Sstevel@tonic-gate valid_addr()
42780Sstevel@tonic-gate {
42790Sstevel@tonic-gate short end = 0, eof = 0;
42800Sstevel@tonic-gate long tcount = count;
42810Sstevel@tonic-gate
42820Sstevel@tonic-gate if (!trapped)
42830Sstevel@tonic-gate return (1);
42840Sstevel@tonic-gate if (cur_bytes < 0) {
42850Sstevel@tonic-gate cur_bytes = 0;
42860Sstevel@tonic-gate if (blocksize > filesize) {
42870Sstevel@tonic-gate printf("beginning of file\n");
42880Sstevel@tonic-gate } else {
42890Sstevel@tonic-gate if (type == BLOCK)
42900Sstevel@tonic-gate printf("beginning of block\n");
42910Sstevel@tonic-gate else
42920Sstevel@tonic-gate printf("beginning of fragment\n");
42930Sstevel@tonic-gate }
42940Sstevel@tonic-gate error++;
42950Sstevel@tonic-gate return (0);
42960Sstevel@tonic-gate }
42970Sstevel@tonic-gate count = 1;
42980Sstevel@tonic-gate (void) check_addr(1, &end, &eof, (filesize < blocksize));
42990Sstevel@tonic-gate count = tcount;
43000Sstevel@tonic-gate if (eof) {
43010Sstevel@tonic-gate printf("end of file\n");
43020Sstevel@tonic-gate error++;
43030Sstevel@tonic-gate return (0);
43040Sstevel@tonic-gate }
43050Sstevel@tonic-gate if (end == 2) {
43060Sstevel@tonic-gate if (erraddr > addr) {
43070Sstevel@tonic-gate if (type == BLOCK)
43080Sstevel@tonic-gate printf("beginning of block\n");
43090Sstevel@tonic-gate else
43100Sstevel@tonic-gate printf("beginning of fragment\n");
43110Sstevel@tonic-gate error++;
43120Sstevel@tonic-gate return (0);
43130Sstevel@tonic-gate }
43140Sstevel@tonic-gate }
43150Sstevel@tonic-gate if (end) {
43160Sstevel@tonic-gate if (type == BLOCK)
43170Sstevel@tonic-gate printf("end of block\n");
43180Sstevel@tonic-gate else
43190Sstevel@tonic-gate printf("end of fragment\n");
43200Sstevel@tonic-gate error++;
43210Sstevel@tonic-gate return (0);
43220Sstevel@tonic-gate }
43230Sstevel@tonic-gate return (1);
43240Sstevel@tonic-gate }
43250Sstevel@tonic-gate
43260Sstevel@tonic-gate /*
43270Sstevel@tonic-gate * check_addr - check if the address crosses the end of block or
43280Sstevel@tonic-gate * end of file. Return the proper count.
43290Sstevel@tonic-gate */
43300Sstevel@tonic-gate static int
check_addr(short eof_flag,short * end,short * eof,short keep_on)43311051Smaheshvs check_addr(short eof_flag, short *end, short *eof, short keep_on)
43320Sstevel@tonic-gate {
43330Sstevel@tonic-gate long temp, tcount = count, tcur_bytes = cur_bytes;
43340Sstevel@tonic-gate u_offset_t taddr = addr;
43350Sstevel@tonic-gate
43360Sstevel@tonic-gate if (bcomp(addr + count * objsz - 1) ||
43370Sstevel@tonic-gate (keep_on && taddr < (bmap(cur_block) << FRGSHIFT))) {
43380Sstevel@tonic-gate error = 0;
43390Sstevel@tonic-gate addr = taddr;
43400Sstevel@tonic-gate cur_bytes = tcur_bytes;
43410Sstevel@tonic-gate if (keep_on) {
43420Sstevel@tonic-gate if (addr < erraddr) {
43430Sstevel@tonic-gate if (cur_bytes < 0) {
43440Sstevel@tonic-gate (*end) = 2;
43450Sstevel@tonic-gate return (0); /* Value ignored */
43460Sstevel@tonic-gate }
43470Sstevel@tonic-gate temp = cur_block - lblkno(fs, cur_bytes);
43480Sstevel@tonic-gate cur_block -= temp;
43490Sstevel@tonic-gate if ((addr = bmap(cur_block) << FRGSHIFT) == 0) {
43500Sstevel@tonic-gate cur_block += temp;
43510Sstevel@tonic-gate return (0); /* Value ignored */
43520Sstevel@tonic-gate }
43530Sstevel@tonic-gate temp = tcur_bytes - cur_bytes;
43540Sstevel@tonic-gate addr += temp;
43550Sstevel@tonic-gate cur_bytes += temp;
43560Sstevel@tonic-gate return (0); /* Value ignored */
43570Sstevel@tonic-gate } else {
43580Sstevel@tonic-gate if (cur_bytes >= filesize) {
43590Sstevel@tonic-gate (*eof)++;
43600Sstevel@tonic-gate return (0); /* Value ignored */
43610Sstevel@tonic-gate }
43620Sstevel@tonic-gate temp = lblkno(fs, cur_bytes) - cur_block;
43630Sstevel@tonic-gate cur_block += temp;
43640Sstevel@tonic-gate if ((addr = bmap(cur_block) << FRGSHIFT) == 0) {
43650Sstevel@tonic-gate cur_block -= temp;
43660Sstevel@tonic-gate return (0); /* Value ignored */
43670Sstevel@tonic-gate }
43680Sstevel@tonic-gate temp = tcur_bytes - cur_bytes;
43690Sstevel@tonic-gate addr += temp;
43700Sstevel@tonic-gate cur_bytes += temp;
43710Sstevel@tonic-gate return (0); /* Value ignored */
43720Sstevel@tonic-gate }
43730Sstevel@tonic-gate }
43740Sstevel@tonic-gate tcount = (blkroundup(fs, addr+1)-addr) / objsz;
43750Sstevel@tonic-gate if (!star)
43760Sstevel@tonic-gate (*end) = 2;
43770Sstevel@tonic-gate }
43780Sstevel@tonic-gate addr = taddr;
43790Sstevel@tonic-gate cur_bytes = tcur_bytes;
43800Sstevel@tonic-gate if (eof_flag) {
43810Sstevel@tonic-gate if (blocksize > filesize) {
43820Sstevel@tonic-gate if (cur_bytes >= filesize) {
43830Sstevel@tonic-gate tcount = 0;
43840Sstevel@tonic-gate (*eof)++;
43850Sstevel@tonic-gate } else if (tcount > (filesize - cur_bytes) / objsz) {
43860Sstevel@tonic-gate tcount = (filesize - cur_bytes) / objsz;
43870Sstevel@tonic-gate if (!star || tcount == 0)
43880Sstevel@tonic-gate (*eof)++;
43890Sstevel@tonic-gate }
43900Sstevel@tonic-gate } else {
43910Sstevel@tonic-gate if (cur_bytes >= blocksize) {
43920Sstevel@tonic-gate tcount = 0;
43930Sstevel@tonic-gate (*end)++;
43940Sstevel@tonic-gate } else if (tcount > (blocksize - cur_bytes) / objsz) {
43950Sstevel@tonic-gate tcount = (blocksize - cur_bytes) / objsz;
43960Sstevel@tonic-gate if (!star || tcount == 0)
43970Sstevel@tonic-gate (*end)++;
43980Sstevel@tonic-gate }
43990Sstevel@tonic-gate }
44000Sstevel@tonic-gate }
44010Sstevel@tonic-gate return (tcount);
44020Sstevel@tonic-gate }
44030Sstevel@tonic-gate
44040Sstevel@tonic-gate /*
44050Sstevel@tonic-gate * print_check - check if the index needs to be printed and delete
44060Sstevel@tonic-gate * rows of zeros from the output.
44070Sstevel@tonic-gate */
44080Sstevel@tonic-gate unsigned long *
print_check(unsigned long * lptr,long * tcount,short tbase,int i)44091051Smaheshvs print_check(unsigned long *lptr, long *tcount, short tbase, int i)
44100Sstevel@tonic-gate {
44111051Smaheshvs int j, k, temp = BYTESPERLINE / objsz;
44120Sstevel@tonic-gate short first_time = 0;
44130Sstevel@tonic-gate unsigned long *tlptr;
44140Sstevel@tonic-gate unsigned short *tsptr, *sptr;
44150Sstevel@tonic-gate
44160Sstevel@tonic-gate sptr = (unsigned short *)lptr;
44170Sstevel@tonic-gate if (i == 0)
44180Sstevel@tonic-gate first_time = 1;
44190Sstevel@tonic-gate if (i % temp == 0) {
44200Sstevel@tonic-gate if (*tcount >= temp - 1) {
44210Sstevel@tonic-gate if (objsz == SHORT)
44220Sstevel@tonic-gate tsptr = sptr;
44230Sstevel@tonic-gate else
44240Sstevel@tonic-gate tlptr = lptr;
44250Sstevel@tonic-gate k = *tcount - 1;
44260Sstevel@tonic-gate for (j = i; k--; j++)
44270Sstevel@tonic-gate if (objsz == SHORT) {
44280Sstevel@tonic-gate if (*tsptr++ != 0)
44290Sstevel@tonic-gate break;
44300Sstevel@tonic-gate } else {
44310Sstevel@tonic-gate if (*tlptr++ != 0)
44320Sstevel@tonic-gate break;
44330Sstevel@tonic-gate }
44340Sstevel@tonic-gate if (j > (i + temp - 1)) {
44350Sstevel@tonic-gate j = (j - i) / temp;
44360Sstevel@tonic-gate while (j-- > 0) {
44370Sstevel@tonic-gate if (objsz == SHORT)
44380Sstevel@tonic-gate sptr += temp;
44390Sstevel@tonic-gate else
44400Sstevel@tonic-gate lptr += temp;
44410Sstevel@tonic-gate *tcount -= temp;
44420Sstevel@tonic-gate i += temp;
44430Sstevel@tonic-gate addr += BYTESPERLINE;
44440Sstevel@tonic-gate cur_bytes += BYTESPERLINE;
44450Sstevel@tonic-gate }
44460Sstevel@tonic-gate if (first_time)
44470Sstevel@tonic-gate printf("*");
44480Sstevel@tonic-gate else
44490Sstevel@tonic-gate printf("\n*");
44500Sstevel@tonic-gate }
44510Sstevel@tonic-gate if (i)
44520Sstevel@tonic-gate printf("\n");
44530Sstevel@tonic-gate index(tbase);
44540Sstevel@tonic-gate } else {
44550Sstevel@tonic-gate if (i)
44560Sstevel@tonic-gate printf("\n");
44570Sstevel@tonic-gate index(tbase);
44580Sstevel@tonic-gate }
44590Sstevel@tonic-gate }
44600Sstevel@tonic-gate if (objsz == SHORT)
44610Sstevel@tonic-gate /*LINTED*/
44620Sstevel@tonic-gate return ((unsigned long *)sptr);
44630Sstevel@tonic-gate else
44640Sstevel@tonic-gate return (lptr);
44650Sstevel@tonic-gate }
44660Sstevel@tonic-gate
44670Sstevel@tonic-gate /*
44680Sstevel@tonic-gate * index - print a byte index for the printout in base b
44690Sstevel@tonic-gate * with leading zeros.
44700Sstevel@tonic-gate */
44710Sstevel@tonic-gate static void
index(int b)44721051Smaheshvs index(int b)
44730Sstevel@tonic-gate {
44740Sstevel@tonic-gate int tbase = base;
44750Sstevel@tonic-gate
44760Sstevel@tonic-gate base = b;
44770Sstevel@tonic-gate print(addr, 8, 8, 1);
44780Sstevel@tonic-gate printf(":\t");
44790Sstevel@tonic-gate base = tbase;
44800Sstevel@tonic-gate }
44810Sstevel@tonic-gate
44820Sstevel@tonic-gate /*
44830Sstevel@tonic-gate * print - print out the value to digits places with/without
44840Sstevel@tonic-gate * leading zeros and right/left justified in the current base.
44850Sstevel@tonic-gate */
44860Sstevel@tonic-gate static void
44870Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
printll(u_offset_t value,int fieldsz,int digits,int lead)44880Sstevel@tonic-gate printll(u_offset_t value, int fieldsz, int digits, int lead)
44890Sstevel@tonic-gate #else /* !_LARGEFILE64_SOURCE */
44900Sstevel@tonic-gate print(long value, int fieldsz, int digits, int lead)
44910Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
44920Sstevel@tonic-gate {
44931051Smaheshvs int i, left = 0;
44941051Smaheshvs char mode = BASE[base - OCTAL];
44951051Smaheshvs char *string = &scratch[0];
44960Sstevel@tonic-gate
44970Sstevel@tonic-gate if (digits < 0) {
44980Sstevel@tonic-gate left = 1;
44990Sstevel@tonic-gate digits *= -1;
45000Sstevel@tonic-gate }
45010Sstevel@tonic-gate if (base != HEX)
45020Sstevel@tonic-gate if (digits)
45030Sstevel@tonic-gate digits = digits + (digits - 1)/((base >> 1) - 1) + 1;
45040Sstevel@tonic-gate else
45050Sstevel@tonic-gate digits = 1;
45060Sstevel@tonic-gate if (lead) {
45070Sstevel@tonic-gate if (left)
45080Sstevel@tonic-gate (void) sprintf(string, "%%%c%d%d.%d"
45090Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45100Sstevel@tonic-gate "ll"
45110Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45120Sstevel@tonic-gate "%c", '-', 0, digits, lead, mode);
45130Sstevel@tonic-gate else
45140Sstevel@tonic-gate (void) sprintf(string, "%%%d%d.%d"
45150Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45160Sstevel@tonic-gate "ll"
45170Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45180Sstevel@tonic-gate "%c", 0, digits, lead, mode);
45190Sstevel@tonic-gate } else {
45200Sstevel@tonic-gate if (left)
45210Sstevel@tonic-gate (void) sprintf(string, "%%%c%d"
45220Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45230Sstevel@tonic-gate "ll"
45240Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45250Sstevel@tonic-gate "%c", '-', digits, mode);
45260Sstevel@tonic-gate else
45270Sstevel@tonic-gate (void) sprintf(string, "%%%d"
45280Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45290Sstevel@tonic-gate "ll"
45300Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45310Sstevel@tonic-gate "%c", digits, mode);
45320Sstevel@tonic-gate }
45330Sstevel@tonic-gate printf(string, value);
45340Sstevel@tonic-gate for (i = 0; i < fieldsz - digits; i++)
45350Sstevel@tonic-gate printf(" ");
45360Sstevel@tonic-gate }
45370Sstevel@tonic-gate
45380Sstevel@tonic-gate /*
45390Sstevel@tonic-gate * Print out the contents of a superblock.
45400Sstevel@tonic-gate */
45410Sstevel@tonic-gate static void
printsb(struct fs * fs)45421051Smaheshvs printsb(struct fs *fs)
45430Sstevel@tonic-gate {
45440Sstevel@tonic-gate int c, i, j, k, size;
45450Sstevel@tonic-gate caddr_t sip;
45460Sstevel@tonic-gate time_t t;
45470Sstevel@tonic-gate
45480Sstevel@tonic-gate t = fs->fs_time;
45490Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
45500Sstevel@tonic-gate if (fs->fs_postblformat == FS_42POSTBLFMT)
45510Sstevel@tonic-gate fs->fs_nrpos = 8;
45520Sstevel@tonic-gate printf("magic\t%lx\tformat\t%s\ttime\t%s", fs->fs_magic,
45530Sstevel@tonic-gate fs->fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
45540Sstevel@tonic-gate ctime(&t));
45550Sstevel@tonic-gate #else
45560Sstevel@tonic-gate printf("magic\t%x\ttime\t%s",
45570Sstevel@tonic-gate fs->fs_magic, ctime(&t));
45580Sstevel@tonic-gate #endif
4559757Svsakar printf("version\t%x\n", fs->fs_version);
45600Sstevel@tonic-gate printf("nbfree\t%ld\tndir\t%ld\tnifree\t%ld\tnffree\t%ld\n",
45610Sstevel@tonic-gate fs->fs_cstotal.cs_nbfree, fs->fs_cstotal.cs_ndir,
45620Sstevel@tonic-gate fs->fs_cstotal.cs_nifree, fs->fs_cstotal.cs_nffree);
45630Sstevel@tonic-gate printf("ncg\t%ld\tncyl\t%ld\tsize\t%ld\tblocks\t%ld\n",
45640Sstevel@tonic-gate fs->fs_ncg, fs->fs_ncyl, fs->fs_size, fs->fs_dsize);
45650Sstevel@tonic-gate printf("bsize\t%ld\tshift\t%ld\tmask\t0x%08lx\n",
45660Sstevel@tonic-gate fs->fs_bsize, fs->fs_bshift, fs->fs_bmask);
45670Sstevel@tonic-gate printf("fsize\t%ld\tshift\t%ld\tmask\t0x%08lx\n",
45680Sstevel@tonic-gate fs->fs_fsize, fs->fs_fshift, fs->fs_fmask);
45690Sstevel@tonic-gate printf("frag\t%ld\tshift\t%ld\tfsbtodb\t%ld\n",
45700Sstevel@tonic-gate fs->fs_frag, fs->fs_fragshift, fs->fs_fsbtodb);
45710Sstevel@tonic-gate printf("cpg\t%ld\tbpg\t%ld\tfpg\t%ld\tipg\t%ld\n",
45720Sstevel@tonic-gate fs->fs_cpg, fs->fs_fpg / fs->fs_frag, fs->fs_fpg, fs->fs_ipg);
45730Sstevel@tonic-gate printf("minfree\t%ld%%\toptim\t%s\tmaxcontig %ld\tmaxbpg\t%ld\n",
45740Sstevel@tonic-gate fs->fs_minfree, fs->fs_optim == FS_OPTSPACE ? "space" : "time",
45750Sstevel@tonic-gate fs->fs_maxcontig, fs->fs_maxbpg);
45760Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
45770Sstevel@tonic-gate #ifdef sun
45780Sstevel@tonic-gate printf("rotdelay %ldms\tfs_id[0] 0x%lx\tfs_id[1] 0x%lx\trps\t%ld\n",
45790Sstevel@tonic-gate fs->fs_rotdelay, fs->fs_id[0], fs->fs_id[1], fs->fs_rps);
45800Sstevel@tonic-gate #else
45810Sstevel@tonic-gate printf("rotdelay %dms\theadswitch %dus\ttrackseek %dus\trps\t%d\n",
45820Sstevel@tonic-gate fs->fs_rotdelay, fs->fs_headswitch, fs->fs_trkseek, fs->fs_rps);
45830Sstevel@tonic-gate #endif /* sun */
45840Sstevel@tonic-gate printf("ntrak\t%ld\tnsect\t%ld\tnpsect\t%ld\tspc\t%ld\n",
45850Sstevel@tonic-gate fs->fs_ntrak, fs->fs_nsect, fs->fs_npsect, fs->fs_spc);
45860Sstevel@tonic-gate printf("trackskew %ld\n", fs->fs_trackskew);
45870Sstevel@tonic-gate #else
45880Sstevel@tonic-gate printf("rotdelay %ldms\trps\t%ld\n",
45890Sstevel@tonic-gate fs->fs_rotdelay, fs->fs_rps);
45900Sstevel@tonic-gate printf("ntrak\t%ld\tnsect\t%ld\tspc\t%ld\n",
45910Sstevel@tonic-gate fs->fs_ntrak, fs->fs_nsect, fs->fs_spc);
45920Sstevel@tonic-gate #endif
45930Sstevel@tonic-gate printf("si %ld\n", fs->fs_si);
45940Sstevel@tonic-gate printf("nindir\t%ld\tinopb\t%ld\tnspf\t%ld\n",
45950Sstevel@tonic-gate fs->fs_nindir, fs->fs_inopb, fs->fs_nspf);
45960Sstevel@tonic-gate printf("sblkno\t%ld\tcblkno\t%ld\tiblkno\t%ld\tdblkno\t%ld\n",
45970Sstevel@tonic-gate fs->fs_sblkno, fs->fs_cblkno, fs->fs_iblkno, fs->fs_dblkno);
45980Sstevel@tonic-gate printf("sbsize\t%ld\tcgsize\t%ld\tcgoffset %ld\tcgmask\t0x%08lx\n",
45990Sstevel@tonic-gate fs->fs_sbsize, fs->fs_cgsize, fs->fs_cgoffset, fs->fs_cgmask);
46000Sstevel@tonic-gate printf("csaddr\t%ld\tcssize\t%ld\tshift\t%ld\tmask\t0x%08lx\n",
46010Sstevel@tonic-gate fs->fs_csaddr, fs->fs_cssize, fs->fs_csshift, fs->fs_csmask);
46020Sstevel@tonic-gate printf("cgrotor\t%ld\tfmod\t%d\tronly\t%d\n",
46030Sstevel@tonic-gate fs->fs_cgrotor, fs->fs_fmod, fs->fs_ronly);
46040Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
46050Sstevel@tonic-gate if (fs->fs_cpc != 0)
46060Sstevel@tonic-gate printf("blocks available in each of %ld rotational positions",
46070Sstevel@tonic-gate fs->fs_nrpos);
46080Sstevel@tonic-gate else
46090Sstevel@tonic-gate printf("insufficient space to maintain rotational tables\n");
46100Sstevel@tonic-gate #endif
46110Sstevel@tonic-gate for (c = 0; c < fs->fs_cpc; c++) {
46120Sstevel@tonic-gate printf("\ncylinder number %d:", c);
46130Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
46140Sstevel@tonic-gate for (i = 0; i < fs->fs_nrpos; i++) {
46150Sstevel@tonic-gate /*LINTED*/
46160Sstevel@tonic-gate if (fs_postbl(fs, c)[i] == -1)
46170Sstevel@tonic-gate continue;
46180Sstevel@tonic-gate printf("\n position %d:\t", i);
46190Sstevel@tonic-gate /*LINTED*/
46200Sstevel@tonic-gate for (j = fs_postbl(fs, c)[i], k = 1; /* void */;
46210Sstevel@tonic-gate j += fs_rotbl(fs)[j], k++) {
46220Sstevel@tonic-gate printf("%5d", j);
46230Sstevel@tonic-gate if (k % 12 == 0)
46240Sstevel@tonic-gate printf("\n\t\t");
46250Sstevel@tonic-gate if (fs_rotbl(fs)[j] == 0)
46260Sstevel@tonic-gate break;
46270Sstevel@tonic-gate }
46280Sstevel@tonic-gate }
46290Sstevel@tonic-gate #else
46300Sstevel@tonic-gate for (i = 0; i < NRPOS; i++) {
46310Sstevel@tonic-gate if (fs->fs_postbl[c][i] == -1)
46320Sstevel@tonic-gate continue;
46330Sstevel@tonic-gate printf("\n position %d:\t", i);
46340Sstevel@tonic-gate for (j = fs->fs_postbl[c][i], k = 1; /* void */;
46350Sstevel@tonic-gate j += fs->fs_rotbl[j], k++) {
46360Sstevel@tonic-gate printf("%5d", j);
46370Sstevel@tonic-gate if (k % 12 == 0)
46380Sstevel@tonic-gate printf("\n\t\t");
46390Sstevel@tonic-gate if (fs->fs_rotbl[j] == 0)
46400Sstevel@tonic-gate break;
46410Sstevel@tonic-gate }
46420Sstevel@tonic-gate }
46430Sstevel@tonic-gate #endif
46440Sstevel@tonic-gate }
46450Sstevel@tonic-gate printf("\ncs[].cs_(nbfree, ndir, nifree, nffree):");
46460Sstevel@tonic-gate sip = calloc(1, fs->fs_cssize);
46470Sstevel@tonic-gate fs->fs_u.fs_csp = (struct csum *)sip;
46480Sstevel@tonic-gate for (i = 0, j = 0; i < fs->fs_cssize; i += fs->fs_bsize, j++) {
46490Sstevel@tonic-gate size = fs->fs_cssize - i < fs->fs_bsize ?
46500Sstevel@tonic-gate fs->fs_cssize - i : fs->fs_bsize;
46510Sstevel@tonic-gate (void) llseek(fd,
46520Sstevel@tonic-gate (offset_t)fsbtodb(fs, (fs->fs_csaddr + j * fs->fs_frag))
46530Sstevel@tonic-gate * fs->fs_fsize / fsbtodb(fs, 1), 0);
46540Sstevel@tonic-gate if (read(fd, sip, size) != size) {
46550Sstevel@tonic-gate free(fs->fs_u.fs_csp);
46560Sstevel@tonic-gate return;
46570Sstevel@tonic-gate }
46580Sstevel@tonic-gate sip += size;
46590Sstevel@tonic-gate }
46600Sstevel@tonic-gate for (i = 0; i < fs->fs_ncg; i++) {
46610Sstevel@tonic-gate struct csum *cs = &fs->fs_cs(fs, i);
46620Sstevel@tonic-gate if (i % 4 == 0)
46630Sstevel@tonic-gate printf("\n ");
46640Sstevel@tonic-gate printf("%d:(%ld,%ld,%ld,%ld) ", i, cs->cs_nbfree, cs->cs_ndir,
46650Sstevel@tonic-gate cs->cs_nifree, cs->cs_nffree);
46660Sstevel@tonic-gate }
46670Sstevel@tonic-gate free(fs->fs_u.fs_csp);
46680Sstevel@tonic-gate printf("\n");
46690Sstevel@tonic-gate if (fs->fs_ncyl % fs->fs_cpg) {
46700Sstevel@tonic-gate printf("cylinders in last group %d\n",
46710Sstevel@tonic-gate i = fs->fs_ncyl % fs->fs_cpg);
46720Sstevel@tonic-gate printf("blocks in last group %ld\n",
46730Sstevel@tonic-gate i * fs->fs_spc / NSPB(fs));
46740Sstevel@tonic-gate }
46750Sstevel@tonic-gate }
46760Sstevel@tonic-gate
46770Sstevel@tonic-gate /*
46780Sstevel@tonic-gate * Print out the contents of a cylinder group.
46790Sstevel@tonic-gate */
46800Sstevel@tonic-gate static void
printcg(struct cg * cg)46811051Smaheshvs printcg(struct cg *cg)
46820Sstevel@tonic-gate {
46830Sstevel@tonic-gate int i, j;
46840Sstevel@tonic-gate time_t t;
46850Sstevel@tonic-gate
46860Sstevel@tonic-gate printf("\ncg %ld:\n", cg->cg_cgx);
46870Sstevel@tonic-gate t = cg->cg_time;
46880Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
46890Sstevel@tonic-gate printf("magic\t%lx\ttell\t%llx\ttime\t%s",
46900Sstevel@tonic-gate fs->fs_postblformat == FS_42POSTBLFMT ?
46910Sstevel@tonic-gate ((struct ocg *)cg)->cg_magic : cg->cg_magic,
46920Sstevel@tonic-gate fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1),
46930Sstevel@tonic-gate ctime(&t));
46940Sstevel@tonic-gate #else
46950Sstevel@tonic-gate printf("magic\t%x\ttell\t%llx\ttime\t%s",
46960Sstevel@tonic-gate cg->cg_magic,
46970Sstevel@tonic-gate fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1),
46980Sstevel@tonic-gate ctime(&t));
46990Sstevel@tonic-gate #endif
47000Sstevel@tonic-gate printf("cgx\t%ld\tncyl\t%d\tniblk\t%d\tndblk\t%ld\n",
47010Sstevel@tonic-gate cg->cg_cgx, cg->cg_ncyl, cg->cg_niblk, cg->cg_ndblk);
47020Sstevel@tonic-gate printf("nbfree\t%ld\tndir\t%ld\tnifree\t%ld\tnffree\t%ld\n",
47030Sstevel@tonic-gate cg->cg_cs.cs_nbfree, cg->cg_cs.cs_ndir,
47040Sstevel@tonic-gate cg->cg_cs.cs_nifree, cg->cg_cs.cs_nffree);
47050Sstevel@tonic-gate printf("rotor\t%ld\tirotor\t%ld\tfrotor\t%ld\nfrsum",
47060Sstevel@tonic-gate cg->cg_rotor, cg->cg_irotor, cg->cg_frotor);
47070Sstevel@tonic-gate for (i = 1, j = 0; i < fs->fs_frag; i++) {
47080Sstevel@tonic-gate printf("\t%ld", cg->cg_frsum[i]);
47090Sstevel@tonic-gate j += i * cg->cg_frsum[i];
47100Sstevel@tonic-gate }
47110Sstevel@tonic-gate printf("\nsum of frsum: %d\niused:\t", j);
47120Sstevel@tonic-gate pbits((unsigned char *)cg_inosused(cg), fs->fs_ipg);
47130Sstevel@tonic-gate printf("free:\t");
47140Sstevel@tonic-gate pbits(cg_blksfree(cg), fs->fs_fpg);
47150Sstevel@tonic-gate printf("b:\n");
47160Sstevel@tonic-gate for (i = 0; i < fs->fs_cpg; i++) {
47170Sstevel@tonic-gate /*LINTED*/
47180Sstevel@tonic-gate if (cg_blktot(cg)[i] == 0)
47190Sstevel@tonic-gate continue;
47200Sstevel@tonic-gate /*LINTED*/
47210Sstevel@tonic-gate printf(" c%d:\t(%ld)\t", i, cg_blktot(cg)[i]);
47220Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
47230Sstevel@tonic-gate for (j = 0; j < fs->fs_nrpos; j++) {
47240Sstevel@tonic-gate if (fs->fs_cpc == 0 ||
47250Sstevel@tonic-gate /*LINTED*/
47260Sstevel@tonic-gate fs_postbl(fs, i % fs->fs_cpc)[j] == -1)
47270Sstevel@tonic-gate continue;
47280Sstevel@tonic-gate /*LINTED*/
47290Sstevel@tonic-gate printf(" %d", cg_blks(fs, cg, i)[j]);
47300Sstevel@tonic-gate }
47310Sstevel@tonic-gate #else
47320Sstevel@tonic-gate for (j = 0; j < NRPOS; j++) {
47330Sstevel@tonic-gate if (fs->fs_cpc == 0 ||
47340Sstevel@tonic-gate fs->fs_postbl[i % fs->fs_cpc][j] == -1)
47350Sstevel@tonic-gate continue;
47360Sstevel@tonic-gate printf(" %d", cg->cg_b[i][j]);
47370Sstevel@tonic-gate }
47380Sstevel@tonic-gate #endif
47390Sstevel@tonic-gate printf("\n");
47400Sstevel@tonic-gate }
47410Sstevel@tonic-gate }
47420Sstevel@tonic-gate
47430Sstevel@tonic-gate /*
47440Sstevel@tonic-gate * Print out the contents of a bit array.
47450Sstevel@tonic-gate */
47460Sstevel@tonic-gate static void
pbits(unsigned char * cp,int max)47471051Smaheshvs pbits(unsigned char *cp, int max)
47480Sstevel@tonic-gate {
47491051Smaheshvs int i;
47500Sstevel@tonic-gate int count = 0, j;
47510Sstevel@tonic-gate
47520Sstevel@tonic-gate for (i = 0; i < max; i++)
47530Sstevel@tonic-gate if (isset(cp, i)) {
47540Sstevel@tonic-gate if (count)
47550Sstevel@tonic-gate printf(",%s", count % 6 ? " " : "\n\t");
47560Sstevel@tonic-gate count++;
47570Sstevel@tonic-gate printf("%d", i);
47580Sstevel@tonic-gate j = i;
47590Sstevel@tonic-gate while ((i+1) < max && isset(cp, i+1))
47600Sstevel@tonic-gate i++;
47610Sstevel@tonic-gate if (i != j)
47620Sstevel@tonic-gate printf("-%d", i);
47630Sstevel@tonic-gate }
47640Sstevel@tonic-gate printf("\n");
47650Sstevel@tonic-gate }
47660Sstevel@tonic-gate
47670Sstevel@tonic-gate /*
47680Sstevel@tonic-gate * bcomp - used to check for block over/under flows when stepping through
47690Sstevel@tonic-gate * a file system.
47700Sstevel@tonic-gate */
47710Sstevel@tonic-gate static int
bcomp(addr)47720Sstevel@tonic-gate bcomp(addr)
47730Sstevel@tonic-gate u_offset_t addr;
47740Sstevel@tonic-gate {
47750Sstevel@tonic-gate if (override)
47760Sstevel@tonic-gate return (0);
47770Sstevel@tonic-gate
47780Sstevel@tonic-gate if (lblkno(fs, addr) == (bhdr.fwd)->blkno)
47790Sstevel@tonic-gate return (0);
47800Sstevel@tonic-gate error++;
47810Sstevel@tonic-gate return (1);
47820Sstevel@tonic-gate }
47830Sstevel@tonic-gate
47840Sstevel@tonic-gate /*
47850Sstevel@tonic-gate * bmap - maps the logical block number of a file into
47860Sstevel@tonic-gate * the corresponding physical block on the file
47870Sstevel@tonic-gate * system.
47880Sstevel@tonic-gate */
47890Sstevel@tonic-gate static long
bmap(long bn)47901051Smaheshvs bmap(long bn)
47910Sstevel@tonic-gate {
47921051Smaheshvs int j;
47931051Smaheshvs struct dinode *ip;
47941051Smaheshvs int sh;
47951051Smaheshvs long nb;
47961051Smaheshvs char *cptr;
47970Sstevel@tonic-gate
47980Sstevel@tonic-gate if ((cptr = getblk(cur_ino)) == 0)
47990Sstevel@tonic-gate return (0);
48000Sstevel@tonic-gate
48010Sstevel@tonic-gate cptr += blkoff(fs, cur_ino);
48020Sstevel@tonic-gate
48030Sstevel@tonic-gate /*LINTED*/
48040Sstevel@tonic-gate ip = (struct dinode *)cptr;
48050Sstevel@tonic-gate
48060Sstevel@tonic-gate if (bn < NDADDR) {
48070Sstevel@tonic-gate nb = ip->di_db[bn];
48080Sstevel@tonic-gate return (nullblk(nb) ? 0L : nb);
48090Sstevel@tonic-gate }
48100Sstevel@tonic-gate
48110Sstevel@tonic-gate sh = 1;
48120Sstevel@tonic-gate bn -= NDADDR;
48130Sstevel@tonic-gate for (j = NIADDR; j > 0; j--) {
48140Sstevel@tonic-gate sh *= NINDIR(fs);
48150Sstevel@tonic-gate if (bn < sh)
48160Sstevel@tonic-gate break;
48170Sstevel@tonic-gate bn -= sh;
48180Sstevel@tonic-gate }
48190Sstevel@tonic-gate if (j == 0) {
48200Sstevel@tonic-gate printf("file too big\n");
48210Sstevel@tonic-gate error++;
48220Sstevel@tonic-gate return (0L);
48230Sstevel@tonic-gate }
48240Sstevel@tonic-gate addr = (uintptr_t)&ip->di_ib[NIADDR - j];
48250Sstevel@tonic-gate nb = get(LONG);
48260Sstevel@tonic-gate if (nb == 0)
48270Sstevel@tonic-gate return (0L);
48280Sstevel@tonic-gate for (; j <= NIADDR; j++) {
48290Sstevel@tonic-gate sh /= NINDIR(fs);
48300Sstevel@tonic-gate addr = (nb << FRGSHIFT) + ((bn / sh) % NINDIR(fs)) * LONG;
48310Sstevel@tonic-gate if (nullblk(nb = get(LONG)))
48320Sstevel@tonic-gate return (0L);
48330Sstevel@tonic-gate }
48340Sstevel@tonic-gate return (nb);
48350Sstevel@tonic-gate }
48360Sstevel@tonic-gate
48370Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
48380Sstevel@tonic-gate
48390Sstevel@tonic-gate /*
48400Sstevel@tonic-gate * The following are "tacked on" to support the old fsdb functionality
48410Sstevel@tonic-gate * of clearing an inode. (All together now...) "It's better to use clri".
48420Sstevel@tonic-gate */
48430Sstevel@tonic-gate
48440Sstevel@tonic-gate #define ISIZE (sizeof (struct dinode))
48450Sstevel@tonic-gate #define NI (MAXBSIZE/ISIZE)
48460Sstevel@tonic-gate
48470Sstevel@tonic-gate
48480Sstevel@tonic-gate static struct dinode di_buf[NI];
48490Sstevel@tonic-gate
48500Sstevel@tonic-gate static union {
48510Sstevel@tonic-gate char dummy[SBSIZE];
48520Sstevel@tonic-gate struct fs sblk;
48530Sstevel@tonic-gate } sb_un;
48540Sstevel@tonic-gate
48550Sstevel@tonic-gate #define sblock sb_un.sblk
48560Sstevel@tonic-gate
48570Sstevel@tonic-gate static void
old_fsdb(int inum,char * special)48581051Smaheshvs old_fsdb(int inum, char *special)
48590Sstevel@tonic-gate {
48600Sstevel@tonic-gate int f; /* File descriptor for "special" */
48610Sstevel@tonic-gate int j;
48620Sstevel@tonic-gate int status = 0;
48630Sstevel@tonic-gate u_offset_t off;
48640Sstevel@tonic-gate long gen;
48650Sstevel@tonic-gate time_t t;
48660Sstevel@tonic-gate
48670Sstevel@tonic-gate f = open(special, 2);
48680Sstevel@tonic-gate if (f < 0) {
48690Sstevel@tonic-gate perror("open");
48700Sstevel@tonic-gate printf("cannot open %s\n", special);
48710Sstevel@tonic-gate exit(31+4);
48720Sstevel@tonic-gate }
48730Sstevel@tonic-gate (void) llseek(f, (offset_t)SBLOCK * DEV_BSIZE, 0);
48740Sstevel@tonic-gate if (read(f, &sblock, SBSIZE) != SBSIZE) {
48750Sstevel@tonic-gate printf("cannot read %s\n", special);
48760Sstevel@tonic-gate exit(31+4);
48770Sstevel@tonic-gate }
48780Sstevel@tonic-gate if (sblock.fs_magic != FS_MAGIC) {
48790Sstevel@tonic-gate printf("bad super block magic number\n");
48800Sstevel@tonic-gate exit(31+4);
48810Sstevel@tonic-gate }
48820Sstevel@tonic-gate if (inum == 0) {
48830Sstevel@tonic-gate printf("%d: is zero\n", inum);
48840Sstevel@tonic-gate exit(31+1);
48850Sstevel@tonic-gate }
48860Sstevel@tonic-gate off = (u_offset_t)fsbtodb(&sblock, itod(&sblock, inum)) * DEV_BSIZE;
48870Sstevel@tonic-gate (void) llseek(f, off, 0);
48880Sstevel@tonic-gate if (read(f, (char *)di_buf, sblock.fs_bsize) != sblock.fs_bsize) {
48890Sstevel@tonic-gate printf("%s: read error\n", special);
48900Sstevel@tonic-gate status = 1;
48910Sstevel@tonic-gate }
48920Sstevel@tonic-gate if (status)
48930Sstevel@tonic-gate exit(31+status);
48940Sstevel@tonic-gate
48950Sstevel@tonic-gate /*
48960Sstevel@tonic-gate * Update the time in superblock, so fsck will check this filesystem.
48970Sstevel@tonic-gate */
48980Sstevel@tonic-gate (void) llseek(f, (offset_t)(SBLOCK * DEV_BSIZE), 0);
48990Sstevel@tonic-gate (void) time(&t);
49000Sstevel@tonic-gate sblock.fs_time = (time32_t)t;
49010Sstevel@tonic-gate if (write(f, &sblock, SBSIZE) != SBSIZE) {
49020Sstevel@tonic-gate printf("cannot update %s\n", special);
49030Sstevel@tonic-gate exit(35);
49040Sstevel@tonic-gate }
49050Sstevel@tonic-gate
49060Sstevel@tonic-gate printf("clearing %u\n", inum);
49070Sstevel@tonic-gate off = (u_offset_t)fsbtodb(&sblock, itod(&sblock, inum)) * DEV_BSIZE;
49080Sstevel@tonic-gate (void) llseek(f, off, 0);
49090Sstevel@tonic-gate read(f, (char *)di_buf, sblock.fs_bsize);
49100Sstevel@tonic-gate j = itoo(&sblock, inum);
49110Sstevel@tonic-gate gen = di_buf[j].di_gen;
49120Sstevel@tonic-gate (void) memset((caddr_t)&di_buf[j], 0, ISIZE);
49130Sstevel@tonic-gate di_buf[j].di_gen = gen + 1;
49140Sstevel@tonic-gate (void) llseek(f, off, 0);
49150Sstevel@tonic-gate write(f, (char *)di_buf, sblock.fs_bsize);
49160Sstevel@tonic-gate exit(31+status);
49170Sstevel@tonic-gate }
49180Sstevel@tonic-gate
49190Sstevel@tonic-gate static int
isnumber(char * s)49201051Smaheshvs isnumber(char *s)
49210Sstevel@tonic-gate {
49220Sstevel@tonic-gate register int c;
49230Sstevel@tonic-gate
49240Sstevel@tonic-gate if (s == NULL)
49250Sstevel@tonic-gate return (0);
49260Sstevel@tonic-gate while ((c = *s++) != NULL)
49270Sstevel@tonic-gate if (c < '0' || c > '9')
49280Sstevel@tonic-gate return (0);
49290Sstevel@tonic-gate return (1);
49300Sstevel@tonic-gate }
49310Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
49320Sstevel@tonic-gate
49330Sstevel@tonic-gate enum boolean { True, False };
49340Sstevel@tonic-gate extent_block_t *log_eb;
49350Sstevel@tonic-gate ml_odunit_t *log_odi;
49360Sstevel@tonic-gate int lufs_tid; /* last valid TID seen */
49370Sstevel@tonic-gate
49380Sstevel@tonic-gate /*
49390Sstevel@tonic-gate * no single value is safe to use to indicate
49400Sstevel@tonic-gate * lufs_tid being invalid so we need a
49410Sstevel@tonic-gate * seperate variable.
49420Sstevel@tonic-gate */
49430Sstevel@tonic-gate enum boolean lufs_tid_valid;
49440Sstevel@tonic-gate
49450Sstevel@tonic-gate /*
49460Sstevel@tonic-gate * log_get_header_info - get the basic info of the logging filesystem
49470Sstevel@tonic-gate */
49480Sstevel@tonic-gate int
log_get_header_info(void)49490Sstevel@tonic-gate log_get_header_info(void)
49500Sstevel@tonic-gate {
49510Sstevel@tonic-gate char *b;
49520Sstevel@tonic-gate int nb;
49530Sstevel@tonic-gate
49540Sstevel@tonic-gate /*
49550Sstevel@tonic-gate * Mark the global tid as invalid everytime we're called to
49560Sstevel@tonic-gate * prevent any false positive responses.
49570Sstevel@tonic-gate */
49580Sstevel@tonic-gate lufs_tid_valid = False;
49590Sstevel@tonic-gate
49600Sstevel@tonic-gate /*
49610Sstevel@tonic-gate * See if we've already set up the header areas. The only problem
49620Sstevel@tonic-gate * with this approach is we don't reread the on disk data though
49630Sstevel@tonic-gate * it shouldn't matter since we don't operate on a live disk.
49640Sstevel@tonic-gate */
49650Sstevel@tonic-gate if ((log_eb != NULL) && (log_odi != NULL))
49660Sstevel@tonic-gate return (1);
49670Sstevel@tonic-gate
49680Sstevel@tonic-gate /*
49690Sstevel@tonic-gate * Either logging is disabled or we've not running 2.7.
49700Sstevel@tonic-gate */
49710Sstevel@tonic-gate if (fs->fs_logbno == 0) {
49720Sstevel@tonic-gate printf("Logging doesn't appear to be enabled on this disk\n");
49730Sstevel@tonic-gate return (0);
49740Sstevel@tonic-gate }
49750Sstevel@tonic-gate
49760Sstevel@tonic-gate /*
49770Sstevel@tonic-gate * To find the log we need to first pick up the block allocation
49780Sstevel@tonic-gate * data. The block number for that data is fs_logbno in the
49790Sstevel@tonic-gate * super block.
49800Sstevel@tonic-gate */
49810Sstevel@tonic-gate if ((b = getblk((u_offset_t)ldbtob(logbtodb(fs, fs->fs_logbno))))
49820Sstevel@tonic-gate == 0) {
49830Sstevel@tonic-gate printf("getblk() indicates an error with logging block\n");
49840Sstevel@tonic-gate return (0);
49850Sstevel@tonic-gate }
49860Sstevel@tonic-gate
49870Sstevel@tonic-gate /*
49880Sstevel@tonic-gate * Next we need to figure out how big the extent data structure
49890Sstevel@tonic-gate * really is. It can't be more then fs_bsize and you could just
49900Sstevel@tonic-gate * allocate that but, why get sloppy.
49910Sstevel@tonic-gate * 1 is subtracted from nextents because extent_block_t contains
49920Sstevel@tonic-gate * a single extent_t itself.
49930Sstevel@tonic-gate */
49940Sstevel@tonic-gate log_eb = (extent_block_t *)b;
49950Sstevel@tonic-gate if (log_eb->type != LUFS_EXTENTS) {
49960Sstevel@tonic-gate printf("Extents block has invalid type (0x%x)\n",
49970Sstevel@tonic-gate log_eb->type);
49980Sstevel@tonic-gate return (0);
49990Sstevel@tonic-gate }
50000Sstevel@tonic-gate nb = sizeof (extent_block_t) +
50010Sstevel@tonic-gate (sizeof (extent_t) * (log_eb->nextents - 1));
50020Sstevel@tonic-gate
50030Sstevel@tonic-gate log_eb = (extent_block_t *)malloc(nb);
50040Sstevel@tonic-gate if (log_eb == NULL) {
50050Sstevel@tonic-gate printf("Failed to allocate memory for extent block log\n");
50060Sstevel@tonic-gate return (0);
50070Sstevel@tonic-gate }
50080Sstevel@tonic-gate memcpy(log_eb, b, nb);
50090Sstevel@tonic-gate
50100Sstevel@tonic-gate if (log_eb->nextbno != 0)
50110Sstevel@tonic-gate /*
50120Sstevel@tonic-gate * Currently, as of 11-Dec-1997 the field nextbno isn't
50130Sstevel@tonic-gate * implemented. If someone starts using this sucker we'd
50140Sstevel@tonic-gate * better warn somebody.
50150Sstevel@tonic-gate */
50160Sstevel@tonic-gate printf("WARNING: extent block field nextbno is non-zero!\n");
50170Sstevel@tonic-gate
50180Sstevel@tonic-gate /*
50190Sstevel@tonic-gate * Now read in the on disk log structure. This is always in the
50200Sstevel@tonic-gate * first block of the first extent.
50210Sstevel@tonic-gate */
50220Sstevel@tonic-gate b = getblk((u_offset_t)ldbtob(logbtodb(fs, log_eb->extents[0].pbno)));
50230Sstevel@tonic-gate log_odi = (ml_odunit_t *)malloc(sizeof (ml_odunit_t));
50240Sstevel@tonic-gate if (log_odi == NULL) {
50250Sstevel@tonic-gate free(log_eb);
50260Sstevel@tonic-gate log_eb = NULL;
50270Sstevel@tonic-gate printf("Failed to allocate memory for ondisk structure\n");
50280Sstevel@tonic-gate return (0);
50290Sstevel@tonic-gate }
50300Sstevel@tonic-gate memcpy(log_odi, b, sizeof (ml_odunit_t));
50310Sstevel@tonic-gate
50320Sstevel@tonic-gate /*
50330Sstevel@tonic-gate * Consistency checks.
50340Sstevel@tonic-gate */
50350Sstevel@tonic-gate if (log_odi->od_version != LUFS_VERSION_LATEST) {
50360Sstevel@tonic-gate free(log_eb);
50370Sstevel@tonic-gate log_eb = NULL;
50380Sstevel@tonic-gate free(log_odi);
50390Sstevel@tonic-gate log_odi = NULL;
50400Sstevel@tonic-gate printf("Version mismatch in on-disk version of log data\n");
50410Sstevel@tonic-gate return (0);
50420Sstevel@tonic-gate } else if (log_odi->od_badlog) {
50430Sstevel@tonic-gate printf("WARNING: Log was marked as bad\n");
50440Sstevel@tonic-gate }
50450Sstevel@tonic-gate
50460Sstevel@tonic-gate return (1);
50470Sstevel@tonic-gate }
50480Sstevel@tonic-gate
50491051Smaheshvs static void
log_display_header(void)50500Sstevel@tonic-gate log_display_header(void)
50510Sstevel@tonic-gate {
50520Sstevel@tonic-gate int x;
50530Sstevel@tonic-gate if (!log_get_header_info())
50540Sstevel@tonic-gate /*
50550Sstevel@tonic-gate * No need to display anything here. The previous routine
50560Sstevel@tonic-gate * has already done so.
50570Sstevel@tonic-gate */
50580Sstevel@tonic-gate return;
50590Sstevel@tonic-gate
50600Sstevel@tonic-gate if (fs->fs_magic == FS_MAGIC)
50610Sstevel@tonic-gate printf("Log block number: 0x%x\n------------------\n",
50620Sstevel@tonic-gate fs->fs_logbno);
50630Sstevel@tonic-gate else
50640Sstevel@tonic-gate printf("Log frag number: 0x%x\n------------------\n",
50650Sstevel@tonic-gate fs->fs_logbno);
50660Sstevel@tonic-gate printf("Extent Info\n\t# Extents : %d\n\t# Bytes : 0x%x\n",
50670Sstevel@tonic-gate log_eb->nextents, log_eb->nbytes);
50680Sstevel@tonic-gate printf("\tNext Block : 0x%x\n\tExtent List\n\t--------\n",
50690Sstevel@tonic-gate log_eb->nextbno);
50700Sstevel@tonic-gate for (x = 0; x < log_eb->nextents; x++)
50710Sstevel@tonic-gate printf("\t [%d] lbno 0x%08x pbno 0x%08x nbno 0x%08x\n",
50720Sstevel@tonic-gate x, log_eb->extents[x].lbno, log_eb->extents[x].pbno,
50730Sstevel@tonic-gate log_eb->extents[x].nbno);
50740Sstevel@tonic-gate printf("\nOn Disk Info\n\tbol_lof : 0x%08x\n\teol_lof : 0x%08x\n",
50750Sstevel@tonic-gate log_odi->od_bol_lof, log_odi->od_eol_lof);
50760Sstevel@tonic-gate printf("\tlog_size : 0x%08x\n",
50770Sstevel@tonic-gate log_odi->od_logsize);
50780Sstevel@tonic-gate printf("\thead_lof : 0x%08x\tident : 0x%x\n",
50790Sstevel@tonic-gate log_odi->od_head_lof, log_odi->od_head_ident);
50800Sstevel@tonic-gate printf("\ttail_lof : 0x%08x\tident : 0x%x\n\thead_tid : 0x%08x\n",
50810Sstevel@tonic-gate log_odi->od_tail_lof, log_odi->od_tail_ident, log_odi->od_head_tid);
50820Sstevel@tonic-gate printf("\tcheck sum : 0x%08x\n", log_odi->od_chksum);
50830Sstevel@tonic-gate if (log_odi->od_chksum !=
50840Sstevel@tonic-gate (log_odi->od_head_ident + log_odi->od_tail_ident))
50850Sstevel@tonic-gate printf("bad checksum: found 0x%08x, should be 0x%08x\n",
50860Sstevel@tonic-gate log_odi->od_chksum,
50870Sstevel@tonic-gate log_odi->od_head_ident + log_odi->od_tail_ident);
50880Sstevel@tonic-gate if (log_odi->od_head_lof == log_odi->od_tail_lof)
50890Sstevel@tonic-gate printf("\t --- Log is empty ---\n");
50900Sstevel@tonic-gate }
50910Sstevel@tonic-gate
50920Sstevel@tonic-gate /*
50930Sstevel@tonic-gate * log_lodb -- logical log offset to disk block number
50940Sstevel@tonic-gate */
50951051Smaheshvs int
log_lodb(u_offset_t off,diskaddr_t * pblk)50960Sstevel@tonic-gate log_lodb(u_offset_t off, diskaddr_t *pblk)
50970Sstevel@tonic-gate {
50980Sstevel@tonic-gate uint32_t lblk = (uint32_t)btodb(off);
50990Sstevel@tonic-gate int x;
51000Sstevel@tonic-gate
51012984Sdmick if (!log_get_header_info())
51022984Sdmick /*
51032984Sdmick * No need to display anything here. The previous routine
51042984Sdmick * has already done so.
51052984Sdmick */
51062993Sdmick return (0);
51072984Sdmick
51080Sstevel@tonic-gate for (x = 0; x < log_eb->nextents; x++)
51090Sstevel@tonic-gate if ((lblk >= log_eb->extents[x].lbno) &&
51100Sstevel@tonic-gate (lblk < (log_eb->extents[x].lbno +
51110Sstevel@tonic-gate log_eb->extents[x].nbno))) {
51120Sstevel@tonic-gate *pblk = (diskaddr_t)lblk - log_eb->extents[x].lbno +
51130Sstevel@tonic-gate logbtodb(fs, log_eb->extents[x].pbno);
51140Sstevel@tonic-gate return (1);
51150Sstevel@tonic-gate }
51160Sstevel@tonic-gate return (0);
51170Sstevel@tonic-gate }
51180Sstevel@tonic-gate
51190Sstevel@tonic-gate /*
51200Sstevel@tonic-gate * String names for the enumerated types. These are only used
51210Sstevel@tonic-gate * for display purposes.
51220Sstevel@tonic-gate */
51230Sstevel@tonic-gate char *dt_str[] = {
51240Sstevel@tonic-gate "DT_NONE", "DT_SB", "DT_CG", "DT_SI", "DT_AB",
51250Sstevel@tonic-gate "DT_ABZERO", "DT_DIR", "DT_INODE", "DT_FBI",
51260Sstevel@tonic-gate "DT_QR", "DT_COMMIT", "DT_CANCEL", "DT_BOT",
51270Sstevel@tonic-gate "DT_EOT", "DT_UD", "DT_SUD", "DT_SHAD", "DT_MAX"
51280Sstevel@tonic-gate };
51290Sstevel@tonic-gate
51300Sstevel@tonic-gate /*
51310Sstevel@tonic-gate * log_read_log -- transfer information from the log and adjust offset
51320Sstevel@tonic-gate */
51331051Smaheshvs int
log_read_log(u_offset_t * addr,caddr_t va,int nb,uint32_t * chk)51340Sstevel@tonic-gate log_read_log(u_offset_t *addr, caddr_t va, int nb, uint32_t *chk)
51350Sstevel@tonic-gate {
51360Sstevel@tonic-gate int xfer;
51370Sstevel@tonic-gate caddr_t bp;
51380Sstevel@tonic-gate diskaddr_t pblk;
51390Sstevel@tonic-gate sect_trailer_t *st;
51400Sstevel@tonic-gate
51410Sstevel@tonic-gate while (nb) {
51420Sstevel@tonic-gate if (!log_lodb(*addr, &pblk)) {
51430Sstevel@tonic-gate printf("Invalid log offset\n");
51440Sstevel@tonic-gate return (0);
51450Sstevel@tonic-gate }
51460Sstevel@tonic-gate
51470Sstevel@tonic-gate /*
51480Sstevel@tonic-gate * fsdb getblk() expects offsets not block number.
51490Sstevel@tonic-gate */
51500Sstevel@tonic-gate if ((bp = getblk((u_offset_t)dbtob(pblk))) == NULL)
51510Sstevel@tonic-gate return (0);
51520Sstevel@tonic-gate
51530Sstevel@tonic-gate xfer = MIN(NB_LEFT_IN_SECTOR(*addr), nb);
51540Sstevel@tonic-gate if (va != NULL) {
51550Sstevel@tonic-gate memcpy(va, bp + blkoff(fs, *addr), xfer);
51560Sstevel@tonic-gate va += xfer;
51570Sstevel@tonic-gate }
51580Sstevel@tonic-gate nb -= xfer;
51590Sstevel@tonic-gate *addr += xfer;
51600Sstevel@tonic-gate
51610Sstevel@tonic-gate /*
51620Sstevel@tonic-gate * If the log offset is now at a sector trailer
51630Sstevel@tonic-gate * run the checks if requested.
51640Sstevel@tonic-gate */
51650Sstevel@tonic-gate if (NB_LEFT_IN_SECTOR(*addr) == 0) {
51660Sstevel@tonic-gate if (chk != NULL) {
51670Sstevel@tonic-gate st = (sect_trailer_t *)
51680Sstevel@tonic-gate (bp + blkoff(fs, *addr));
51690Sstevel@tonic-gate if (*chk != st->st_ident) {
51700Sstevel@tonic-gate printf(
51710Sstevel@tonic-gate "Expected sector trailer id 0x%08x, but saw 0x%08x\n",
51720Sstevel@tonic-gate *chk, st->st_ident);
51730Sstevel@tonic-gate return (0);
51740Sstevel@tonic-gate } else {
51750Sstevel@tonic-gate *chk = st->st_ident + 1;
51760Sstevel@tonic-gate /*
51770Sstevel@tonic-gate * We update the on disk structure
51780Sstevel@tonic-gate * transaction ID each time we see
51790Sstevel@tonic-gate * one. By comparing this value
51800Sstevel@tonic-gate * to the last valid DT_COMMIT record
51810Sstevel@tonic-gate * we can determine if our log is
51820Sstevel@tonic-gate * completely valid.
51830Sstevel@tonic-gate */
51840Sstevel@tonic-gate log_odi->od_head_tid = st->st_tid;
51850Sstevel@tonic-gate }
51860Sstevel@tonic-gate }
51870Sstevel@tonic-gate *addr += sizeof (sect_trailer_t);
51880Sstevel@tonic-gate }
51890Sstevel@tonic-gate if ((int32_t)*addr == log_odi->od_eol_lof)
51900Sstevel@tonic-gate *addr = log_odi->od_bol_lof;
51910Sstevel@tonic-gate }
51920Sstevel@tonic-gate return (1);
51930Sstevel@tonic-gate }
51940Sstevel@tonic-gate
51950Sstevel@tonic-gate u_offset_t
log_nbcommit(u_offset_t a)51960Sstevel@tonic-gate log_nbcommit(u_offset_t a)
51970Sstevel@tonic-gate {
51980Sstevel@tonic-gate /*
51990Sstevel@tonic-gate * Comments are straight from ufs_log.c
52000Sstevel@tonic-gate *
52010Sstevel@tonic-gate * log is the offset following the commit header. However,
52020Sstevel@tonic-gate * if the commit header fell on the end-of-sector, then lof
52030Sstevel@tonic-gate * has already been advanced to the beginning of the next
52040Sstevel@tonic-gate * sector. So do nothgin. Otherwise, return the remaining
52050Sstevel@tonic-gate * bytes in the sector.
52060Sstevel@tonic-gate */
52070Sstevel@tonic-gate if ((a & (DEV_BSIZE - 1)) == 0)
52080Sstevel@tonic-gate return (0);
52090Sstevel@tonic-gate else
52100Sstevel@tonic-gate return (NB_LEFT_IN_SECTOR(a));
52110Sstevel@tonic-gate }
52120Sstevel@tonic-gate
52130Sstevel@tonic-gate /*
52140Sstevel@tonic-gate * log_show -- pretty print the deltas. The number of which is determined
52150Sstevel@tonic-gate * by the log_enum arg. If LOG_ALLDELTAS the routine, as the
52160Sstevel@tonic-gate * name implies dumps everything. If LOG_NDELTAS, the routine
52170Sstevel@tonic-gate * will print out "count" deltas starting at "addr". If
52180Sstevel@tonic-gate * LOG_CHECKSCAN then run through the log checking the st_ident
52190Sstevel@tonic-gate * for valid data.
52200Sstevel@tonic-gate */
52211051Smaheshvs static void
log_show(enum log_enum l)52220Sstevel@tonic-gate log_show(enum log_enum l)
52230Sstevel@tonic-gate {
52240Sstevel@tonic-gate struct delta d;
52250Sstevel@tonic-gate int32_t bol, eol;
52260Sstevel@tonic-gate int x = 0;
52270Sstevel@tonic-gate uint32_t chk;
52280Sstevel@tonic-gate
52290Sstevel@tonic-gate if (!log_get_header_info())
52300Sstevel@tonic-gate /*
52310Sstevel@tonic-gate * No need to display any error messages here. The previous
52320Sstevel@tonic-gate * routine has already done so.
52330Sstevel@tonic-gate */
52340Sstevel@tonic-gate return;
52350Sstevel@tonic-gate
52360Sstevel@tonic-gate bol = log_odi->od_head_lof;
52370Sstevel@tonic-gate eol = log_odi->od_tail_lof;
52380Sstevel@tonic-gate chk = log_odi->od_head_ident;
52390Sstevel@tonic-gate
52400Sstevel@tonic-gate if (bol == eol) {
52410Sstevel@tonic-gate if ((l == LOG_ALLDELTAS) || (l == LOG_CHECKSCAN)) {
52420Sstevel@tonic-gate printf("Empty log.\n");
52430Sstevel@tonic-gate return;
52440Sstevel@tonic-gate } else
52450Sstevel@tonic-gate printf("WARNING: empty log. addr may generate bogus"
52460Sstevel@tonic-gate " information");
52470Sstevel@tonic-gate }
52480Sstevel@tonic-gate
52490Sstevel@tonic-gate /*
52500Sstevel@tonic-gate * Only reset the "addr" if we've been requested to show all
52510Sstevel@tonic-gate * deltas in the log.
52520Sstevel@tonic-gate */
52530Sstevel@tonic-gate if ((l == LOG_ALLDELTAS) || (l == LOG_CHECKSCAN))
52540Sstevel@tonic-gate addr = (u_offset_t)bol;
52550Sstevel@tonic-gate
52560Sstevel@tonic-gate if (l != LOG_CHECKSCAN) {
52570Sstevel@tonic-gate printf(" Log Offset Delta Count Type\n");
52580Sstevel@tonic-gate printf("-----------------------------------------"
52590Sstevel@tonic-gate "-----------------\n");
52600Sstevel@tonic-gate }
52610Sstevel@tonic-gate
52620Sstevel@tonic-gate while ((bol != eol) && ((l == LOG_ALLDELTAS) ||
52630Sstevel@tonic-gate (l == LOG_CHECKSCAN) || count--)) {
52640Sstevel@tonic-gate if (!log_read_log(&addr, (caddr_t)&d, sizeof (d),
52650Sstevel@tonic-gate ((l == LOG_ALLDELTAS) || (l == LOG_CHECKSCAN)) ?
52660Sstevel@tonic-gate &chk : NULL))
52670Sstevel@tonic-gate /*
52680Sstevel@tonic-gate * Two failures are possible. One from getblk()
52690Sstevel@tonic-gate * which prints out a message or when we've hit
52700Sstevel@tonic-gate * an invalid block which may or may not indicate
52710Sstevel@tonic-gate * an error
52720Sstevel@tonic-gate */
52730Sstevel@tonic-gate goto end_scan;
52740Sstevel@tonic-gate
52750Sstevel@tonic-gate if ((uint32_t)d.d_nb > log_odi->od_logsize) {
52760Sstevel@tonic-gate printf("Bad delta entry. size out of bounds\n");
52770Sstevel@tonic-gate return;
52780Sstevel@tonic-gate }
52790Sstevel@tonic-gate if (l != LOG_CHECKSCAN)
52800Sstevel@tonic-gate printf("[%04d] %08x %08x.%08x %08x %s\n", x++, bol,
52810Sstevel@tonic-gate d.d_mof, d.d_nb,
52820Sstevel@tonic-gate dt_str[d.d_typ >= DT_MAX ? DT_MAX : d.d_typ]);
52830Sstevel@tonic-gate
52840Sstevel@tonic-gate switch (d.d_typ) {
52850Sstevel@tonic-gate case DT_CANCEL:
52860Sstevel@tonic-gate case DT_ABZERO:
52870Sstevel@tonic-gate /*
52880Sstevel@tonic-gate * These two deltas don't have log space
52890Sstevel@tonic-gate * associated with the entry even though
52900Sstevel@tonic-gate * d_nb is non-zero.
52910Sstevel@tonic-gate */
52920Sstevel@tonic-gate break;
52930Sstevel@tonic-gate
52940Sstevel@tonic-gate case DT_COMMIT:
52950Sstevel@tonic-gate /*
52960Sstevel@tonic-gate * Commit records have zero size yet, the
52970Sstevel@tonic-gate * rest of the current disk block is avoided.
52980Sstevel@tonic-gate */
52990Sstevel@tonic-gate addr += log_nbcommit(addr);
53000Sstevel@tonic-gate lufs_tid = log_odi->od_head_tid;
53010Sstevel@tonic-gate lufs_tid_valid = True;
53020Sstevel@tonic-gate break;
53030Sstevel@tonic-gate
53040Sstevel@tonic-gate default:
53050Sstevel@tonic-gate if (!log_read_log(&addr, NULL, d.d_nb,
53060Sstevel@tonic-gate ((l == LOG_ALLDELTAS) ||
53070Sstevel@tonic-gate (l == LOG_CHECKSCAN)) ? &chk : NULL))
53080Sstevel@tonic-gate goto end_scan;
53090Sstevel@tonic-gate break;
53100Sstevel@tonic-gate }
53110Sstevel@tonic-gate bol = (int32_t)addr;
53120Sstevel@tonic-gate }
53130Sstevel@tonic-gate
53140Sstevel@tonic-gate end_scan:
53150Sstevel@tonic-gate if (lufs_tid_valid == True) {
53160Sstevel@tonic-gate if (lufs_tid == log_odi->od_head_tid)
53170Sstevel@tonic-gate printf("scan -- okay\n");
53180Sstevel@tonic-gate else
53190Sstevel@tonic-gate printf("scan -- some transactions have been lost\n");
53200Sstevel@tonic-gate } else {
53210Sstevel@tonic-gate printf("scan -- failed to find a single valid transaction\n");
53220Sstevel@tonic-gate printf(" (possibly due to an empty log)\n");
53230Sstevel@tonic-gate }
53240Sstevel@tonic-gate }
5325