xref: /titanic_41/usr/src/cmd/fs.d/ufs/fsdb/fsdb.c (revision 16222dda8ab79e59a26e1a5f6c4f627c0c53508a)
17c478bd9Sstevel@tonic-gate /*
2*16222ddaSGary Mills  * Copyright 2015 Gary Mills
385651ed9SJohn.Zolnowsky@Sun.COM  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1988 Regents of the University of California.
87c478bd9Sstevel@tonic-gate  * All rights reserved.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
117c478bd9Sstevel@tonic-gate  * Computer Consoles Inc.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
147c478bd9Sstevel@tonic-gate  * provided that: (1) source distributions retain this entire copyright
157c478bd9Sstevel@tonic-gate  * notice and comment, and (2) distributions including binaries display
167c478bd9Sstevel@tonic-gate  * the following acknowledgement:  ``This product includes software
177c478bd9Sstevel@tonic-gate  * developed by the University of California, Berkeley and its contributors''
187c478bd9Sstevel@tonic-gate  * in the documentation or other materials provided with the distribution
197c478bd9Sstevel@tonic-gate  * and in all advertising materials mentioning features or use of this
207c478bd9Sstevel@tonic-gate  * software. Neither the name of the University nor the names of its
217c478bd9Sstevel@tonic-gate  * contributors may be used to endorse or promote products derived
227c478bd9Sstevel@tonic-gate  * from this software without specific prior written permission.
237c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
247c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
257c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #ifndef lint
297c478bd9Sstevel@tonic-gate char copyright[] =
307c478bd9Sstevel@tonic-gate "@(#) Copyright(c) 1988 Regents of the University of California.\n\
317c478bd9Sstevel@tonic-gate All rights reserved.\n";
327c478bd9Sstevel@tonic-gate #endif /* not lint */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #ifndef lint
357c478bd9Sstevel@tonic-gate static char sccsid[] = "@(#)fsdb.c	5.8 (Berkeley) 6/1/90";
367c478bd9Sstevel@tonic-gate #endif /* not lint */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  *  fsdb - file system debugger
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  *  usage: fsdb [-o suboptions] special
427c478bd9Sstevel@tonic-gate  *  options/suboptions:
437c478bd9Sstevel@tonic-gate  *	-o
447c478bd9Sstevel@tonic-gate  *		?		display usage
457c478bd9Sstevel@tonic-gate  *		o		override some error conditions
467c478bd9Sstevel@tonic-gate  *		p="string"	set prompt to string
477c478bd9Sstevel@tonic-gate  *		w		open for write
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include <sys/param.h>
517c478bd9Sstevel@tonic-gate #include <sys/signal.h>
527c478bd9Sstevel@tonic-gate #include <sys/file.h>
537c478bd9Sstevel@tonic-gate #include <inttypes.h>
547c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #ifdef sun
577c478bd9Sstevel@tonic-gate #include <unistd.h>
587c478bd9Sstevel@tonic-gate #include <stdlib.h>
597c478bd9Sstevel@tonic-gate #include <string.h>
607c478bd9Sstevel@tonic-gate #include <fcntl.h>
617c478bd9Sstevel@tonic-gate #include <signal.h>
627c478bd9Sstevel@tonic-gate #include <sys/types.h>
637c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
647c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
657c478bd9Sstevel@tonic-gate #include <sys/wait.h>
667c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
677c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
687c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
697c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_acl.h>
707c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
717c478bd9Sstevel@tonic-gate #else
727c478bd9Sstevel@tonic-gate #include <sys/dir.h>
737c478bd9Sstevel@tonic-gate #include <ufs/fs.h>
747c478bd9Sstevel@tonic-gate #include <ufs/dinode.h>
757c478bd9Sstevel@tonic-gate #include <paths.h>
767c478bd9Sstevel@tonic-gate #endif /* sun */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate #include <stdio.h>
797c478bd9Sstevel@tonic-gate #include <setjmp.h>
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate #define	OLD_FSDB_COMPATIBILITY	/* To support the obsoleted "-z" option */
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate #ifndef _PATH_BSHELL
847c478bd9Sstevel@tonic-gate #define	_PATH_BSHELL	"/bin/sh"
857c478bd9Sstevel@tonic-gate #endif /* _PATH_BSHELL */
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Defines from the 4.3-tahoe file system, for systems with the 4.2 or 4.3
887c478bd9Sstevel@tonic-gate  * file system.
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate #ifndef FS_42POSTBLFMT
917c478bd9Sstevel@tonic-gate #define	cg_blktot(cgp) (((cgp))->cg_btot)
927c478bd9Sstevel@tonic-gate #define	cg_blks(fs, cgp, cylno) (((cgp))->cg_b[cylno])
937c478bd9Sstevel@tonic-gate #define	cg_inosused(cgp) (((cgp))->cg_iused)
947c478bd9Sstevel@tonic-gate #define	cg_blksfree(cgp) (((cgp))->cg_free)
957c478bd9Sstevel@tonic-gate #define	cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
967c478bd9Sstevel@tonic-gate #endif
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * Never changing defines.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate #define	OCTAL		8		/* octal base */
1027c478bd9Sstevel@tonic-gate #define	DECIMAL		10		/* decimal base */
1037c478bd9Sstevel@tonic-gate #define	HEX		16		/* hexadecimal base */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate /*
1067c478bd9Sstevel@tonic-gate  * Adjustable defines.
1077c478bd9Sstevel@tonic-gate  */
1087c478bd9Sstevel@tonic-gate #define	NBUF		10		/* number of cache buffers */
1097c478bd9Sstevel@tonic-gate #define	PROMPTSIZE	80		/* size of user definable prompt */
1107c478bd9Sstevel@tonic-gate #define	MAXFILES	40000		/* max number of files ls can handle */
1117c478bd9Sstevel@tonic-gate #define	FIRST_DEPTH	10		/* default depth for find and ls */
1127c478bd9Sstevel@tonic-gate #define	SECOND_DEPTH	100		/* second try at depth (maximum) */
1137c478bd9Sstevel@tonic-gate #define	INPUTBUFFER	1040		/* size of input buffer */
1147c478bd9Sstevel@tonic-gate #define	BYTESPERLINE	16		/* bytes per line of /dxo output */
1157c478bd9Sstevel@tonic-gate #define	NREG		36		/* number of save registers */
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate #define	DEVPREFIX	"/dev/"		/* Uninteresting part of "special" */
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
1207c478bd9Sstevel@tonic-gate #define	FSDB_OPTIONS	"o:wp:z:"
1217c478bd9Sstevel@tonic-gate #else
1227c478bd9Sstevel@tonic-gate #define	FSDB_OPTIONS	"o:wp:"
1237c478bd9Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate  * Values dependent on sizes of structs and such.
1287c478bd9Sstevel@tonic-gate  */
1297c478bd9Sstevel@tonic-gate #define	NUMB		3			/* these three are arbitrary, */
1307c478bd9Sstevel@tonic-gate #define	BLOCK		5			/* but must be different from */
1317c478bd9Sstevel@tonic-gate #define	FRAGMENT	7			/* the rest (hence odd). */
1327c478bd9Sstevel@tonic-gate #define	BITSPERCHAR	8			/* couldn't find it anywhere  */
1337c478bd9Sstevel@tonic-gate #define	CHAR		(sizeof (char))
1347c478bd9Sstevel@tonic-gate #define	SHORT		(sizeof (short))
1357c478bd9Sstevel@tonic-gate #define	LONG		(sizeof (long))
1367c478bd9Sstevel@tonic-gate #define	U_OFFSET_T	(sizeof (u_offset_t))	/* essentially "long long" */
1377c478bd9Sstevel@tonic-gate #define	INODE		(sizeof (struct dinode))
1387c478bd9Sstevel@tonic-gate #define	DIRECTORY	(sizeof (struct direct))
1397c478bd9Sstevel@tonic-gate #define	CGRP		(sizeof (struct cg))
1407c478bd9Sstevel@tonic-gate #define	SB		(sizeof (struct fs))
1417c478bd9Sstevel@tonic-gate #define	BLKSIZE		(fs->fs_bsize)		/* for clarity */
1427c478bd9Sstevel@tonic-gate #define	FRGSIZE		(fs->fs_fsize)
1437c478bd9Sstevel@tonic-gate #define	BLKSHIFT	(fs->fs_bshift)
1447c478bd9Sstevel@tonic-gate #define	FRGSHIFT	(fs->fs_fshift)
1457c478bd9Sstevel@tonic-gate #define	SHADOW_DATA	(sizeof (struct ufs_fsd))
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate /*
1487c478bd9Sstevel@tonic-gate  * Messy macros that would otherwise clutter up such glamorous code.
1497c478bd9Sstevel@tonic-gate  */
1507c478bd9Sstevel@tonic-gate #define	itob(i)		(((u_offset_t)itod(fs, (i)) << \
1517c478bd9Sstevel@tonic-gate 	(u_offset_t)FRGSHIFT) + (u_offset_t)itoo(fs, (i)) * (u_offset_t)INODE)
1527c478bd9Sstevel@tonic-gate #define	min(x, y)	((x) < (y) ? (x) : (y))
1537c478bd9Sstevel@tonic-gate #define	STRINGSIZE(d)	((long)d->d_reclen - \
1547c478bd9Sstevel@tonic-gate 				((long)&d->d_name[0] - (long)&d->d_ino))
1557c478bd9Sstevel@tonic-gate #define	letter(c)	((((c) >= 'a')&&((c) <= 'z')) ||\
1567c478bd9Sstevel@tonic-gate 				(((c) >= 'A')&&((c) <= 'Z')))
1577c478bd9Sstevel@tonic-gate #define	digit(c)	(((c) >= '0') && ((c) <= '9'))
1587c478bd9Sstevel@tonic-gate #define	HEXLETTER(c)	(((c) >= 'A') && ((c) <= 'F'))
1597c478bd9Sstevel@tonic-gate #define	hexletter(c)	(((c) >= 'a') && ((c) <= 'f'))
1607c478bd9Sstevel@tonic-gate #define	octaldigit(c)	(((c) >= '0') && ((c) <= '7'))
1617c478bd9Sstevel@tonic-gate #define	uppertolower(c)	((c) - 'A' + 'a')
1627c478bd9Sstevel@tonic-gate #define	hextodigit(c)	((c) - 'a' + 10)
1637c478bd9Sstevel@tonic-gate #define	numtodigit(c)	((c) - '0')
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate #if !defined(loword)
1667c478bd9Sstevel@tonic-gate #define	loword(X)	(((ushort_t *)&X)[1])
1677c478bd9Sstevel@tonic-gate #endif /* loword */
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate #if !defined(lobyte)
1707c478bd9Sstevel@tonic-gate #define	lobyte(X)	(((unsigned char *)&X)[1])
1717c478bd9Sstevel@tonic-gate #endif /* lobyte */
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate  * buffer cache structure.
1757c478bd9Sstevel@tonic-gate  */
1767c478bd9Sstevel@tonic-gate static struct lbuf {
1777c478bd9Sstevel@tonic-gate 	struct	lbuf  *fwd;
1787c478bd9Sstevel@tonic-gate 	struct	lbuf  *back;
1797c478bd9Sstevel@tonic-gate 	char	*blkaddr;
1807c478bd9Sstevel@tonic-gate 	short	valid;
1817c478bd9Sstevel@tonic-gate 	u_offset_t	blkno;
1827c478bd9Sstevel@tonic-gate } lbuf[NBUF], bhdr;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate  * used to hold save registers (see '<' and '>').
1867c478bd9Sstevel@tonic-gate  */
1877c478bd9Sstevel@tonic-gate struct	save_registers {
1887c478bd9Sstevel@tonic-gate 	u_offset_t	sv_addr;
1897c478bd9Sstevel@tonic-gate 	u_offset_t	sv_value;
1907c478bd9Sstevel@tonic-gate 	long		sv_objsz;
1917c478bd9Sstevel@tonic-gate } regs[NREG];
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate /*
1947c478bd9Sstevel@tonic-gate  * cd, find, and ls use this to hold filenames.  Each filename is broken
1957c478bd9Sstevel@tonic-gate  * up by a slash.  In other words, /usr/src/adm would have a len field
1967c478bd9Sstevel@tonic-gate  * of 2 (starting from 0), and filenames->fname[0-2] would hold usr,
1977c478bd9Sstevel@tonic-gate  * src, and adm components of the pathname.
1987c478bd9Sstevel@tonic-gate  */
1997c478bd9Sstevel@tonic-gate static struct filenames {
2007c478bd9Sstevel@tonic-gate 	ino_t	ino;		/* inode */
2017c478bd9Sstevel@tonic-gate 	long	len;		/* number of components */
2027c478bd9Sstevel@tonic-gate 	char	flag;		/* flag if using SECOND_DEPTH allocator */
2037c478bd9Sstevel@tonic-gate 	char	find;		/* flag if found by find */
2047c478bd9Sstevel@tonic-gate 	char	**fname;	/* hold components of pathname */
2057c478bd9Sstevel@tonic-gate } *filenames, *top;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate enum log_enum { LOG_NDELTAS, LOG_ALLDELTAS, LOG_CHECKSCAN };
2087c478bd9Sstevel@tonic-gate #ifdef sun
2097c478bd9Sstevel@tonic-gate struct fs	*fs;
2107c478bd9Sstevel@tonic-gate static union {
2117c478bd9Sstevel@tonic-gate 	struct fs	un_filesystem;
2127c478bd9Sstevel@tonic-gate 	char		un_sbsize[SBSIZE];
2137c478bd9Sstevel@tonic-gate } fs_un;
2147c478bd9Sstevel@tonic-gate #define	filesystem	fs_un.un_filesystem
2157c478bd9Sstevel@tonic-gate #else
2167c478bd9Sstevel@tonic-gate struct fs filesystem, *fs;	/* super block */
2177c478bd9Sstevel@tonic-gate #endif /* sun */
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate  * Global data.
2217c478bd9Sstevel@tonic-gate  */
2227c478bd9Sstevel@tonic-gate static char		*input_path[MAXPATHLEN];
2237c478bd9Sstevel@tonic-gate static char		*stack_path[MAXPATHLEN];
2247c478bd9Sstevel@tonic-gate static char		*current_path[MAXPATHLEN];
2257c478bd9Sstevel@tonic-gate static char		input_buffer[INPUTBUFFER];
2267c478bd9Sstevel@tonic-gate static char		*prompt;
2277c478bd9Sstevel@tonic-gate static char		*buffers;
2287c478bd9Sstevel@tonic-gate static char		scratch[64];
2297c478bd9Sstevel@tonic-gate static char		BASE[] = "o u     x";
2307c478bd9Sstevel@tonic-gate static char		PROMPT[PROMPTSIZE];
2317c478bd9Sstevel@tonic-gate static char		laststyle = '/';
2327c478bd9Sstevel@tonic-gate static char		lastpo = 'x';
2337c478bd9Sstevel@tonic-gate static short		input_pointer;
2347c478bd9Sstevel@tonic-gate static short		current_pathp;
2357c478bd9Sstevel@tonic-gate static short		stack_pathp;
2367c478bd9Sstevel@tonic-gate static short		input_pathp;
2377c478bd9Sstevel@tonic-gate static short		cmp_level;
2387c478bd9Sstevel@tonic-gate static int		nfiles;
2397c478bd9Sstevel@tonic-gate static short		type = NUMB;
2407c478bd9Sstevel@tonic-gate static short		dirslot;
2417c478bd9Sstevel@tonic-gate static short		fd;
2427c478bd9Sstevel@tonic-gate static short		c_count;
2437c478bd9Sstevel@tonic-gate static short		error;
2447c478bd9Sstevel@tonic-gate static short		paren;
2457c478bd9Sstevel@tonic-gate static short		trapped;
2467c478bd9Sstevel@tonic-gate static short		doing_cd;
2477c478bd9Sstevel@tonic-gate static short		doing_find;
2487c478bd9Sstevel@tonic-gate static short		find_by_name;
2497c478bd9Sstevel@tonic-gate static short		find_by_inode;
2507c478bd9Sstevel@tonic-gate static short		long_list;
2517c478bd9Sstevel@tonic-gate static short		recursive;
2527c478bd9Sstevel@tonic-gate static short		objsz = SHORT;
2537c478bd9Sstevel@tonic-gate static short		override = 0;
2547c478bd9Sstevel@tonic-gate static short		wrtflag = O_RDONLY;
2557c478bd9Sstevel@tonic-gate static short		base = HEX;
2567c478bd9Sstevel@tonic-gate static short		acting_on_inode;
2577c478bd9Sstevel@tonic-gate static short		acting_on_directory;
2587c478bd9Sstevel@tonic-gate static short		should_print = 1;
2597c478bd9Sstevel@tonic-gate static short		clear;
2607c478bd9Sstevel@tonic-gate static short		star;
2617c478bd9Sstevel@tonic-gate static u_offset_t	addr;
2627c478bd9Sstevel@tonic-gate static u_offset_t	bod_addr;
2637c478bd9Sstevel@tonic-gate static u_offset_t	value;
2647c478bd9Sstevel@tonic-gate static u_offset_t	erraddr;
2657c478bd9Sstevel@tonic-gate static long		errcur_bytes;
2667c478bd9Sstevel@tonic-gate static u_offset_t	errino;
2677c478bd9Sstevel@tonic-gate static long		errinum;
2687c478bd9Sstevel@tonic-gate static long		cur_cgrp;
2697c478bd9Sstevel@tonic-gate static u_offset_t	cur_ino;
2707c478bd9Sstevel@tonic-gate static long		cur_inum;
2717c478bd9Sstevel@tonic-gate static u_offset_t	cur_dir;
2727c478bd9Sstevel@tonic-gate static long		cur_block;
2737c478bd9Sstevel@tonic-gate static long		cur_bytes;
2747c478bd9Sstevel@tonic-gate static long		find_ino;
2757c478bd9Sstevel@tonic-gate static u_offset_t	filesize;
2767c478bd9Sstevel@tonic-gate static u_offset_t	blocksize;
2777c478bd9Sstevel@tonic-gate static long		stringsize;
2787c478bd9Sstevel@tonic-gate static long		count = 1;
2797c478bd9Sstevel@tonic-gate static long		commands;
2807c478bd9Sstevel@tonic-gate static long		read_requests;
2817c478bd9Sstevel@tonic-gate static long		actual_disk_reads;
2827c478bd9Sstevel@tonic-gate static jmp_buf		env;
2837c478bd9Sstevel@tonic-gate static long		maxfiles;
2847c478bd9Sstevel@tonic-gate static long		cur_shad;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate #ifndef sun
2877c478bd9Sstevel@tonic-gate extern char	*malloc(), *calloc();
2887c478bd9Sstevel@tonic-gate #endif
2897c478bd9Sstevel@tonic-gate static char		getachar();
2907c478bd9Sstevel@tonic-gate static char		*getblk(), *fmtentry();
2917c478bd9Sstevel@tonic-gate 
292d1a180b0Smaheshvs static offset_t		get(short);
2937c478bd9Sstevel@tonic-gate static long		bmap();
2947c478bd9Sstevel@tonic-gate static long		expr();
2957c478bd9Sstevel@tonic-gate static long		term();
2967c478bd9Sstevel@tonic-gate static long		getnumb();
2977c478bd9Sstevel@tonic-gate static u_offset_t	getdirslot();
298d1a180b0Smaheshvs static unsigned long	*print_check(unsigned long *, long *, short, int);
2997c478bd9Sstevel@tonic-gate 
300d1a180b0Smaheshvs static void		usage(char *);
301d1a180b0Smaheshvs static void		ungetachar(char);
3027c478bd9Sstevel@tonic-gate static void		getnextinput();
3037c478bd9Sstevel@tonic-gate static void		eat_spaces();
304d1a180b0Smaheshvs static void		restore_inode(ino_t);
3057c478bd9Sstevel@tonic-gate static void		find();
306d1a180b0Smaheshvs static void		ls(struct filenames *, struct filenames *, short);
307d1a180b0Smaheshvs static void		formatf(struct filenames *, struct filenames *);
3087c478bd9Sstevel@tonic-gate static void		parse();
309d1a180b0Smaheshvs static void		follow_path(long, long);
3107c478bd9Sstevel@tonic-gate static void		getname();
311d1a180b0Smaheshvs static void		freemem(struct filenames *, int);
312d1a180b0Smaheshvs static void		print_path(char **, int);
3137c478bd9Sstevel@tonic-gate static void		fill();
314d1a180b0Smaheshvs static void		put(u_offset_t, short);
315d1a180b0Smaheshvs static void		insert(struct lbuf *);
3167c478bd9Sstevel@tonic-gate static void		puta();
317d1a180b0Smaheshvs static void		fprnt(char, char);
3187c478bd9Sstevel@tonic-gate static void		index();
3197c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
3207c478bd9Sstevel@tonic-gate static void		printll
3217c478bd9Sstevel@tonic-gate 	(u_offset_t value, int fieldsz, int digits, int lead);
3227c478bd9Sstevel@tonic-gate #define	print(value, fieldsz, digits, lead) \
3237c478bd9Sstevel@tonic-gate 	printll((u_offset_t)value, fieldsz, digits, lead)
3247c478bd9Sstevel@tonic-gate #else /* !_LARGEFILE64_SOURCE */
3257c478bd9Sstevel@tonic-gate static void		print(long value, int fieldsz, int digits, int lead);
3267c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
327d1a180b0Smaheshvs static void		printsb(struct fs *);
328d1a180b0Smaheshvs static void		printcg(struct cg *);
329d1a180b0Smaheshvs static void		pbits(unsigned char *, int);
330d1a180b0Smaheshvs static void		old_fsdb(int, char *);	/* For old fsdb functionality */
3317c478bd9Sstevel@tonic-gate 
332d1a180b0Smaheshvs static int		isnumber(char *);
333d1a180b0Smaheshvs static int		icheck(u_offset_t);
334d1a180b0Smaheshvs static int		cgrp_check(long);
3357c478bd9Sstevel@tonic-gate static int		valid_addr();
336d1a180b0Smaheshvs static int		match(char *, int);
337d1a180b0Smaheshvs static int		devcheck(short);
3387c478bd9Sstevel@tonic-gate static int		bcomp();
339d1a180b0Smaheshvs static int		compare(char *, char *, short);
340d1a180b0Smaheshvs static int		check_addr(short, short *, short *, short);
3417c478bd9Sstevel@tonic-gate static int		fcmp();
3427c478bd9Sstevel@tonic-gate static int		ffcmp();
3437c478bd9Sstevel@tonic-gate 
344d1a180b0Smaheshvs static int		getshadowslot(long);
345d1a180b0Smaheshvs static void		getshadowdata(long *, int);
346d1a180b0Smaheshvs static void		syncshadowscan(int);
347d1a180b0Smaheshvs static void		log_display_header(void);
348d1a180b0Smaheshvs static void		log_show(enum log_enum);
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate #ifdef sun
3517c478bd9Sstevel@tonic-gate static void		err();
3527c478bd9Sstevel@tonic-gate #else
3537c478bd9Sstevel@tonic-gate static int		err();
3547c478bd9Sstevel@tonic-gate #endif /* sun */
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate /* Suboption vector */
3577c478bd9Sstevel@tonic-gate static char *subopt_v[] = {
3587c478bd9Sstevel@tonic-gate #define	OVERRIDE	0
3597c478bd9Sstevel@tonic-gate 	"o",
3607c478bd9Sstevel@tonic-gate #define	NEW_PROMPT	1
3617c478bd9Sstevel@tonic-gate 	"p",
3627c478bd9Sstevel@tonic-gate #define	WRITE_ENABLED	2
3637c478bd9Sstevel@tonic-gate 	"w",
3647c478bd9Sstevel@tonic-gate #define	ALT_PROMPT	3
3657c478bd9Sstevel@tonic-gate 	"prompt",
3667c478bd9Sstevel@tonic-gate 	NULL
3677c478bd9Sstevel@tonic-gate };
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate  * main - lines are read up to the unprotected ('\') newline and
3717c478bd9Sstevel@tonic-gate  *	held in an input buffer.  Characters may be read from the
3727c478bd9Sstevel@tonic-gate  *	input buffer using getachar() and unread using ungetachar().
3737c478bd9Sstevel@tonic-gate  *	Reading the whole line ahead allows the use of debuggers
3747c478bd9Sstevel@tonic-gate  *	which would otherwise be impossible since the debugger
3757c478bd9Sstevel@tonic-gate  *	and fsdb could not share stdin.
3767c478bd9Sstevel@tonic-gate  */
3777c478bd9Sstevel@tonic-gate 
378d1a180b0Smaheshvs int
main(int argc,char * argv[])379d1a180b0Smaheshvs main(int argc, char *argv[])
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate 
382d1a180b0Smaheshvs 	char		c, *cptr;
383d1a180b0Smaheshvs 	short		i;
384d1a180b0Smaheshvs 	struct direct	*dirp;
385d1a180b0Smaheshvs 	struct lbuf	*bp;
3867c478bd9Sstevel@tonic-gate 	char		*progname;
387*16222ddaSGary Mills 	volatile short	colon;
388*16222ddaSGary Mills 	short		mode;
3897c478bd9Sstevel@tonic-gate 	long		temp;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/* Options/Suboptions processing */
3927c478bd9Sstevel@tonic-gate 	int	opt;
3937c478bd9Sstevel@tonic-gate 	char	*subopts;
3947c478bd9Sstevel@tonic-gate 	char	*optval;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/*
3977c478bd9Sstevel@tonic-gate 	 * The following are used to support the old fsdb functionality
3987c478bd9Sstevel@tonic-gate 	 * of clearing an inode. It's better to use 'clri'.
3997c478bd9Sstevel@tonic-gate 	 */
4007c478bd9Sstevel@tonic-gate 	int			inum;	/* Inode number to clear */
4017c478bd9Sstevel@tonic-gate 	char			*special;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 	setbuf(stdin, NULL);
4047c478bd9Sstevel@tonic-gate 	progname = argv[0];
4057c478bd9Sstevel@tonic-gate 	prompt = &PROMPT[0];
4067c478bd9Sstevel@tonic-gate 	/*
4077c478bd9Sstevel@tonic-gate 	 * Parse options.
4087c478bd9Sstevel@tonic-gate 	 */
4097c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, FSDB_OPTIONS)) != EOF) {
4107c478bd9Sstevel@tonic-gate 		switch (opt) {
4117c478bd9Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
4127c478bd9Sstevel@tonic-gate 		case 'z':	/* Hack - Better to use clri */
4137c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
4147c478bd9Sstevel@tonic-gate "Warning: The '-z' option of 'fsdb_ufs' has been declared obsolete",
4157c478bd9Sstevel@tonic-gate "and may not be supported in a future version of Solaris.",
4167c478bd9Sstevel@tonic-gate "While this functionality is currently still supported, the",
4177c478bd9Sstevel@tonic-gate "recommended procedure to clear an inode is to use clri(1M).");
4187c478bd9Sstevel@tonic-gate 			if (isnumber(optarg)) {
4197c478bd9Sstevel@tonic-gate 				inum = atoi(optarg);
4207c478bd9Sstevel@tonic-gate 				special = argv[optind];
4217c478bd9Sstevel@tonic-gate 				/* Doesn't return */
4227c478bd9Sstevel@tonic-gate 				old_fsdb(inum, special);
4237c478bd9Sstevel@tonic-gate 			} else {
4247c478bd9Sstevel@tonic-gate 				usage(progname);
4257c478bd9Sstevel@tonic-gate 				exit(31+1);
4267c478bd9Sstevel@tonic-gate 			}
4277c478bd9Sstevel@tonic-gate 			/* Should exit() before here */
4287c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
4297c478bd9Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
4307c478bd9Sstevel@tonic-gate 		case 'o':
4317c478bd9Sstevel@tonic-gate 			/* UFS Specific Options */
4327c478bd9Sstevel@tonic-gate 			subopts = optarg;
4337c478bd9Sstevel@tonic-gate 			while (*subopts != '\0') {
4347c478bd9Sstevel@tonic-gate 				switch (getsubopt(&subopts, subopt_v,
4357c478bd9Sstevel@tonic-gate 								&optval)) {
4367c478bd9Sstevel@tonic-gate 				case OVERRIDE:
4377c478bd9Sstevel@tonic-gate 					printf("error checking off\n");
4387c478bd9Sstevel@tonic-gate 					override = 1;
4397c478bd9Sstevel@tonic-gate 					break;
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 				/*
4427c478bd9Sstevel@tonic-gate 				 * Change the "-o prompt=foo" option to
4437c478bd9Sstevel@tonic-gate 				 * "-o p=foo" to match documentation.
4447c478bd9Sstevel@tonic-gate 				 * ALT_PROMPT continues support for the
4457c478bd9Sstevel@tonic-gate 				 * undocumented "-o prompt=foo" option so
4467c478bd9Sstevel@tonic-gate 				 * that we don't break anyone.
4477c478bd9Sstevel@tonic-gate 				 */
4487c478bd9Sstevel@tonic-gate 				case NEW_PROMPT:
4497c478bd9Sstevel@tonic-gate 				case ALT_PROMPT:
4507c478bd9Sstevel@tonic-gate 					if (optval == NULL) {
4517c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
4527c478bd9Sstevel@tonic-gate 							"No prompt string\n");
4537c478bd9Sstevel@tonic-gate 						usage(progname);
4547c478bd9Sstevel@tonic-gate 					}
4557c478bd9Sstevel@tonic-gate 					(void) strncpy(PROMPT, optval,
4567c478bd9Sstevel@tonic-gate 								PROMPTSIZE);
4577c478bd9Sstevel@tonic-gate 					break;
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 				case WRITE_ENABLED:
4607c478bd9Sstevel@tonic-gate 					/* suitable for open */
4617c478bd9Sstevel@tonic-gate 					wrtflag = O_RDWR;
4627c478bd9Sstevel@tonic-gate 					break;
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 				default:
4657c478bd9Sstevel@tonic-gate 					usage(progname);
4667c478bd9Sstevel@tonic-gate 					/* Should exit here */
4677c478bd9Sstevel@tonic-gate 				}
4687c478bd9Sstevel@tonic-gate 			}
4697c478bd9Sstevel@tonic-gate 			break;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		default:
4727c478bd9Sstevel@tonic-gate 			usage(progname);
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 	}
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	if ((argc - optind) != 1) {	/* Should just have "special" left */
4777c478bd9Sstevel@tonic-gate 		usage(progname);
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 	special = argv[optind];
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	/*
4827c478bd9Sstevel@tonic-gate 	 * Unless it's already been set, the default prompt includes the
4837c478bd9Sstevel@tonic-gate 	 * name of the special device.
4847c478bd9Sstevel@tonic-gate 	 */
4857c478bd9Sstevel@tonic-gate 	if (*prompt == NULL)
4867c478bd9Sstevel@tonic-gate 		(void) sprintf(prompt, "%s > ", special);
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	/*
4897c478bd9Sstevel@tonic-gate 	 * Attempt to open the special file.
4907c478bd9Sstevel@tonic-gate 	 */
4917c478bd9Sstevel@tonic-gate 	if ((fd = open(special, wrtflag)) < 0) {
4927c478bd9Sstevel@tonic-gate 		perror(special);
4937c478bd9Sstevel@tonic-gate 		exit(1);
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 	/*
4967c478bd9Sstevel@tonic-gate 	 * Read in the super block and validate (not too picky).
4977c478bd9Sstevel@tonic-gate 	 */
4987c478bd9Sstevel@tonic-gate 	if (llseek(fd, (offset_t)(SBLOCK * DEV_BSIZE), 0) == -1) {
4997c478bd9Sstevel@tonic-gate 		perror(special);
5007c478bd9Sstevel@tonic-gate 		exit(1);
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate #ifdef sun
5047c478bd9Sstevel@tonic-gate 	if (read(fd, &filesystem, SBSIZE) != SBSIZE) {
5057c478bd9Sstevel@tonic-gate 		printf("%s: cannot read superblock\n", special);
5067c478bd9Sstevel@tonic-gate 		exit(1);
5077c478bd9Sstevel@tonic-gate 	}
5087c478bd9Sstevel@tonic-gate #else
5097c478bd9Sstevel@tonic-gate 	if (read(fd, &filesystem, sizeof (filesystem)) != sizeof (filesystem)) {
5107c478bd9Sstevel@tonic-gate 		printf("%s: cannot read superblock\n", special);
5117c478bd9Sstevel@tonic-gate 		exit(1);
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate #endif /* sun */
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	fs = &filesystem;
5167c478bd9Sstevel@tonic-gate 	if ((fs->fs_magic != FS_MAGIC) && (fs->fs_magic != MTB_UFS_MAGIC)) {
5177c478bd9Sstevel@tonic-gate 		if (!override) {
5187c478bd9Sstevel@tonic-gate 			printf("%s: Bad magic number in file system\n",
5197c478bd9Sstevel@tonic-gate 								special);
5207c478bd9Sstevel@tonic-gate 			exit(1);
5217c478bd9Sstevel@tonic-gate 		}
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 		printf("WARNING: Bad magic number in file system. ");
5247c478bd9Sstevel@tonic-gate 		printf("Continue? (y/n): ");
5257c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5267c478bd9Sstevel@tonic-gate 		if (gets(input_buffer) == NULL) {
5277c478bd9Sstevel@tonic-gate 			exit(1);
5287c478bd9Sstevel@tonic-gate 		}
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 		if (*input_buffer != 'y' && *input_buffer != 'Y') {
5317c478bd9Sstevel@tonic-gate 			exit(1);
5327c478bd9Sstevel@tonic-gate 		}
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 
5356451fdbcSvsakar 	if ((fs->fs_magic == FS_MAGIC &&
5366451fdbcSvsakar 	    (fs->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
5376451fdbcSvsakar 	    fs->fs_version != UFS_VERSION_MIN)) ||
5386451fdbcSvsakar 	    (fs->fs_magic == MTB_UFS_MAGIC &&
5397c478bd9Sstevel@tonic-gate 	    (fs->fs_version > MTB_UFS_VERSION_1 ||
5406451fdbcSvsakar 	    fs->fs_version < MTB_UFS_VERSION_MIN))) {
5417c478bd9Sstevel@tonic-gate 		if (!override) {
5427c478bd9Sstevel@tonic-gate 			printf("%s: Unrecognized UFS version number: %d\n",
5437c478bd9Sstevel@tonic-gate 			    special, fs->fs_version);
5447c478bd9Sstevel@tonic-gate 			exit(1);
5457c478bd9Sstevel@tonic-gate 		}
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 		printf("WARNING: Unrecognized UFS version number. ");
5487c478bd9Sstevel@tonic-gate 		printf("Continue? (y/n): ");
5497c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5507c478bd9Sstevel@tonic-gate 		if (gets(input_buffer) == NULL) {
5517c478bd9Sstevel@tonic-gate 			exit(1);
5527c478bd9Sstevel@tonic-gate 		}
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 		if (*input_buffer != 'y' && *input_buffer != 'Y') {
5557c478bd9Sstevel@tonic-gate 			exit(1);
5567c478bd9Sstevel@tonic-gate 		}
5577c478bd9Sstevel@tonic-gate 	}
5587c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
5597c478bd9Sstevel@tonic-gate 	if (fs->fs_postblformat == FS_42POSTBLFMT)
5607c478bd9Sstevel@tonic-gate 		fs->fs_nrpos = 8;
5617c478bd9Sstevel@tonic-gate #endif
5627c478bd9Sstevel@tonic-gate 	printf("fsdb of %s %s -- last mounted on %s\n",
5637c478bd9Sstevel@tonic-gate 		special,
5647c478bd9Sstevel@tonic-gate 		(wrtflag == O_RDWR) ? "(Opened for write)" : "(Read only)",
5657c478bd9Sstevel@tonic-gate 		&fs->fs_fsmnt[0]);
5667c478bd9Sstevel@tonic-gate #ifdef sun
5677c478bd9Sstevel@tonic-gate 	printf("fs_clean is currently set to ");
5687c478bd9Sstevel@tonic-gate 	switch (fs->fs_clean) {
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	case FSACTIVE:
5717c478bd9Sstevel@tonic-gate 		printf("FSACTIVE\n");
5727c478bd9Sstevel@tonic-gate 		break;
5737c478bd9Sstevel@tonic-gate 	case FSCLEAN:
5747c478bd9Sstevel@tonic-gate 		printf("FSCLEAN\n");
5757c478bd9Sstevel@tonic-gate 		break;
5767c478bd9Sstevel@tonic-gate 	case FSSTABLE:
5777c478bd9Sstevel@tonic-gate 		printf("FSSTABLE\n");
5787c478bd9Sstevel@tonic-gate 		break;
5797c478bd9Sstevel@tonic-gate 	case FSBAD:
5807c478bd9Sstevel@tonic-gate 		printf("FSBAD\n");
5817c478bd9Sstevel@tonic-gate 		break;
5827c478bd9Sstevel@tonic-gate 	case FSSUSPEND:
5837c478bd9Sstevel@tonic-gate 		printf("FSSUSPEND\n");
5847c478bd9Sstevel@tonic-gate 		break;
5857c478bd9Sstevel@tonic-gate 	case FSLOG:
5867c478bd9Sstevel@tonic-gate 		printf("FSLOG\n");
5877c478bd9Sstevel@tonic-gate 		break;
5887c478bd9Sstevel@tonic-gate 	case FSFIX:
5897c478bd9Sstevel@tonic-gate 		printf("FSFIX\n");
5907c478bd9Sstevel@tonic-gate 		if (!override) {
5917c478bd9Sstevel@tonic-gate 			printf("%s: fsck may be running on this file system\n",
5927c478bd9Sstevel@tonic-gate 								special);
5937c478bd9Sstevel@tonic-gate 			exit(1);
5947c478bd9Sstevel@tonic-gate 		}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 		printf("WARNING: fsck may be running on this file system. ");
5977c478bd9Sstevel@tonic-gate 		printf("Continue? (y/n): ");
5987c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5997c478bd9Sstevel@tonic-gate 		if (gets(input_buffer) == NULL) {
6007c478bd9Sstevel@tonic-gate 			exit(1);
6017c478bd9Sstevel@tonic-gate 		}
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 		if (*input_buffer != 'y' && *input_buffer != 'Y') {
6047c478bd9Sstevel@tonic-gate 			exit(1);
6057c478bd9Sstevel@tonic-gate 		}
6067c478bd9Sstevel@tonic-gate 		break;
6077c478bd9Sstevel@tonic-gate 	default:
6087c478bd9Sstevel@tonic-gate 		printf("an unknown value (0x%x)\n", fs->fs_clean);
6097c478bd9Sstevel@tonic-gate 		break;
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	if (fs->fs_state == (FSOKAY - fs->fs_time)) {
6137c478bd9Sstevel@tonic-gate 		printf("fs_state consistent (fs_clean CAN be trusted)\n");
6147c478bd9Sstevel@tonic-gate 	} else {
6157c478bd9Sstevel@tonic-gate 		printf("fs_state inconsistent (fs_clean CAN'T trusted)\n");
6167c478bd9Sstevel@tonic-gate 	}
6177c478bd9Sstevel@tonic-gate #endif /* sun */
6187c478bd9Sstevel@tonic-gate 	/*
6197c478bd9Sstevel@tonic-gate 	 * Malloc buffers and set up cache.
6207c478bd9Sstevel@tonic-gate 	 */
6217c478bd9Sstevel@tonic-gate 	buffers = malloc(NBUF * BLKSIZE);
6227c478bd9Sstevel@tonic-gate 	bhdr.fwd = bhdr.back = &bhdr;
6237c478bd9Sstevel@tonic-gate 	for (i = 0; i < NBUF; i++) {
6247c478bd9Sstevel@tonic-gate 		bp = &lbuf[i];
6257c478bd9Sstevel@tonic-gate 		bp->blkaddr = buffers + (i * BLKSIZE);
6267c478bd9Sstevel@tonic-gate 		bp->valid = 0;
6277c478bd9Sstevel@tonic-gate 		insert(bp);
6287c478bd9Sstevel@tonic-gate 	}
6297c478bd9Sstevel@tonic-gate 	/*
6307c478bd9Sstevel@tonic-gate 	 * Malloc filenames structure.  The space for the actual filenames
6317c478bd9Sstevel@tonic-gate 	 * is allocated as it needs it. We estimate the size based on the
6327c478bd9Sstevel@tonic-gate 	 * number of inodes(objects) in the filesystem and the number of
6337c478bd9Sstevel@tonic-gate 	 * directories.  The number of directories are padded by 3 because
6347c478bd9Sstevel@tonic-gate 	 * each directory traversed during a "find" or "ls -R" needs 3
6357c478bd9Sstevel@tonic-gate 	 * entries.
6367c478bd9Sstevel@tonic-gate 	 */
6377c478bd9Sstevel@tonic-gate 	maxfiles = (long)((((u_offset_t)fs->fs_ncg * (u_offset_t)fs->fs_ipg) -
6387c478bd9Sstevel@tonic-gate 	    (u_offset_t)fs->fs_cstotal.cs_nifree) +
6397c478bd9Sstevel@tonic-gate 	    ((u_offset_t)fs->fs_cstotal.cs_ndir * (u_offset_t)3));
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	filenames = (struct filenames *)calloc(maxfiles,
6427c478bd9Sstevel@tonic-gate 	    sizeof (struct filenames));
6437c478bd9Sstevel@tonic-gate 	if (filenames == NULL) {
6447c478bd9Sstevel@tonic-gate 		/*
6457c478bd9Sstevel@tonic-gate 		 * If we could not allocate memory for all of files
6467c478bd9Sstevel@tonic-gate 		 * in the filesystem then, back off to the old fixed
6477c478bd9Sstevel@tonic-gate 		 * value.
6487c478bd9Sstevel@tonic-gate 		 */
6497c478bd9Sstevel@tonic-gate 		maxfiles = MAXFILES;
6507c478bd9Sstevel@tonic-gate 		filenames = (struct filenames *)calloc(maxfiles,
6517c478bd9Sstevel@tonic-gate 		    sizeof (struct filenames));
6527c478bd9Sstevel@tonic-gate 		if (filenames == NULL) {
6537c478bd9Sstevel@tonic-gate 			printf("out of memory\n");
6547c478bd9Sstevel@tonic-gate 			exit(1);
6557c478bd9Sstevel@tonic-gate 		}
6567c478bd9Sstevel@tonic-gate 	}
6577c478bd9Sstevel@tonic-gate 
6587c478bd9Sstevel@tonic-gate 	restore_inode(2);
6597c478bd9Sstevel@tonic-gate 	/*
6607c478bd9Sstevel@tonic-gate 	 * Malloc a few filenames (needed by pwd for example).
6617c478bd9Sstevel@tonic-gate 	 */
6627c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAXPATHLEN; i++) {
6637c478bd9Sstevel@tonic-gate 		input_path[i] = calloc(1, MAXNAMLEN);
6647c478bd9Sstevel@tonic-gate 		stack_path[i] = calloc(1, MAXNAMLEN);
6657c478bd9Sstevel@tonic-gate 		current_path[i] = calloc(1, MAXNAMLEN);
6667c478bd9Sstevel@tonic-gate 		if (current_path[i] == NULL) {
6677c478bd9Sstevel@tonic-gate 			printf("out of memory\n");
6687c478bd9Sstevel@tonic-gate 			exit(1);
6697c478bd9Sstevel@tonic-gate 		}
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate 	current_pathp = -1;
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	(void) signal(2, err);
6747c478bd9Sstevel@tonic-gate 	(void) setjmp(env);
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	getnextinput();
6777c478bd9Sstevel@tonic-gate 	/*
6787c478bd9Sstevel@tonic-gate 	 * Main loop and case statement.  If an error condition occurs
6797c478bd9Sstevel@tonic-gate 	 * initialization and recovery is attempted.
6807c478bd9Sstevel@tonic-gate 	 */
6817c478bd9Sstevel@tonic-gate 	for (;;) {
6827c478bd9Sstevel@tonic-gate 		if (error) {
6837c478bd9Sstevel@tonic-gate 			freemem(filenames, nfiles);
6847c478bd9Sstevel@tonic-gate 			nfiles = 0;
6857c478bd9Sstevel@tonic-gate 			c_count = 0;
6867c478bd9Sstevel@tonic-gate 			count = 1;
6877c478bd9Sstevel@tonic-gate 			star = 0;
6887c478bd9Sstevel@tonic-gate 			error = 0;
6897c478bd9Sstevel@tonic-gate 			paren = 0;
6907c478bd9Sstevel@tonic-gate 			acting_on_inode = 0;
6917c478bd9Sstevel@tonic-gate 			acting_on_directory = 0;
6927c478bd9Sstevel@tonic-gate 			should_print = 1;
6937c478bd9Sstevel@tonic-gate 			addr = erraddr;
6947c478bd9Sstevel@tonic-gate 			cur_ino = errino;
6957c478bd9Sstevel@tonic-gate 			cur_inum = errinum;
6967c478bd9Sstevel@tonic-gate 			cur_bytes = errcur_bytes;
6977c478bd9Sstevel@tonic-gate 			printf("?\n");
6987c478bd9Sstevel@tonic-gate 			getnextinput();
6997c478bd9Sstevel@tonic-gate 			if (error)
7007c478bd9Sstevel@tonic-gate 				continue;
7017c478bd9Sstevel@tonic-gate 		}
7027c478bd9Sstevel@tonic-gate 		c_count++;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 		switch (c = getachar()) {
7057c478bd9Sstevel@tonic-gate 
7067c478bd9Sstevel@tonic-gate 		case '\n': /* command end */
7077c478bd9Sstevel@tonic-gate 			freemem(filenames, nfiles);
7087c478bd9Sstevel@tonic-gate 			nfiles = 0;
7097c478bd9Sstevel@tonic-gate 			if (should_print && laststyle == '=') {
7107c478bd9Sstevel@tonic-gate 				ungetachar(c);
7117c478bd9Sstevel@tonic-gate 				goto calc;
7127c478bd9Sstevel@tonic-gate 			}
7137c478bd9Sstevel@tonic-gate 			if (c_count == 1) {
7147c478bd9Sstevel@tonic-gate 				clear = 0;
7157c478bd9Sstevel@tonic-gate 				should_print = 1;
7167c478bd9Sstevel@tonic-gate 				erraddr = addr;
7177c478bd9Sstevel@tonic-gate 				errino = cur_ino;
7187c478bd9Sstevel@tonic-gate 				errinum = cur_inum;
7197c478bd9Sstevel@tonic-gate 				errcur_bytes = cur_bytes;
7207c478bd9Sstevel@tonic-gate 				switch (objsz) {
7217c478bd9Sstevel@tonic-gate 				case DIRECTORY:
7227c478bd9Sstevel@tonic-gate 					if ((addr = getdirslot(
7237c478bd9Sstevel@tonic-gate 							(long)dirslot+1)) == 0)
7247c478bd9Sstevel@tonic-gate 						should_print = 0;
7257c478bd9Sstevel@tonic-gate 					if (error) {
7267c478bd9Sstevel@tonic-gate 						ungetachar(c);
7277c478bd9Sstevel@tonic-gate 						continue;
7287c478bd9Sstevel@tonic-gate 					}
7297c478bd9Sstevel@tonic-gate 					break;
7307c478bd9Sstevel@tonic-gate 				case INODE:
7317c478bd9Sstevel@tonic-gate 					cur_inum++;
7327c478bd9Sstevel@tonic-gate 					addr = itob(cur_inum);
7337c478bd9Sstevel@tonic-gate 					if (!icheck(addr)) {
7347c478bd9Sstevel@tonic-gate 						cur_inum--;
7357c478bd9Sstevel@tonic-gate 						should_print = 0;
7367c478bd9Sstevel@tonic-gate 					}
7377c478bd9Sstevel@tonic-gate 					break;
7387c478bd9Sstevel@tonic-gate 				case CGRP:
7397c478bd9Sstevel@tonic-gate 				case SB:
7407c478bd9Sstevel@tonic-gate 					cur_cgrp++;
7417c478bd9Sstevel@tonic-gate 					addr = cgrp_check(cur_cgrp);
7427c478bd9Sstevel@tonic-gate 					if (addr == 0) {
7437c478bd9Sstevel@tonic-gate 						cur_cgrp--;
7447c478bd9Sstevel@tonic-gate 						continue;
7457c478bd9Sstevel@tonic-gate 					}
7467c478bd9Sstevel@tonic-gate 					break;
7477c478bd9Sstevel@tonic-gate 				case SHADOW_DATA:
7487c478bd9Sstevel@tonic-gate 					if ((addr = getshadowslot(
7497c478bd9Sstevel@tonic-gate 					    (long)cur_shad + 1)) == 0)
7507c478bd9Sstevel@tonic-gate 						should_print = 0;
7517c478bd9Sstevel@tonic-gate 					if (error) {
7527c478bd9Sstevel@tonic-gate 						ungetachar(c);
7537c478bd9Sstevel@tonic-gate 						continue;
7547c478bd9Sstevel@tonic-gate 					}
7557c478bd9Sstevel@tonic-gate 					break;
7567c478bd9Sstevel@tonic-gate 				default:
7577c478bd9Sstevel@tonic-gate 					addr += objsz;
7587c478bd9Sstevel@tonic-gate 					cur_bytes += objsz;
7597c478bd9Sstevel@tonic-gate 					if (valid_addr() == 0)
7607c478bd9Sstevel@tonic-gate 						continue;
7617c478bd9Sstevel@tonic-gate 				}
7627c478bd9Sstevel@tonic-gate 			}
7637c478bd9Sstevel@tonic-gate 			if (type == NUMB)
7647c478bd9Sstevel@tonic-gate 				trapped = 0;
7657c478bd9Sstevel@tonic-gate 			if (should_print)
7667c478bd9Sstevel@tonic-gate 				switch (objsz) {
7677c478bd9Sstevel@tonic-gate 				case DIRECTORY:
7687c478bd9Sstevel@tonic-gate 					fprnt('?', 'd');
7697c478bd9Sstevel@tonic-gate 					break;
7707c478bd9Sstevel@tonic-gate 				case INODE:
7717c478bd9Sstevel@tonic-gate 					fprnt('?', 'i');
7727c478bd9Sstevel@tonic-gate 					if (!error)
7737c478bd9Sstevel@tonic-gate 						cur_ino = addr;
7747c478bd9Sstevel@tonic-gate 					break;
7757c478bd9Sstevel@tonic-gate 				case CGRP:
7767c478bd9Sstevel@tonic-gate 					fprnt('?', 'c');
7777c478bd9Sstevel@tonic-gate 					break;
7787c478bd9Sstevel@tonic-gate 				case SB:
7797c478bd9Sstevel@tonic-gate 					fprnt('?', 's');
7807c478bd9Sstevel@tonic-gate 					break;
7817c478bd9Sstevel@tonic-gate 				case SHADOW_DATA:
7827c478bd9Sstevel@tonic-gate 					fprnt('?', 'S');
7837c478bd9Sstevel@tonic-gate 					break;
7847c478bd9Sstevel@tonic-gate 				case CHAR:
7857c478bd9Sstevel@tonic-gate 				case SHORT:
7867c478bd9Sstevel@tonic-gate 				case LONG:
7877c478bd9Sstevel@tonic-gate 					fprnt(laststyle, lastpo);
7887c478bd9Sstevel@tonic-gate 				}
7897c478bd9Sstevel@tonic-gate 			if (error) {
7907c478bd9Sstevel@tonic-gate 				ungetachar(c);
7917c478bd9Sstevel@tonic-gate 				continue;
7927c478bd9Sstevel@tonic-gate 			}
7937c478bd9Sstevel@tonic-gate 			c_count = colon = acting_on_inode = 0;
7947c478bd9Sstevel@tonic-gate 			acting_on_directory = 0;
7957c478bd9Sstevel@tonic-gate 			should_print = 1;
7967c478bd9Sstevel@tonic-gate 			getnextinput();
7977c478bd9Sstevel@tonic-gate 			if (error)
7987c478bd9Sstevel@tonic-gate 				continue;
7997c478bd9Sstevel@tonic-gate 			erraddr = addr;
8007c478bd9Sstevel@tonic-gate 			errino = cur_ino;
8017c478bd9Sstevel@tonic-gate 			errinum = cur_inum;
8027c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
8037c478bd9Sstevel@tonic-gate 			continue;
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate 		case '(': /* numeric expression or unknown command */
8067c478bd9Sstevel@tonic-gate 		default:
8077c478bd9Sstevel@tonic-gate 			colon = 0;
8087c478bd9Sstevel@tonic-gate 			if (digit(c) || c == '(') {
8097c478bd9Sstevel@tonic-gate 				ungetachar(c);
8107c478bd9Sstevel@tonic-gate 				addr = expr();
8117c478bd9Sstevel@tonic-gate 				type = NUMB;
8127c478bd9Sstevel@tonic-gate 				value = addr;
8137c478bd9Sstevel@tonic-gate 				continue;
8147c478bd9Sstevel@tonic-gate 			}
8157c478bd9Sstevel@tonic-gate 			printf("unknown command or bad syntax\n");
8167c478bd9Sstevel@tonic-gate 			error++;
8177c478bd9Sstevel@tonic-gate 			continue;
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 		case '?': /* general print facilities */
8207c478bd9Sstevel@tonic-gate 		case '/':
8217c478bd9Sstevel@tonic-gate 			fprnt(c, getachar());
8227c478bd9Sstevel@tonic-gate 			continue;
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 		case ';': /* command separator and . */
8257c478bd9Sstevel@tonic-gate 		case '\t':
8267c478bd9Sstevel@tonic-gate 		case ' ':
8277c478bd9Sstevel@tonic-gate 		case '.':
8287c478bd9Sstevel@tonic-gate 			continue;
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 		case ':': /* command indicator */
8317c478bd9Sstevel@tonic-gate 			colon++;
8327c478bd9Sstevel@tonic-gate 			commands++;
8337c478bd9Sstevel@tonic-gate 			should_print = 0;
8347c478bd9Sstevel@tonic-gate 			stringsize = 0;
8357c478bd9Sstevel@tonic-gate 			trapped = 0;
8367c478bd9Sstevel@tonic-gate 			continue;
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 		case ',': /* count indicator */
8397c478bd9Sstevel@tonic-gate 			colon = star = 0;
8407c478bd9Sstevel@tonic-gate 			if ((c = getachar()) == '*') {
8417c478bd9Sstevel@tonic-gate 				star = 1;
8427c478bd9Sstevel@tonic-gate 				count = BLKSIZE;
8437c478bd9Sstevel@tonic-gate 			} else {
8447c478bd9Sstevel@tonic-gate 				ungetachar(c);
8457c478bd9Sstevel@tonic-gate 				count = expr();
8467c478bd9Sstevel@tonic-gate 				if (error)
8477c478bd9Sstevel@tonic-gate 					continue;
8487c478bd9Sstevel@tonic-gate 				if (!count)
8497c478bd9Sstevel@tonic-gate 					count = 1;
8507c478bd9Sstevel@tonic-gate 			}
8517c478bd9Sstevel@tonic-gate 			clear = 0;
8527c478bd9Sstevel@tonic-gate 			continue;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 		case '+': /* address addition */
8557c478bd9Sstevel@tonic-gate 			colon = 0;
8567c478bd9Sstevel@tonic-gate 			c = getachar();
8577c478bd9Sstevel@tonic-gate 			ungetachar(c);
8587c478bd9Sstevel@tonic-gate 			if (c == '\n')
8597c478bd9Sstevel@tonic-gate 				temp = 1;
8607c478bd9Sstevel@tonic-gate 			else {
8617c478bd9Sstevel@tonic-gate 				temp = expr();
8627c478bd9Sstevel@tonic-gate 				if (error)
8637c478bd9Sstevel@tonic-gate 					continue;
8647c478bd9Sstevel@tonic-gate 			}
8657c478bd9Sstevel@tonic-gate 			erraddr = addr;
8667c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
8677c478bd9Sstevel@tonic-gate 			switch (objsz) {
8687c478bd9Sstevel@tonic-gate 			case DIRECTORY:
8697c478bd9Sstevel@tonic-gate 				addr = getdirslot((long)(dirslot + temp));
8707c478bd9Sstevel@tonic-gate 				if (error)
8717c478bd9Sstevel@tonic-gate 					continue;
8727c478bd9Sstevel@tonic-gate 				break;
8737c478bd9Sstevel@tonic-gate 			case INODE:
8747c478bd9Sstevel@tonic-gate 				cur_inum += temp;
8757c478bd9Sstevel@tonic-gate 				addr = itob(cur_inum);
8767c478bd9Sstevel@tonic-gate 				if (!icheck(addr)) {
8777c478bd9Sstevel@tonic-gate 					cur_inum -= temp;
8787c478bd9Sstevel@tonic-gate 					continue;
8797c478bd9Sstevel@tonic-gate 				}
8807c478bd9Sstevel@tonic-gate 				break;
8817c478bd9Sstevel@tonic-gate 			case CGRP:
8827c478bd9Sstevel@tonic-gate 			case SB:
8837c478bd9Sstevel@tonic-gate 				cur_cgrp += temp;
8847c478bd9Sstevel@tonic-gate 				if ((addr = cgrp_check(cur_cgrp)) == 0) {
8857c478bd9Sstevel@tonic-gate 					cur_cgrp -= temp;
8867c478bd9Sstevel@tonic-gate 					continue;
8877c478bd9Sstevel@tonic-gate 				}
8887c478bd9Sstevel@tonic-gate 				break;
8897c478bd9Sstevel@tonic-gate 			case SHADOW_DATA:
8907c478bd9Sstevel@tonic-gate 				addr = getshadowslot((long)(cur_shad + temp));
8917c478bd9Sstevel@tonic-gate 				if (error)
8927c478bd9Sstevel@tonic-gate 				    continue;
8937c478bd9Sstevel@tonic-gate 				break;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 			default:
8967c478bd9Sstevel@tonic-gate 				laststyle = '/';
8977c478bd9Sstevel@tonic-gate 				addr += temp * objsz;
8987c478bd9Sstevel@tonic-gate 				cur_bytes += temp * objsz;
8997c478bd9Sstevel@tonic-gate 				if (valid_addr() == 0)
9007c478bd9Sstevel@tonic-gate 					continue;
9017c478bd9Sstevel@tonic-gate 			}
9027c478bd9Sstevel@tonic-gate 			value = get(objsz);
9037c478bd9Sstevel@tonic-gate 			continue;
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 		case '-': /* address subtraction */
9067c478bd9Sstevel@tonic-gate 			colon = 0;
9077c478bd9Sstevel@tonic-gate 			c = getachar();
9087c478bd9Sstevel@tonic-gate 			ungetachar(c);
9097c478bd9Sstevel@tonic-gate 			if (c == '\n')
9107c478bd9Sstevel@tonic-gate 				temp = 1;
9117c478bd9Sstevel@tonic-gate 			else {
9127c478bd9Sstevel@tonic-gate 				temp = expr();
9137c478bd9Sstevel@tonic-gate 				if (error)
9147c478bd9Sstevel@tonic-gate 					continue;
9157c478bd9Sstevel@tonic-gate 			}
9167c478bd9Sstevel@tonic-gate 			erraddr = addr;
9177c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
9187c478bd9Sstevel@tonic-gate 			switch (objsz) {
9197c478bd9Sstevel@tonic-gate 			case DIRECTORY:
9207c478bd9Sstevel@tonic-gate 				addr = getdirslot((long)(dirslot - temp));
9217c478bd9Sstevel@tonic-gate 				if (error)
9227c478bd9Sstevel@tonic-gate 					continue;
9237c478bd9Sstevel@tonic-gate 				break;
9247c478bd9Sstevel@tonic-gate 			case INODE:
9257c478bd9Sstevel@tonic-gate 				cur_inum -= temp;
9267c478bd9Sstevel@tonic-gate 				addr = itob(cur_inum);
9277c478bd9Sstevel@tonic-gate 				if (!icheck(addr)) {
9287c478bd9Sstevel@tonic-gate 					cur_inum += temp;
9297c478bd9Sstevel@tonic-gate 					continue;
9307c478bd9Sstevel@tonic-gate 				}
9317c478bd9Sstevel@tonic-gate 				break;
9327c478bd9Sstevel@tonic-gate 			case CGRP:
9337c478bd9Sstevel@tonic-gate 			case SB:
9347c478bd9Sstevel@tonic-gate 				cur_cgrp -= temp;
9357c478bd9Sstevel@tonic-gate 				if ((addr = cgrp_check(cur_cgrp)) == 0) {
9367c478bd9Sstevel@tonic-gate 					cur_cgrp += temp;
9377c478bd9Sstevel@tonic-gate 					continue;
9387c478bd9Sstevel@tonic-gate 				}
9397c478bd9Sstevel@tonic-gate 				break;
9407c478bd9Sstevel@tonic-gate 			case SHADOW_DATA:
9417c478bd9Sstevel@tonic-gate 				addr = getshadowslot((long)(cur_shad - temp));
9427c478bd9Sstevel@tonic-gate 				if (error)
9437c478bd9Sstevel@tonic-gate 					continue;
9447c478bd9Sstevel@tonic-gate 				break;
9457c478bd9Sstevel@tonic-gate 			default:
9467c478bd9Sstevel@tonic-gate 				laststyle = '/';
9477c478bd9Sstevel@tonic-gate 				addr -= temp * objsz;
9487c478bd9Sstevel@tonic-gate 				cur_bytes -= temp * objsz;
9497c478bd9Sstevel@tonic-gate 				if (valid_addr() == 0)
9507c478bd9Sstevel@tonic-gate 					continue;
9517c478bd9Sstevel@tonic-gate 			}
9527c478bd9Sstevel@tonic-gate 			value = get(objsz);
9537c478bd9Sstevel@tonic-gate 			continue;
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 		case '*': /* address multiplication */
9567c478bd9Sstevel@tonic-gate 			colon = 0;
9577c478bd9Sstevel@tonic-gate 			temp = expr();
9587c478bd9Sstevel@tonic-gate 			if (error)
9597c478bd9Sstevel@tonic-gate 				continue;
9607c478bd9Sstevel@tonic-gate 			if (objsz != INODE && objsz != DIRECTORY)
9617c478bd9Sstevel@tonic-gate 				laststyle = '/';
9627c478bd9Sstevel@tonic-gate 			addr *= temp;
9637c478bd9Sstevel@tonic-gate 			value = get(objsz);
9647c478bd9Sstevel@tonic-gate 			continue;
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 		case '%': /* address division */
9677c478bd9Sstevel@tonic-gate 			colon = 0;
9687c478bd9Sstevel@tonic-gate 			temp = expr();
9697c478bd9Sstevel@tonic-gate 			if (error)
9707c478bd9Sstevel@tonic-gate 				continue;
9717c478bd9Sstevel@tonic-gate 			if (!temp) {
9727c478bd9Sstevel@tonic-gate 				printf("divide by zero\n");
9737c478bd9Sstevel@tonic-gate 				error++;
9747c478bd9Sstevel@tonic-gate 				continue;
9757c478bd9Sstevel@tonic-gate 			}
9767c478bd9Sstevel@tonic-gate 			if (objsz != INODE && objsz != DIRECTORY)
9777c478bd9Sstevel@tonic-gate 				laststyle = '/';
9787c478bd9Sstevel@tonic-gate 			addr /= temp;
9797c478bd9Sstevel@tonic-gate 			value = get(objsz);
9807c478bd9Sstevel@tonic-gate 			continue;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 		case '=': { /* assignment operation */
9837c478bd9Sstevel@tonic-gate 			short tbase;
9847c478bd9Sstevel@tonic-gate calc:
9857c478bd9Sstevel@tonic-gate 			tbase = base;
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 			c = getachar();
9887c478bd9Sstevel@tonic-gate 			if (c == '\n') {
9897c478bd9Sstevel@tonic-gate 				ungetachar(c);
9907c478bd9Sstevel@tonic-gate 				c = lastpo;
9917c478bd9Sstevel@tonic-gate 				if (acting_on_inode == 1) {
9927c478bd9Sstevel@tonic-gate 					if (c != 'o' && c != 'd' && c != 'x' &&
9937c478bd9Sstevel@tonic-gate 					    c != 'O' && c != 'D' && c != 'X') {
9947c478bd9Sstevel@tonic-gate 						switch (objsz) {
9957c478bd9Sstevel@tonic-gate 						case LONG:
9967c478bd9Sstevel@tonic-gate 							c = lastpo = 'X';
9977c478bd9Sstevel@tonic-gate 							break;
9987c478bd9Sstevel@tonic-gate 						case SHORT:
9997c478bd9Sstevel@tonic-gate 							c = lastpo = 'x';
10007c478bd9Sstevel@tonic-gate 							break;
10017c478bd9Sstevel@tonic-gate 						case CHAR:
10027c478bd9Sstevel@tonic-gate 							c = lastpo = 'c';
10037c478bd9Sstevel@tonic-gate 						}
10047c478bd9Sstevel@tonic-gate 					}
10057c478bd9Sstevel@tonic-gate 				} else {
10067c478bd9Sstevel@tonic-gate 					if (acting_on_inode == 2)
10077c478bd9Sstevel@tonic-gate 						c = lastpo = 't';
10087c478bd9Sstevel@tonic-gate 				}
10097c478bd9Sstevel@tonic-gate 			} else if (acting_on_inode)
10107c478bd9Sstevel@tonic-gate 				lastpo = c;
10117c478bd9Sstevel@tonic-gate 			should_print = star = 0;
10127c478bd9Sstevel@tonic-gate 			count = 1;
10137c478bd9Sstevel@tonic-gate 			erraddr = addr;
10147c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
10157c478bd9Sstevel@tonic-gate 			switch (c) {
10167c478bd9Sstevel@tonic-gate 			case '"': /* character string */
10177c478bd9Sstevel@tonic-gate 				if (type == NUMB) {
10187c478bd9Sstevel@tonic-gate 					blocksize = BLKSIZE;
10197c478bd9Sstevel@tonic-gate 					filesize = BLKSIZE * 2;
10207c478bd9Sstevel@tonic-gate 					cur_bytes = blkoff(fs, addr);
10217c478bd9Sstevel@tonic-gate 					if (objsz == DIRECTORY ||
10227c478bd9Sstevel@tonic-gate 								objsz == INODE)
10237c478bd9Sstevel@tonic-gate 						lastpo = 'X';
10247c478bd9Sstevel@tonic-gate 				}
10257c478bd9Sstevel@tonic-gate 				puta();
10267c478bd9Sstevel@tonic-gate 				continue;
10277c478bd9Sstevel@tonic-gate 			case '+': /* =+ operator */
10287c478bd9Sstevel@tonic-gate 				temp = expr();
10297c478bd9Sstevel@tonic-gate 				value = get(objsz);
10307c478bd9Sstevel@tonic-gate 				if (!error)
10317c478bd9Sstevel@tonic-gate 					put(value+temp, objsz);
10327c478bd9Sstevel@tonic-gate 				continue;
10337c478bd9Sstevel@tonic-gate 			case '-': /* =- operator */
10347c478bd9Sstevel@tonic-gate 				temp = expr();
10357c478bd9Sstevel@tonic-gate 				value = get(objsz);
10367c478bd9Sstevel@tonic-gate 				if (!error)
10377c478bd9Sstevel@tonic-gate 					put(value-temp, objsz);
10387c478bd9Sstevel@tonic-gate 				continue;
10397c478bd9Sstevel@tonic-gate 			case 'b':
10407c478bd9Sstevel@tonic-gate 			case 'c':
10417c478bd9Sstevel@tonic-gate 				if (objsz == CGRP)
10427c478bd9Sstevel@tonic-gate 					fprnt('?', c);
10437c478bd9Sstevel@tonic-gate 				else
10447c478bd9Sstevel@tonic-gate 					fprnt('/', c);
10457c478bd9Sstevel@tonic-gate 				continue;
10467c478bd9Sstevel@tonic-gate 			case 'i':
10477c478bd9Sstevel@tonic-gate 				addr = cur_ino;
10487c478bd9Sstevel@tonic-gate 				fprnt('?', 'i');
10497c478bd9Sstevel@tonic-gate 				continue;
10507c478bd9Sstevel@tonic-gate 			case 's':
10517c478bd9Sstevel@tonic-gate 				fprnt('?', 's');
10527c478bd9Sstevel@tonic-gate 				continue;
10537c478bd9Sstevel@tonic-gate 			case 't':
10547c478bd9Sstevel@tonic-gate 			case 'T':
10557c478bd9Sstevel@tonic-gate 				laststyle = '=';
10567c478bd9Sstevel@tonic-gate 				printf("\t\t");
10577c478bd9Sstevel@tonic-gate 				{
10587c478bd9Sstevel@tonic-gate 					/*
10597c478bd9Sstevel@tonic-gate 					 * Truncation is intentional so
10607c478bd9Sstevel@tonic-gate 					 * ctime is happy.
10617c478bd9Sstevel@tonic-gate 					 */
10627c478bd9Sstevel@tonic-gate 					time_t tvalue = (time_t)value;
10637c478bd9Sstevel@tonic-gate 					printf("%s", ctime(&tvalue));
10647c478bd9Sstevel@tonic-gate 				}
10657c478bd9Sstevel@tonic-gate 				continue;
10667c478bd9Sstevel@tonic-gate 			case 'o':
10677c478bd9Sstevel@tonic-gate 				base = OCTAL;
10687c478bd9Sstevel@tonic-gate 				goto otx;
10697c478bd9Sstevel@tonic-gate 			case 'd':
10707c478bd9Sstevel@tonic-gate 				if (objsz == DIRECTORY) {
10717c478bd9Sstevel@tonic-gate 					addr = cur_dir;
10727c478bd9Sstevel@tonic-gate 					fprnt('?', 'd');
10737c478bd9Sstevel@tonic-gate 					continue;
10747c478bd9Sstevel@tonic-gate 				}
10757c478bd9Sstevel@tonic-gate 				base = DECIMAL;
10767c478bd9Sstevel@tonic-gate 				goto otx;
10777c478bd9Sstevel@tonic-gate 			case 'x':
10787c478bd9Sstevel@tonic-gate 				base = HEX;
10797c478bd9Sstevel@tonic-gate otx:
10807c478bd9Sstevel@tonic-gate 				laststyle = '=';
10817c478bd9Sstevel@tonic-gate 				printf("\t\t");
10827c478bd9Sstevel@tonic-gate 				if (acting_on_inode)
10837c478bd9Sstevel@tonic-gate 					print(value & 0177777L, 12, -8, 0);
10847c478bd9Sstevel@tonic-gate 				else
10857c478bd9Sstevel@tonic-gate 					print(addr & 0177777L, 12, -8, 0);
10867c478bd9Sstevel@tonic-gate 				printf("\n");
10877c478bd9Sstevel@tonic-gate 				base = tbase;
10887c478bd9Sstevel@tonic-gate 				continue;
10897c478bd9Sstevel@tonic-gate 			case 'O':
10907c478bd9Sstevel@tonic-gate 				base = OCTAL;
10917c478bd9Sstevel@tonic-gate 				goto OTX;
10927c478bd9Sstevel@tonic-gate 			case 'D':
10937c478bd9Sstevel@tonic-gate 				base = DECIMAL;
10947c478bd9Sstevel@tonic-gate 				goto OTX;
10957c478bd9Sstevel@tonic-gate 			case 'X':
10967c478bd9Sstevel@tonic-gate 				base = HEX;
10977c478bd9Sstevel@tonic-gate OTX:
10987c478bd9Sstevel@tonic-gate 				laststyle = '=';
10997c478bd9Sstevel@tonic-gate 				printf("\t\t");
11007c478bd9Sstevel@tonic-gate 				if (acting_on_inode)
11017c478bd9Sstevel@tonic-gate 					print(value, 12, -8, 0);
11027c478bd9Sstevel@tonic-gate 				else
11037c478bd9Sstevel@tonic-gate 					print(addr, 12, -8, 0);
11047c478bd9Sstevel@tonic-gate 				printf("\n");
11057c478bd9Sstevel@tonic-gate 				base = tbase;
11067c478bd9Sstevel@tonic-gate 				continue;
11077c478bd9Sstevel@tonic-gate 			default: /* regular assignment */
11087c478bd9Sstevel@tonic-gate 				ungetachar(c);
11097c478bd9Sstevel@tonic-gate 				value = expr();
11107c478bd9Sstevel@tonic-gate 				if (error)
11117c478bd9Sstevel@tonic-gate 					printf("syntax error\n");
11127c478bd9Sstevel@tonic-gate 				else
11137c478bd9Sstevel@tonic-gate 					put(value, objsz);
11147c478bd9Sstevel@tonic-gate 				continue;
11157c478bd9Sstevel@tonic-gate 			}
11167c478bd9Sstevel@tonic-gate 		}
11177c478bd9Sstevel@tonic-gate 
11187c478bd9Sstevel@tonic-gate 		case '>': /* save current address */
11197c478bd9Sstevel@tonic-gate 			colon = 0;
11207c478bd9Sstevel@tonic-gate 			should_print = 0;
11217c478bd9Sstevel@tonic-gate 			c = getachar();
11227c478bd9Sstevel@tonic-gate 			if (!letter(c) && !digit(c)) {
11237c478bd9Sstevel@tonic-gate 				printf("invalid register specification, ");
11247c478bd9Sstevel@tonic-gate 				printf("must be letter or digit\n");
11257c478bd9Sstevel@tonic-gate 				error++;
11267c478bd9Sstevel@tonic-gate 				continue;
11277c478bd9Sstevel@tonic-gate 			}
11287c478bd9Sstevel@tonic-gate 			if (letter(c)) {
11297c478bd9Sstevel@tonic-gate 				if (c < 'a')
11307c478bd9Sstevel@tonic-gate 					c = uppertolower(c);
11317c478bd9Sstevel@tonic-gate 				c = hextodigit(c);
11327c478bd9Sstevel@tonic-gate 			} else
11337c478bd9Sstevel@tonic-gate 				c = numtodigit(c);
11347c478bd9Sstevel@tonic-gate 			regs[c].sv_addr = addr;
11357c478bd9Sstevel@tonic-gate 			regs[c].sv_value = value;
11367c478bd9Sstevel@tonic-gate 			regs[c].sv_objsz = objsz;
11377c478bd9Sstevel@tonic-gate 			continue;
11387c478bd9Sstevel@tonic-gate 
11397c478bd9Sstevel@tonic-gate 		case '<': /* restore saved address */
11407c478bd9Sstevel@tonic-gate 			colon = 0;
11417c478bd9Sstevel@tonic-gate 			should_print = 0;
11427c478bd9Sstevel@tonic-gate 			c = getachar();
11437c478bd9Sstevel@tonic-gate 			if (!letter(c) && !digit(c)) {
11447c478bd9Sstevel@tonic-gate 				printf("invalid register specification, ");
11457c478bd9Sstevel@tonic-gate 				printf("must be letter or digit\n");
11467c478bd9Sstevel@tonic-gate 				error++;
11477c478bd9Sstevel@tonic-gate 				continue;
11487c478bd9Sstevel@tonic-gate 			}
11497c478bd9Sstevel@tonic-gate 			if (letter(c)) {
11507c478bd9Sstevel@tonic-gate 				if (c < 'a')
11517c478bd9Sstevel@tonic-gate 					c = uppertolower(c);
11527c478bd9Sstevel@tonic-gate 				c = hextodigit(c);
11537c478bd9Sstevel@tonic-gate 			} else
11547c478bd9Sstevel@tonic-gate 				c = numtodigit(c);
11557c478bd9Sstevel@tonic-gate 			addr = regs[c].sv_addr;
11567c478bd9Sstevel@tonic-gate 			value = regs[c].sv_value;
11577c478bd9Sstevel@tonic-gate 			objsz = regs[c].sv_objsz;
11587c478bd9Sstevel@tonic-gate 			continue;
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 		case 'a':
11617c478bd9Sstevel@tonic-gate 			if (colon)
11627c478bd9Sstevel@tonic-gate 				colon = 0;
11637c478bd9Sstevel@tonic-gate 			else
11647c478bd9Sstevel@tonic-gate 				goto no_colon;
11657c478bd9Sstevel@tonic-gate 			if (match("at", 2)) { 		/* access time */
11667c478bd9Sstevel@tonic-gate 				acting_on_inode = 2;
11677c478bd9Sstevel@tonic-gate 				should_print = 1;
1168d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1169d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_atime;
11707c478bd9Sstevel@tonic-gate 				value = get(LONG);
11717c478bd9Sstevel@tonic-gate 				type = NULL;
11727c478bd9Sstevel@tonic-gate 				continue;
11737c478bd9Sstevel@tonic-gate 			}
11747c478bd9Sstevel@tonic-gate 			goto bad_syntax;
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 		case 'b':
11777c478bd9Sstevel@tonic-gate 			if (colon)
11787c478bd9Sstevel@tonic-gate 				colon = 0;
11797c478bd9Sstevel@tonic-gate 			else
11807c478bd9Sstevel@tonic-gate 				goto no_colon;
11817c478bd9Sstevel@tonic-gate 			if (match("block", 2)) { 	/* block conversion */
11827c478bd9Sstevel@tonic-gate 				if (type == NUMB) {
11837c478bd9Sstevel@tonic-gate 					value = addr;
11847c478bd9Sstevel@tonic-gate 					cur_bytes = 0;
11857c478bd9Sstevel@tonic-gate 					blocksize = BLKSIZE;
11867c478bd9Sstevel@tonic-gate 					filesize = BLKSIZE * 2;
11877c478bd9Sstevel@tonic-gate 				}
11887c478bd9Sstevel@tonic-gate 				addr = value << FRGSHIFT;
11897c478bd9Sstevel@tonic-gate 				bod_addr = addr;
11907c478bd9Sstevel@tonic-gate 				value = get(LONG);
11917c478bd9Sstevel@tonic-gate 				type = BLOCK;
11927c478bd9Sstevel@tonic-gate 				dirslot = 0;
11937c478bd9Sstevel@tonic-gate 				trapped++;
11947c478bd9Sstevel@tonic-gate 				continue;
11957c478bd9Sstevel@tonic-gate 			}
11967c478bd9Sstevel@tonic-gate 			if (match("bs", 2)) {		/* block size */
11977c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
11987c478bd9Sstevel@tonic-gate 				should_print = 1;
11997c478bd9Sstevel@tonic-gate 				if (icheck(cur_ino) == 0)
12007c478bd9Sstevel@tonic-gate 					continue;
1201d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1202d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_blocks;
12037c478bd9Sstevel@tonic-gate 				value = get(LONG);
12047c478bd9Sstevel@tonic-gate 				type = NULL;
12057c478bd9Sstevel@tonic-gate 				continue;
12067c478bd9Sstevel@tonic-gate 			}
12077c478bd9Sstevel@tonic-gate 			if (match("base", 2)) {		/* change/show base */
12087c478bd9Sstevel@tonic-gate showbase:
12097c478bd9Sstevel@tonic-gate 				if ((c = getachar()) == '\n') {
12107c478bd9Sstevel@tonic-gate 					ungetachar(c);
12117c478bd9Sstevel@tonic-gate 					printf("base =\t\t");
12127c478bd9Sstevel@tonic-gate 					switch (base) {
12137c478bd9Sstevel@tonic-gate 					case OCTAL:
12147c478bd9Sstevel@tonic-gate 						printf("OCTAL\n");
12157c478bd9Sstevel@tonic-gate 						continue;
12167c478bd9Sstevel@tonic-gate 					case DECIMAL:
12177c478bd9Sstevel@tonic-gate 						printf("DECIMAL\n");
12187c478bd9Sstevel@tonic-gate 						continue;
12197c478bd9Sstevel@tonic-gate 					case HEX:
12207c478bd9Sstevel@tonic-gate 						printf("HEX\n");
12217c478bd9Sstevel@tonic-gate 						continue;
12227c478bd9Sstevel@tonic-gate 					}
12237c478bd9Sstevel@tonic-gate 				}
12247c478bd9Sstevel@tonic-gate 				if (c != '=') {
12257c478bd9Sstevel@tonic-gate 					printf("missing '='\n");
12267c478bd9Sstevel@tonic-gate 					error++;
12277c478bd9Sstevel@tonic-gate 					continue;
12287c478bd9Sstevel@tonic-gate 				}
12297c478bd9Sstevel@tonic-gate 				value = expr();
12307c478bd9Sstevel@tonic-gate 				switch (value) {
12317c478bd9Sstevel@tonic-gate 				default:
12327c478bd9Sstevel@tonic-gate 					printf("invalid base\n");
12337c478bd9Sstevel@tonic-gate 					error++;
12347c478bd9Sstevel@tonic-gate 					break;
12357c478bd9Sstevel@tonic-gate 				case OCTAL:
12367c478bd9Sstevel@tonic-gate 				case DECIMAL:
12377c478bd9Sstevel@tonic-gate 				case HEX:
12387c478bd9Sstevel@tonic-gate 					base = (short)value;
12397c478bd9Sstevel@tonic-gate 				}
12407c478bd9Sstevel@tonic-gate 				goto showbase;
12417c478bd9Sstevel@tonic-gate 			}
12427c478bd9Sstevel@tonic-gate 			goto bad_syntax;
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 		case 'c':
12457c478bd9Sstevel@tonic-gate 			if (colon)
12467c478bd9Sstevel@tonic-gate 				colon = 0;
12477c478bd9Sstevel@tonic-gate 			else
12487c478bd9Sstevel@tonic-gate 				goto no_colon;
12497c478bd9Sstevel@tonic-gate 			if (match("cd", 2)) {		/* change directory */
12507c478bd9Sstevel@tonic-gate 				top = filenames - 1;
12517c478bd9Sstevel@tonic-gate 				eat_spaces();
12527c478bd9Sstevel@tonic-gate 				if ((c = getachar()) == '\n') {
12537c478bd9Sstevel@tonic-gate 					ungetachar(c);
12547c478bd9Sstevel@tonic-gate 					current_pathp = -1;
12557c478bd9Sstevel@tonic-gate 					restore_inode(2);
12567c478bd9Sstevel@tonic-gate 					continue;
12577c478bd9Sstevel@tonic-gate 				}
12587c478bd9Sstevel@tonic-gate 				ungetachar(c);
12597c478bd9Sstevel@tonic-gate 				temp = cur_inum;
12607c478bd9Sstevel@tonic-gate 				doing_cd = 1;
12617c478bd9Sstevel@tonic-gate 				parse();
12627c478bd9Sstevel@tonic-gate 				doing_cd = 0;
12637c478bd9Sstevel@tonic-gate 				if (nfiles != 1) {
12647c478bd9Sstevel@tonic-gate 					restore_inode((ino_t)temp);
12657c478bd9Sstevel@tonic-gate 					if (!error) {
12667c478bd9Sstevel@tonic-gate 						print_path(input_path,
12677c478bd9Sstevel@tonic-gate 							(int)input_pathp);
12687c478bd9Sstevel@tonic-gate 						if (nfiles == 0)
12697c478bd9Sstevel@tonic-gate 							printf(" not found\n");
12707c478bd9Sstevel@tonic-gate 						else
12717c478bd9Sstevel@tonic-gate 							printf(" ambiguous\n");
12727c478bd9Sstevel@tonic-gate 						error++;
12737c478bd9Sstevel@tonic-gate 					}
12747c478bd9Sstevel@tonic-gate 					continue;
12757c478bd9Sstevel@tonic-gate 				}
12767c478bd9Sstevel@tonic-gate 				restore_inode(filenames->ino);
12777c478bd9Sstevel@tonic-gate 				if ((mode = icheck(addr)) == 0)
12787c478bd9Sstevel@tonic-gate 					continue;
12797c478bd9Sstevel@tonic-gate 				if ((mode & IFMT) != IFDIR) {
12807c478bd9Sstevel@tonic-gate 					restore_inode((ino_t)temp);
12817c478bd9Sstevel@tonic-gate 					print_path(input_path,
12827c478bd9Sstevel@tonic-gate 							(int)input_pathp);
12837c478bd9Sstevel@tonic-gate 					printf(" not a directory\n");
12847c478bd9Sstevel@tonic-gate 					error++;
12857c478bd9Sstevel@tonic-gate 					continue;
12867c478bd9Sstevel@tonic-gate 				}
12877c478bd9Sstevel@tonic-gate 				for (i = 0; i <= top->len; i++)
12887c478bd9Sstevel@tonic-gate 					(void) strcpy(current_path[i],
12897c478bd9Sstevel@tonic-gate 						top->fname[i]);
12907c478bd9Sstevel@tonic-gate 				current_pathp = top->len;
12917c478bd9Sstevel@tonic-gate 				continue;
12927c478bd9Sstevel@tonic-gate 			}
12937c478bd9Sstevel@tonic-gate 			if (match("cg", 2)) {		/* cylinder group */
12947c478bd9Sstevel@tonic-gate 				if (type == NUMB)
12957c478bd9Sstevel@tonic-gate 					value = addr;
12967c478bd9Sstevel@tonic-gate 				if (value > fs->fs_ncg - 1) {
12977c478bd9Sstevel@tonic-gate 					printf("maximum cylinder group is ");
12987c478bd9Sstevel@tonic-gate 					print(fs->fs_ncg - 1, 8, -8, 0);
12997c478bd9Sstevel@tonic-gate 					printf("\n");
13007c478bd9Sstevel@tonic-gate 					error++;
13017c478bd9Sstevel@tonic-gate 					continue;
13027c478bd9Sstevel@tonic-gate 				}
13037c478bd9Sstevel@tonic-gate 				type = objsz = CGRP;
13047c478bd9Sstevel@tonic-gate 				cur_cgrp = (long)value;
13057c478bd9Sstevel@tonic-gate 				addr = cgtod(fs, cur_cgrp) << FRGSHIFT;
13067c478bd9Sstevel@tonic-gate 				continue;
13077c478bd9Sstevel@tonic-gate 			}
13087c478bd9Sstevel@tonic-gate 			if (match("ct", 2)) {		/* creation time */
13097c478bd9Sstevel@tonic-gate 				acting_on_inode = 2;
13107c478bd9Sstevel@tonic-gate 				should_print = 1;
1311d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1312d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_ctime;
13137c478bd9Sstevel@tonic-gate 				value = get(LONG);
13147c478bd9Sstevel@tonic-gate 				type = NULL;
13157c478bd9Sstevel@tonic-gate 				continue;
13167c478bd9Sstevel@tonic-gate 			}
13177c478bd9Sstevel@tonic-gate 			goto bad_syntax;
13187c478bd9Sstevel@tonic-gate 
13197c478bd9Sstevel@tonic-gate 		case 'd':
13207c478bd9Sstevel@tonic-gate 			if (colon)
13217c478bd9Sstevel@tonic-gate 				colon = 0;
13227c478bd9Sstevel@tonic-gate 			else
13237c478bd9Sstevel@tonic-gate 				goto no_colon;
13247c478bd9Sstevel@tonic-gate 			if (match("directory", 2)) { 	/* directory offsets */
13257c478bd9Sstevel@tonic-gate 				if (type == NUMB)
13267c478bd9Sstevel@tonic-gate 					value = addr;
13277c478bd9Sstevel@tonic-gate 				objsz = DIRECTORY;
13287c478bd9Sstevel@tonic-gate 				type = DIRECTORY;
13297c478bd9Sstevel@tonic-gate 				addr = (u_offset_t)getdirslot((long)value);
13307c478bd9Sstevel@tonic-gate 				continue;
13317c478bd9Sstevel@tonic-gate 			}
13327c478bd9Sstevel@tonic-gate 			if (match("db", 2)) {		/* direct block */
13337c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
13347c478bd9Sstevel@tonic-gate 				should_print = 1;
13357c478bd9Sstevel@tonic-gate 				if (type == NUMB)
13367c478bd9Sstevel@tonic-gate 					value = addr;
13377c478bd9Sstevel@tonic-gate 				if (value >= NDADDR) {
13387c478bd9Sstevel@tonic-gate 					printf("direct blocks are 0 to ");
13397c478bd9Sstevel@tonic-gate 					print(NDADDR - 1, 0, 0, 0);
13407c478bd9Sstevel@tonic-gate 					printf("\n");
13417c478bd9Sstevel@tonic-gate 					error++;
13427c478bd9Sstevel@tonic-gate 					continue;
13437c478bd9Sstevel@tonic-gate 				}
13447c478bd9Sstevel@tonic-gate 				addr = cur_ino;
13457c478bd9Sstevel@tonic-gate 				if (!icheck(addr))
13467c478bd9Sstevel@tonic-gate 					continue;
13477c478bd9Sstevel@tonic-gate 				addr = (long)
1348d1a180b0Smaheshvs 					&((struct dinode *)(uintptr_t)cur_ino)->
13497c478bd9Sstevel@tonic-gate 								di_db[value];
13507c478bd9Sstevel@tonic-gate 				bod_addr = addr;
13517c478bd9Sstevel@tonic-gate 				cur_bytes = (value) * BLKSIZE;
13527c478bd9Sstevel@tonic-gate 				cur_block = (long)value;
13537c478bd9Sstevel@tonic-gate 				type = BLOCK;
13547c478bd9Sstevel@tonic-gate 				dirslot = 0;
13557c478bd9Sstevel@tonic-gate 				value = get(LONG);
13567c478bd9Sstevel@tonic-gate 				if (!value && !override) {
13577c478bd9Sstevel@tonic-gate 					printf("non existent block\n");
13587c478bd9Sstevel@tonic-gate 					error++;
13597c478bd9Sstevel@tonic-gate 				}
13607c478bd9Sstevel@tonic-gate 				continue;
13617c478bd9Sstevel@tonic-gate 			}
13627c478bd9Sstevel@tonic-gate 			goto bad_syntax;
13637c478bd9Sstevel@tonic-gate 
13647c478bd9Sstevel@tonic-gate 		case 'f':
13657c478bd9Sstevel@tonic-gate 			if (colon)
13667c478bd9Sstevel@tonic-gate 				colon = 0;
13677c478bd9Sstevel@tonic-gate 			else
13687c478bd9Sstevel@tonic-gate 				goto no_colon;
13697c478bd9Sstevel@tonic-gate 			if (match("find", 3)) {		/* find command */
13707c478bd9Sstevel@tonic-gate 				find();
13717c478bd9Sstevel@tonic-gate 				continue;
13727c478bd9Sstevel@tonic-gate 			}
13737c478bd9Sstevel@tonic-gate 			if (match("fragment", 2)) {	/* fragment conv. */
13747c478bd9Sstevel@tonic-gate 				if (type == NUMB) {
13757c478bd9Sstevel@tonic-gate 					value = addr;
13767c478bd9Sstevel@tonic-gate 					cur_bytes = 0;
13777c478bd9Sstevel@tonic-gate 					blocksize = FRGSIZE;
13787c478bd9Sstevel@tonic-gate 					filesize = FRGSIZE * 2;
13797c478bd9Sstevel@tonic-gate 				}
13807c478bd9Sstevel@tonic-gate 				if (min(blocksize, filesize) - cur_bytes >
13817c478bd9Sstevel@tonic-gate 							FRGSIZE) {
13827c478bd9Sstevel@tonic-gate 					blocksize = cur_bytes + FRGSIZE;
13837c478bd9Sstevel@tonic-gate 					filesize = blocksize * 2;
13847c478bd9Sstevel@tonic-gate 				}
13857c478bd9Sstevel@tonic-gate 				addr = value << FRGSHIFT;
13867c478bd9Sstevel@tonic-gate 				bod_addr = addr;
13877c478bd9Sstevel@tonic-gate 				value = get(LONG);
13887c478bd9Sstevel@tonic-gate 				type = FRAGMENT;
13897c478bd9Sstevel@tonic-gate 				dirslot = 0;
13907c478bd9Sstevel@tonic-gate 				trapped++;
13917c478bd9Sstevel@tonic-gate 				continue;
13927c478bd9Sstevel@tonic-gate 			}
13937c478bd9Sstevel@tonic-gate 			if (match("file", 4)) {		/* access as file */
13947c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
13957c478bd9Sstevel@tonic-gate 				should_print = 1;
13967c478bd9Sstevel@tonic-gate 				if (type == NUMB)
13977c478bd9Sstevel@tonic-gate 					value = addr;
13987c478bd9Sstevel@tonic-gate 				addr = cur_ino;
13997c478bd9Sstevel@tonic-gate 				if ((mode = icheck(addr)) == 0)
14007c478bd9Sstevel@tonic-gate 					continue;
14017c478bd9Sstevel@tonic-gate 				if (!override) {
14027c478bd9Sstevel@tonic-gate 					switch (mode & IFMT) {
14037c478bd9Sstevel@tonic-gate 					case IFCHR:
14047c478bd9Sstevel@tonic-gate 					case IFBLK:
14057c478bd9Sstevel@tonic-gate 					    printf("special device\n");
14067c478bd9Sstevel@tonic-gate 					    error++;
14077c478bd9Sstevel@tonic-gate 					    continue;
14087c478bd9Sstevel@tonic-gate 					}
14097c478bd9Sstevel@tonic-gate 				}
14107c478bd9Sstevel@tonic-gate 				if ((addr = (u_offset_t)
14117c478bd9Sstevel@tonic-gate 				    (bmap((long)value) << FRGSHIFT)) == 0)
14127c478bd9Sstevel@tonic-gate 					continue;
14137c478bd9Sstevel@tonic-gate 				cur_block = (long)value;
14147c478bd9Sstevel@tonic-gate 				bod_addr = addr;
14157c478bd9Sstevel@tonic-gate 				type = BLOCK;
14167c478bd9Sstevel@tonic-gate 				dirslot = 0;
14177c478bd9Sstevel@tonic-gate 				continue;
14187c478bd9Sstevel@tonic-gate 			}
14197c478bd9Sstevel@tonic-gate 			if (match("fill", 4)) {		/* fill */
14207c478bd9Sstevel@tonic-gate 				if (getachar() != '=') {
14217c478bd9Sstevel@tonic-gate 					printf("missing '='\n");
14227c478bd9Sstevel@tonic-gate 					error++;
14237c478bd9Sstevel@tonic-gate 					continue;
14247c478bd9Sstevel@tonic-gate 				}
14257c478bd9Sstevel@tonic-gate 				if (objsz == INODE || objsz == DIRECTORY ||
14267c478bd9Sstevel@tonic-gate 				    objsz == SHADOW_DATA) {
14277c478bd9Sstevel@tonic-gate 					printf(
14287c478bd9Sstevel@tonic-gate 					    "can't fill inode or directory\n");
14297c478bd9Sstevel@tonic-gate 					error++;
14307c478bd9Sstevel@tonic-gate 					continue;
14317c478bd9Sstevel@tonic-gate 				}
14327c478bd9Sstevel@tonic-gate 				fill();
14337c478bd9Sstevel@tonic-gate 				continue;
14347c478bd9Sstevel@tonic-gate 			}
14357c478bd9Sstevel@tonic-gate 			goto bad_syntax;
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 		case 'g':
14387c478bd9Sstevel@tonic-gate 			if (colon)
14397c478bd9Sstevel@tonic-gate 				colon = 0;
14407c478bd9Sstevel@tonic-gate 			else
14417c478bd9Sstevel@tonic-gate 				goto no_colon;
14427c478bd9Sstevel@tonic-gate 			if (match("gid", 1)) {		/* group id */
14437c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
14447c478bd9Sstevel@tonic-gate 				should_print = 1;
1445d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1446d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_gid;
14477c478bd9Sstevel@tonic-gate 				value = get(SHORT);
14487c478bd9Sstevel@tonic-gate 				type = NULL;
14497c478bd9Sstevel@tonic-gate 				continue;
14507c478bd9Sstevel@tonic-gate 			}
14517c478bd9Sstevel@tonic-gate 			goto bad_syntax;
14527c478bd9Sstevel@tonic-gate 
14537c478bd9Sstevel@tonic-gate 		case 'i':
14547c478bd9Sstevel@tonic-gate 			if (colon)
14557c478bd9Sstevel@tonic-gate 				colon = 0;
14567c478bd9Sstevel@tonic-gate 			else
14577c478bd9Sstevel@tonic-gate 				goto no_colon;
14587c478bd9Sstevel@tonic-gate 			if (match("inode", 2)) { /* i# to inode conversion */
14597c478bd9Sstevel@tonic-gate 				if (c_count == 2) {
14607c478bd9Sstevel@tonic-gate 					addr = cur_ino;
14617c478bd9Sstevel@tonic-gate 					value = get(INODE);
14627c478bd9Sstevel@tonic-gate 					type = NULL;
14637c478bd9Sstevel@tonic-gate 					laststyle = '=';
14647c478bd9Sstevel@tonic-gate 					lastpo = 'i';
14657c478bd9Sstevel@tonic-gate 					should_print = 1;
14667c478bd9Sstevel@tonic-gate 					continue;
14677c478bd9Sstevel@tonic-gate 				}
14687c478bd9Sstevel@tonic-gate 				if (type == NUMB)
14697c478bd9Sstevel@tonic-gate 					value = addr;
14707c478bd9Sstevel@tonic-gate 				addr = itob(value);
14717c478bd9Sstevel@tonic-gate 				if (!icheck(addr))
14727c478bd9Sstevel@tonic-gate 					continue;
14737c478bd9Sstevel@tonic-gate 				cur_ino = addr;
14747c478bd9Sstevel@tonic-gate 				cur_inum = (long)value;
14757c478bd9Sstevel@tonic-gate 				value = get(INODE);
14767c478bd9Sstevel@tonic-gate 				type = NULL;
14777c478bd9Sstevel@tonic-gate 				continue;
14787c478bd9Sstevel@tonic-gate 			}
14797c478bd9Sstevel@tonic-gate 			if (match("ib", 2)) {	/* indirect block */
14807c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
14817c478bd9Sstevel@tonic-gate 				should_print = 1;
14827c478bd9Sstevel@tonic-gate 				if (type == NUMB)
14837c478bd9Sstevel@tonic-gate 					value = addr;
14847c478bd9Sstevel@tonic-gate 				if (value >= NIADDR) {
14857c478bd9Sstevel@tonic-gate 					printf("indirect blocks are 0 to ");
14867c478bd9Sstevel@tonic-gate 					print(NIADDR - 1, 0, 0, 0);
14877c478bd9Sstevel@tonic-gate 					printf("\n");
14887c478bd9Sstevel@tonic-gate 					error++;
14897c478bd9Sstevel@tonic-gate 					continue;
14907c478bd9Sstevel@tonic-gate 				}
1491d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)(uintptr_t)
1492d1a180b0Smaheshvs 						cur_ino)->di_ib[value];
14937c478bd9Sstevel@tonic-gate 				cur_bytes = (NDADDR - 1) * BLKSIZE;
14947c478bd9Sstevel@tonic-gate 				temp = 1;
14957c478bd9Sstevel@tonic-gate 				for (i = 0; i < value; i++) {
14967c478bd9Sstevel@tonic-gate 					temp *= NINDIR(fs) * BLKSIZE;
14977c478bd9Sstevel@tonic-gate 					cur_bytes += temp;
14987c478bd9Sstevel@tonic-gate 				}
14997c478bd9Sstevel@tonic-gate 				type = BLOCK;
15007c478bd9Sstevel@tonic-gate 				dirslot = 0;
15017c478bd9Sstevel@tonic-gate 				value = get(LONG);
15027c478bd9Sstevel@tonic-gate 				if (!value && !override) {
15037c478bd9Sstevel@tonic-gate 					printf("non existent block\n");
15047c478bd9Sstevel@tonic-gate 					error++;
15057c478bd9Sstevel@tonic-gate 				}
15067c478bd9Sstevel@tonic-gate 				continue;
15077c478bd9Sstevel@tonic-gate 			}
15087c478bd9Sstevel@tonic-gate 			goto bad_syntax;
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate 		case 'l':
15117c478bd9Sstevel@tonic-gate 			if (colon)
15127c478bd9Sstevel@tonic-gate 				colon = 0;
15137c478bd9Sstevel@tonic-gate 			else
15147c478bd9Sstevel@tonic-gate 				goto no_colon;
15157c478bd9Sstevel@tonic-gate 			if (match("log_head", 8)) {
15167c478bd9Sstevel@tonic-gate 				log_display_header();
15177c478bd9Sstevel@tonic-gate 				should_print = 0;
15187c478bd9Sstevel@tonic-gate 				continue;
15197c478bd9Sstevel@tonic-gate 			}
15207c478bd9Sstevel@tonic-gate 			if (match("log_delta", 9)) {
15217c478bd9Sstevel@tonic-gate 				log_show(LOG_NDELTAS);
15227c478bd9Sstevel@tonic-gate 				should_print = 0;
15237c478bd9Sstevel@tonic-gate 				continue;
15247c478bd9Sstevel@tonic-gate 			}
15257c478bd9Sstevel@tonic-gate 			if (match("log_show", 8)) {
15267c478bd9Sstevel@tonic-gate 				log_show(LOG_ALLDELTAS);
15277c478bd9Sstevel@tonic-gate 				should_print = 0;
15287c478bd9Sstevel@tonic-gate 				continue;
15297c478bd9Sstevel@tonic-gate 			}
15307c478bd9Sstevel@tonic-gate 			if (match("log_chk", 7)) {
15317c478bd9Sstevel@tonic-gate 				log_show(LOG_CHECKSCAN);
15327c478bd9Sstevel@tonic-gate 				should_print = 0;
15337c478bd9Sstevel@tonic-gate 				continue;
15347c478bd9Sstevel@tonic-gate 			}
15357c478bd9Sstevel@tonic-gate 			if (match("log_otodb", 9)) {
15367c478bd9Sstevel@tonic-gate 				if (log_lodb((u_offset_t)addr, &temp)) {
15377c478bd9Sstevel@tonic-gate 					addr = temp;
15387c478bd9Sstevel@tonic-gate 					should_print = 1;
15397c478bd9Sstevel@tonic-gate 					laststyle = '=';
15407c478bd9Sstevel@tonic-gate 				} else
15417c478bd9Sstevel@tonic-gate 					error++;
15427c478bd9Sstevel@tonic-gate 				continue;
15437c478bd9Sstevel@tonic-gate 			}
15447c478bd9Sstevel@tonic-gate 			if (match("ls", 2)) {		/* ls command */
15457c478bd9Sstevel@tonic-gate 				temp = cur_inum;
15467c478bd9Sstevel@tonic-gate 				recursive = long_list = 0;
15477c478bd9Sstevel@tonic-gate 				top = filenames - 1;
15487c478bd9Sstevel@tonic-gate 				for (;;) {
15497c478bd9Sstevel@tonic-gate 					eat_spaces();
15507c478bd9Sstevel@tonic-gate 					if ((c = getachar()) == '-') {
15517c478bd9Sstevel@tonic-gate 						if ((c = getachar()) == 'R') {
15527c478bd9Sstevel@tonic-gate 							recursive = 1;
15537c478bd9Sstevel@tonic-gate 							continue;
15547c478bd9Sstevel@tonic-gate 						} else if (c == 'l') {
15557c478bd9Sstevel@tonic-gate 							long_list = 1;
15567c478bd9Sstevel@tonic-gate 						} else {
15577c478bd9Sstevel@tonic-gate 							printf(
15587c478bd9Sstevel@tonic-gate 							    "unknown option ");
15597c478bd9Sstevel@tonic-gate 							printf("'%c'\n", c);
15607c478bd9Sstevel@tonic-gate 							error++;
15617c478bd9Sstevel@tonic-gate 							break;
15627c478bd9Sstevel@tonic-gate 						}
15637c478bd9Sstevel@tonic-gate 					} else
15647c478bd9Sstevel@tonic-gate 						ungetachar(c);
15657c478bd9Sstevel@tonic-gate 					if ((c = getachar()) == '\n') {
15667c478bd9Sstevel@tonic-gate 						if (c_count != 2) {
15677c478bd9Sstevel@tonic-gate 							ungetachar(c);
15687c478bd9Sstevel@tonic-gate 							break;
15697c478bd9Sstevel@tonic-gate 						}
15707c478bd9Sstevel@tonic-gate 					}
15717c478bd9Sstevel@tonic-gate 					c_count++;
15727c478bd9Sstevel@tonic-gate 					ungetachar(c);
15737c478bd9Sstevel@tonic-gate 					parse();
15747c478bd9Sstevel@tonic-gate 					restore_inode((ino_t)temp);
15757c478bd9Sstevel@tonic-gate 					if (error)
15767c478bd9Sstevel@tonic-gate 						break;
15777c478bd9Sstevel@tonic-gate 				}
15787c478bd9Sstevel@tonic-gate 				recursive = 0;
15797c478bd9Sstevel@tonic-gate 				if (error || nfiles == 0) {
15807c478bd9Sstevel@tonic-gate 					if (!error) {
15817c478bd9Sstevel@tonic-gate 						print_path(input_path,
15827c478bd9Sstevel@tonic-gate 							(int)input_pathp);
15837c478bd9Sstevel@tonic-gate 						printf(" not found\n");
15847c478bd9Sstevel@tonic-gate 					}
15857c478bd9Sstevel@tonic-gate 					continue;
15867c478bd9Sstevel@tonic-gate 				}
15877c478bd9Sstevel@tonic-gate 				if (nfiles) {
15887c478bd9Sstevel@tonic-gate 				    cmp_level = 0;
15897c478bd9Sstevel@tonic-gate 				    qsort((char *)filenames, nfiles,
15907c478bd9Sstevel@tonic-gate 					sizeof (struct filenames), ffcmp);
15917c478bd9Sstevel@tonic-gate 				    ls(filenames, filenames + (nfiles - 1), 0);
15927c478bd9Sstevel@tonic-gate 				} else {
15937c478bd9Sstevel@tonic-gate 				    printf("no match\n");
15947c478bd9Sstevel@tonic-gate 				    error++;
15957c478bd9Sstevel@tonic-gate 				}
15967c478bd9Sstevel@tonic-gate 				restore_inode((ino_t)temp);
15977c478bd9Sstevel@tonic-gate 				continue;
15987c478bd9Sstevel@tonic-gate 			}
15997c478bd9Sstevel@tonic-gate 			if (match("ln", 2)) {		/* link count */
16007c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
16017c478bd9Sstevel@tonic-gate 				should_print = 1;
1602d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1603d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_nlink;
16047c478bd9Sstevel@tonic-gate 				value = get(SHORT);
16057c478bd9Sstevel@tonic-gate 				type = NULL;
16067c478bd9Sstevel@tonic-gate 				continue;
16077c478bd9Sstevel@tonic-gate 			}
16087c478bd9Sstevel@tonic-gate 			goto bad_syntax;
16097c478bd9Sstevel@tonic-gate 
16107c478bd9Sstevel@tonic-gate 		case 'm':
16117c478bd9Sstevel@tonic-gate 			if (colon)
16127c478bd9Sstevel@tonic-gate 				colon = 0;
16137c478bd9Sstevel@tonic-gate 			else
16147c478bd9Sstevel@tonic-gate 				goto no_colon;
16157c478bd9Sstevel@tonic-gate 			addr = cur_ino;
16167c478bd9Sstevel@tonic-gate 			if ((mode = icheck(addr)) == 0)
16177c478bd9Sstevel@tonic-gate 				continue;
16187c478bd9Sstevel@tonic-gate 			if (match("mt", 2)) { 		/* modification time */
16197c478bd9Sstevel@tonic-gate 				acting_on_inode = 2;
16207c478bd9Sstevel@tonic-gate 				should_print = 1;
1621d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1622d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_mtime;
16237c478bd9Sstevel@tonic-gate 				value = get(LONG);
16247c478bd9Sstevel@tonic-gate 				type = NULL;
16257c478bd9Sstevel@tonic-gate 				continue;
16267c478bd9Sstevel@tonic-gate 			}
16277c478bd9Sstevel@tonic-gate 			if (match("md", 2)) {		/* mode */
16287c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
16297c478bd9Sstevel@tonic-gate 				should_print = 1;
1630d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1631d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_mode;
16327c478bd9Sstevel@tonic-gate 				value = get(SHORT);
16337c478bd9Sstevel@tonic-gate 				type = NULL;
16347c478bd9Sstevel@tonic-gate 				continue;
16357c478bd9Sstevel@tonic-gate 			}
16367c478bd9Sstevel@tonic-gate 			if (match("maj", 2)) {	/* major device number */
16377c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
16387c478bd9Sstevel@tonic-gate 				should_print = 1;
16397c478bd9Sstevel@tonic-gate 				if (devcheck(mode))
16407c478bd9Sstevel@tonic-gate 					continue;
1641d1a180b0Smaheshvs 				addr = (uintptr_t)&((struct dinode *)(uintptr_t)
1642d1a180b0Smaheshvs 							cur_ino)->di_ordev;
16437c478bd9Sstevel@tonic-gate 				{
16447c478bd9Sstevel@tonic-gate 					long	dvalue;
16457c478bd9Sstevel@tonic-gate 					dvalue = get(LONG);
16467c478bd9Sstevel@tonic-gate 					value = major(dvalue);
16477c478bd9Sstevel@tonic-gate 				}
16487c478bd9Sstevel@tonic-gate 				type = NULL;
16497c478bd9Sstevel@tonic-gate 				continue;
16507c478bd9Sstevel@tonic-gate 			}
16517c478bd9Sstevel@tonic-gate 			if (match("min", 2)) {	/* minor device number */
16527c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
16537c478bd9Sstevel@tonic-gate 				should_print = 1;
16547c478bd9Sstevel@tonic-gate 				if (devcheck(mode))
16557c478bd9Sstevel@tonic-gate 					continue;
1656d1a180b0Smaheshvs 				addr = (uintptr_t)&((struct dinode *)(uintptr_t)
1657d1a180b0Smaheshvs 							cur_ino)->di_ordev;
16587c478bd9Sstevel@tonic-gate 				{
16597c478bd9Sstevel@tonic-gate 					long	dvalue;
16607c478bd9Sstevel@tonic-gate 					dvalue = (long)get(LONG);
16617c478bd9Sstevel@tonic-gate 					value = minor(dvalue);
16627c478bd9Sstevel@tonic-gate 				}
16637c478bd9Sstevel@tonic-gate 				type = NULL;
16647c478bd9Sstevel@tonic-gate 				continue;
16657c478bd9Sstevel@tonic-gate 			}
16667c478bd9Sstevel@tonic-gate 			goto bad_syntax;
16677c478bd9Sstevel@tonic-gate 
16687c478bd9Sstevel@tonic-gate 		case 'n':
16697c478bd9Sstevel@tonic-gate 			if (colon)
16707c478bd9Sstevel@tonic-gate 				colon = 0;
16717c478bd9Sstevel@tonic-gate 			else
16727c478bd9Sstevel@tonic-gate 				goto no_colon;
16737c478bd9Sstevel@tonic-gate 			if (match("nm", 1)) {		/* directory name */
16747c478bd9Sstevel@tonic-gate 				objsz = DIRECTORY;
16757c478bd9Sstevel@tonic-gate 				acting_on_directory = 1;
16767c478bd9Sstevel@tonic-gate 				cur_dir = addr;
16777c478bd9Sstevel@tonic-gate 				if ((cptr = getblk(addr)) == 0)
16787c478bd9Sstevel@tonic-gate 					continue;
16797c478bd9Sstevel@tonic-gate 				/*LINTED*/
16807c478bd9Sstevel@tonic-gate 				dirp = (struct direct *)(cptr+blkoff(fs, addr));
16817c478bd9Sstevel@tonic-gate 				stringsize = (long)dirp->d_reclen -
16827c478bd9Sstevel@tonic-gate 						((long)&dirp->d_name[0] -
16837c478bd9Sstevel@tonic-gate 							(long)&dirp->d_ino);
1684d1a180b0Smaheshvs 				addr = (long)&((struct direct *)
1685d1a180b0Smaheshvs 						(uintptr_t)addr)->d_name[0];
16867c478bd9Sstevel@tonic-gate 				type = NULL;
16877c478bd9Sstevel@tonic-gate 				continue;
16887c478bd9Sstevel@tonic-gate 			}
16897c478bd9Sstevel@tonic-gate 			goto bad_syntax;
16907c478bd9Sstevel@tonic-gate 
16917c478bd9Sstevel@tonic-gate 		case 'o':
16927c478bd9Sstevel@tonic-gate 			if (colon)
16937c478bd9Sstevel@tonic-gate 				colon = 0;
16947c478bd9Sstevel@tonic-gate 			else
16957c478bd9Sstevel@tonic-gate 				goto no_colon;
16967c478bd9Sstevel@tonic-gate 			if (match("override", 1)) {	/* override flip flop */
16977c478bd9Sstevel@tonic-gate 				override = !override;
16987c478bd9Sstevel@tonic-gate 				if (override)
16997c478bd9Sstevel@tonic-gate 					printf("error checking off\n");
17007c478bd9Sstevel@tonic-gate 				else
17017c478bd9Sstevel@tonic-gate 					printf("error checking on\n");
17027c478bd9Sstevel@tonic-gate 				continue;
17037c478bd9Sstevel@tonic-gate 			}
17047c478bd9Sstevel@tonic-gate 			goto bad_syntax;
17057c478bd9Sstevel@tonic-gate 
17067c478bd9Sstevel@tonic-gate 		case 'p':
17077c478bd9Sstevel@tonic-gate 			if (colon)
17087c478bd9Sstevel@tonic-gate 				colon = 0;
17097c478bd9Sstevel@tonic-gate 			else
17107c478bd9Sstevel@tonic-gate 				goto no_colon;
17117c478bd9Sstevel@tonic-gate 			if (match("pwd", 2)) {		/* print working dir */
17127c478bd9Sstevel@tonic-gate 				print_path(current_path, (int)current_pathp);
17137c478bd9Sstevel@tonic-gate 				printf("\n");
17147c478bd9Sstevel@tonic-gate 				continue;
17157c478bd9Sstevel@tonic-gate 			}
17167c478bd9Sstevel@tonic-gate 			if (match("prompt", 2)) {	/* change prompt */
17177c478bd9Sstevel@tonic-gate 				if ((c = getachar()) != '=') {
17187c478bd9Sstevel@tonic-gate 					printf("missing '='\n");
17197c478bd9Sstevel@tonic-gate 					error++;
17207c478bd9Sstevel@tonic-gate 					continue;
17217c478bd9Sstevel@tonic-gate 				}
17227c478bd9Sstevel@tonic-gate 				if ((c = getachar()) != '"') {
17237c478bd9Sstevel@tonic-gate 					printf("missing '\"'\n");
17247c478bd9Sstevel@tonic-gate 					error++;
17257c478bd9Sstevel@tonic-gate 					continue;
17267c478bd9Sstevel@tonic-gate 				}
17277c478bd9Sstevel@tonic-gate 				i = 0;
17287c478bd9Sstevel@tonic-gate 				prompt = &prompt[0];
17297c478bd9Sstevel@tonic-gate 				while ((c = getachar()) != '"' && c != '\n') {
17307c478bd9Sstevel@tonic-gate 					prompt[i++] = c;
17317c478bd9Sstevel@tonic-gate 					if (i >= PROMPTSIZE) {
17327c478bd9Sstevel@tonic-gate 						printf("string too long\n");
17337c478bd9Sstevel@tonic-gate 						error++;
17347c478bd9Sstevel@tonic-gate 						break;
17357c478bd9Sstevel@tonic-gate 					}
17367c478bd9Sstevel@tonic-gate 				}
17377c478bd9Sstevel@tonic-gate 				prompt[i] = '\0';
17387c478bd9Sstevel@tonic-gate 				continue;
17397c478bd9Sstevel@tonic-gate 			}
17407c478bd9Sstevel@tonic-gate 			goto bad_syntax;
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 		case 'q':
17437c478bd9Sstevel@tonic-gate 			if (!colon)
17447c478bd9Sstevel@tonic-gate 				goto no_colon;
17457c478bd9Sstevel@tonic-gate 			if (match("quit", 1)) {		/* quit */
17467c478bd9Sstevel@tonic-gate 				if ((c = getachar()) != '\n') {
17477c478bd9Sstevel@tonic-gate 					error++;
17487c478bd9Sstevel@tonic-gate 					continue;
17497c478bd9Sstevel@tonic-gate 				}
17507c478bd9Sstevel@tonic-gate 				exit(0);
17517c478bd9Sstevel@tonic-gate 			}
17527c478bd9Sstevel@tonic-gate 			goto bad_syntax;
17537c478bd9Sstevel@tonic-gate 
17547c478bd9Sstevel@tonic-gate 		case 's':
17557c478bd9Sstevel@tonic-gate 			if (colon)
17567c478bd9Sstevel@tonic-gate 				colon = 0;
17577c478bd9Sstevel@tonic-gate 			else
17587c478bd9Sstevel@tonic-gate 				goto no_colon;
17597c478bd9Sstevel@tonic-gate 			if (match("sb", 2)) {		/* super block */
17607c478bd9Sstevel@tonic-gate 				if (c_count == 2) {
17617c478bd9Sstevel@tonic-gate 					cur_cgrp = -1;
17627c478bd9Sstevel@tonic-gate 					type = objsz = SB;
17637c478bd9Sstevel@tonic-gate 					laststyle = '=';
17647c478bd9Sstevel@tonic-gate 					lastpo = 's';
17657c478bd9Sstevel@tonic-gate 					should_print = 1;
17667c478bd9Sstevel@tonic-gate 					continue;
17677c478bd9Sstevel@tonic-gate 				}
17687c478bd9Sstevel@tonic-gate 				if (type == NUMB)
17697c478bd9Sstevel@tonic-gate 					value = addr;
17707c478bd9Sstevel@tonic-gate 				if (value > fs->fs_ncg - 1) {
17717c478bd9Sstevel@tonic-gate 					printf("maximum super block is ");
17727c478bd9Sstevel@tonic-gate 					print(fs->fs_ncg - 1, 8, -8, 0);
17737c478bd9Sstevel@tonic-gate 					printf("\n");
17747c478bd9Sstevel@tonic-gate 					error++;
17757c478bd9Sstevel@tonic-gate 					continue;
17767c478bd9Sstevel@tonic-gate 				}
17777c478bd9Sstevel@tonic-gate 				type = objsz = SB;
17787c478bd9Sstevel@tonic-gate 				cur_cgrp = (long)value;
17797c478bd9Sstevel@tonic-gate 				addr = cgsblock(fs, cur_cgrp) << FRGSHIFT;
17807c478bd9Sstevel@tonic-gate 				continue;
17817c478bd9Sstevel@tonic-gate 			}
17827c478bd9Sstevel@tonic-gate 			if (match("shadow", 2)) {	/* shadow inode data */
17837c478bd9Sstevel@tonic-gate 				if (type == NUMB)
17847c478bd9Sstevel@tonic-gate 					value = addr;
17857c478bd9Sstevel@tonic-gate 				objsz = SHADOW_DATA;
17867c478bd9Sstevel@tonic-gate 				type = SHADOW_DATA;
17877c478bd9Sstevel@tonic-gate 				addr = getshadowslot(value);
17887c478bd9Sstevel@tonic-gate 				continue;
17897c478bd9Sstevel@tonic-gate 			}
17907c478bd9Sstevel@tonic-gate 			if (match("si", 2)) {   /* shadow inode field */
17917c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
17927c478bd9Sstevel@tonic-gate 				should_print = 1;
1793d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1794d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_shadow;
17957c478bd9Sstevel@tonic-gate 				value = get(LONG);
17967c478bd9Sstevel@tonic-gate 				type = NULL;
17977c478bd9Sstevel@tonic-gate 				continue;
17987c478bd9Sstevel@tonic-gate 			}
17997c478bd9Sstevel@tonic-gate 
18007c478bd9Sstevel@tonic-gate 			if (match("sz", 2)) {		/* file size */
18017c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
18027c478bd9Sstevel@tonic-gate 				should_print = 1;
1803d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1804d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_size;
18057c478bd9Sstevel@tonic-gate 				value = get(U_OFFSET_T);
18067c478bd9Sstevel@tonic-gate 				type = NULL;
18077c478bd9Sstevel@tonic-gate 				objsz = U_OFFSET_T;
18087c478bd9Sstevel@tonic-gate 				laststyle = '=';
18097c478bd9Sstevel@tonic-gate 				lastpo = 'X';
18107c478bd9Sstevel@tonic-gate 				continue;
18117c478bd9Sstevel@tonic-gate 			}
18127c478bd9Sstevel@tonic-gate 			goto bad_syntax;
18137c478bd9Sstevel@tonic-gate 
18147c478bd9Sstevel@tonic-gate 		case 'u':
18157c478bd9Sstevel@tonic-gate 			if (colon)
18167c478bd9Sstevel@tonic-gate 				colon = 0;
18177c478bd9Sstevel@tonic-gate 			else
18187c478bd9Sstevel@tonic-gate 				goto no_colon;
18197c478bd9Sstevel@tonic-gate 			if (match("uid", 1)) {		/* user id */
18207c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
18217c478bd9Sstevel@tonic-gate 				should_print = 1;
1822d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1823d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_uid;
18247c478bd9Sstevel@tonic-gate 				value = get(SHORT);
18257c478bd9Sstevel@tonic-gate 				type = NULL;
18267c478bd9Sstevel@tonic-gate 				continue;
18277c478bd9Sstevel@tonic-gate 			}
18287c478bd9Sstevel@tonic-gate 			goto bad_syntax;
18297c478bd9Sstevel@tonic-gate 
18307c478bd9Sstevel@tonic-gate 		case 'F': /* buffer status (internal use only) */
18317c478bd9Sstevel@tonic-gate 			if (colon)
18327c478bd9Sstevel@tonic-gate 				colon = 0;
18337c478bd9Sstevel@tonic-gate 			else
18347c478bd9Sstevel@tonic-gate 				goto no_colon;
18357c478bd9Sstevel@tonic-gate 			for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd)
18367c478bd9Sstevel@tonic-gate 				printf("%8" PRIx64 " %d\n",
18377c478bd9Sstevel@tonic-gate 				    bp->blkno, bp->valid);
18387c478bd9Sstevel@tonic-gate 			printf("\n");
18397c478bd9Sstevel@tonic-gate 			printf("# commands\t\t%ld\n", commands);
18407c478bd9Sstevel@tonic-gate 			printf("# read requests\t\t%ld\n", read_requests);
18417c478bd9Sstevel@tonic-gate 			printf("# actual disk reads\t%ld\n", actual_disk_reads);
18427c478bd9Sstevel@tonic-gate 			continue;
18437c478bd9Sstevel@tonic-gate no_colon:
18447c478bd9Sstevel@tonic-gate 		printf("a colon should precede a command\n");
18457c478bd9Sstevel@tonic-gate 		error++;
18467c478bd9Sstevel@tonic-gate 		continue;
18477c478bd9Sstevel@tonic-gate bad_syntax:
18487c478bd9Sstevel@tonic-gate 		printf("more letters needed to distinguish command\n");
18497c478bd9Sstevel@tonic-gate 		error++;
18507c478bd9Sstevel@tonic-gate 		continue;
18517c478bd9Sstevel@tonic-gate 		}
18527c478bd9Sstevel@tonic-gate 	}
18537c478bd9Sstevel@tonic-gate }
18547c478bd9Sstevel@tonic-gate 
18557c478bd9Sstevel@tonic-gate /*
18567c478bd9Sstevel@tonic-gate  * usage - print usage and exit
18577c478bd9Sstevel@tonic-gate  */
18587c478bd9Sstevel@tonic-gate static void
usage(char * progname)1859d1a180b0Smaheshvs usage(char *progname)
18607c478bd9Sstevel@tonic-gate {
18617c478bd9Sstevel@tonic-gate 	printf("usage:   %s [options] special\n", progname);
18627c478bd9Sstevel@tonic-gate 	printf("options:\n");
18637c478bd9Sstevel@tonic-gate 	printf("\t-o		Specify ufs filesystem sepcific options\n");
18647c478bd9Sstevel@tonic-gate 	printf("		Available suboptions are:\n");
18657c478bd9Sstevel@tonic-gate 	printf("\t\t?		display usage\n");
18667c478bd9Sstevel@tonic-gate 	printf("\t\to		override some error conditions\n");
18677c478bd9Sstevel@tonic-gate 	printf("\t\tp=\"string\"	set prompt to string\n");
18687c478bd9Sstevel@tonic-gate 	printf("\t\tw		open for write\n");
18697c478bd9Sstevel@tonic-gate 	exit(1);
18707c478bd9Sstevel@tonic-gate }
18717c478bd9Sstevel@tonic-gate 
18727c478bd9Sstevel@tonic-gate /*
18737c478bd9Sstevel@tonic-gate  * getachar - get next character from input buffer.
18747c478bd9Sstevel@tonic-gate  */
18757c478bd9Sstevel@tonic-gate static char
getachar()18767c478bd9Sstevel@tonic-gate getachar()
18777c478bd9Sstevel@tonic-gate {
18787c478bd9Sstevel@tonic-gate 	return (input_buffer[input_pointer++]);
18797c478bd9Sstevel@tonic-gate }
18807c478bd9Sstevel@tonic-gate 
18817c478bd9Sstevel@tonic-gate /*
18827c478bd9Sstevel@tonic-gate  * ungetachar - return character to input buffer.
18837c478bd9Sstevel@tonic-gate  */
18847c478bd9Sstevel@tonic-gate static void
ungetachar(char c)1885d1a180b0Smaheshvs ungetachar(char c)
18867c478bd9Sstevel@tonic-gate {
18877c478bd9Sstevel@tonic-gate 	if (input_pointer == 0) {
18887c478bd9Sstevel@tonic-gate 		printf("internal problem maintaining input buffer\n");
18897c478bd9Sstevel@tonic-gate 		error++;
18907c478bd9Sstevel@tonic-gate 		return;
18917c478bd9Sstevel@tonic-gate 	}
18927c478bd9Sstevel@tonic-gate 	input_buffer[--input_pointer] = c;
18937c478bd9Sstevel@tonic-gate }
18947c478bd9Sstevel@tonic-gate 
18957c478bd9Sstevel@tonic-gate /*
18967c478bd9Sstevel@tonic-gate  * getnextinput - display the prompt and read an input line.
18977c478bd9Sstevel@tonic-gate  *	An input line is up to 128 characters terminated by the newline
18987c478bd9Sstevel@tonic-gate  *	character.  Handle overflow, shell escape, and eof.
18997c478bd9Sstevel@tonic-gate  */
19007c478bd9Sstevel@tonic-gate static void
getnextinput()19017c478bd9Sstevel@tonic-gate getnextinput()
19027c478bd9Sstevel@tonic-gate {
1903d1a180b0Smaheshvs 	int	i;
1904d1a180b0Smaheshvs 	char	c;
1905d1a180b0Smaheshvs 	short	pid, rpid;
19067c478bd9Sstevel@tonic-gate 	int	retcode;
19077c478bd9Sstevel@tonic-gate 
19087c478bd9Sstevel@tonic-gate newline:
19097c478bd9Sstevel@tonic-gate 	i = 0;
19107c478bd9Sstevel@tonic-gate 	printf("%s", prompt);
19117c478bd9Sstevel@tonic-gate ignore_eol:
19127c478bd9Sstevel@tonic-gate 	while ((c = getc(stdin)) != '\n' && !(c == '!' && i == 0) &&
19137c478bd9Sstevel@tonic-gate 					!feof(stdin) && i <= INPUTBUFFER - 2)
19147c478bd9Sstevel@tonic-gate 		input_buffer[i++] = c;
19157c478bd9Sstevel@tonic-gate 	if (i > 0 && input_buffer[i - 1] == '\\') {
19167c478bd9Sstevel@tonic-gate 		input_buffer[i++] = c;
19177c478bd9Sstevel@tonic-gate 		goto ignore_eol;
19187c478bd9Sstevel@tonic-gate 	}
19197c478bd9Sstevel@tonic-gate 	if (feof(stdin)) {
19207c478bd9Sstevel@tonic-gate 		printf("\n");
19217c478bd9Sstevel@tonic-gate 		exit(0);
19227c478bd9Sstevel@tonic-gate 	}
19237c478bd9Sstevel@tonic-gate 	if (c == '!') {
19247c478bd9Sstevel@tonic-gate 		if ((pid = fork()) == 0) {
19257c478bd9Sstevel@tonic-gate 			(void) execl(_PATH_BSHELL, "sh", "-t", 0);
19267c478bd9Sstevel@tonic-gate 			error++;
19277c478bd9Sstevel@tonic-gate 			return;
19287c478bd9Sstevel@tonic-gate 		}
19297c478bd9Sstevel@tonic-gate 		while ((rpid = wait(&retcode)) != pid && rpid != -1)
19307c478bd9Sstevel@tonic-gate 			;
19317c478bd9Sstevel@tonic-gate 		printf("!\n");
19327c478bd9Sstevel@tonic-gate 		goto newline;
19337c478bd9Sstevel@tonic-gate 	}
19347c478bd9Sstevel@tonic-gate 	if (c != '\n')
19357c478bd9Sstevel@tonic-gate 		printf("input truncated to 128 characters\n");
19367c478bd9Sstevel@tonic-gate 	input_buffer[i] = '\n';
19377c478bd9Sstevel@tonic-gate 	input_pointer = 0;
19387c478bd9Sstevel@tonic-gate }
19397c478bd9Sstevel@tonic-gate 
19407c478bd9Sstevel@tonic-gate /*
19417c478bd9Sstevel@tonic-gate  * eat_spaces - read extraneous spaces.
19427c478bd9Sstevel@tonic-gate  */
19437c478bd9Sstevel@tonic-gate static void
eat_spaces()19447c478bd9Sstevel@tonic-gate eat_spaces()
19457c478bd9Sstevel@tonic-gate {
1946d1a180b0Smaheshvs 	char	c;
19477c478bd9Sstevel@tonic-gate 
19487c478bd9Sstevel@tonic-gate 	while ((c = getachar()) == ' ')
19497c478bd9Sstevel@tonic-gate 		;
19507c478bd9Sstevel@tonic-gate 	ungetachar(c);
19517c478bd9Sstevel@tonic-gate }
19527c478bd9Sstevel@tonic-gate 
19537c478bd9Sstevel@tonic-gate /*
19547c478bd9Sstevel@tonic-gate  * restore_inode - set up all inode indicators so inum is now
19557c478bd9Sstevel@tonic-gate  *	the current inode.
19567c478bd9Sstevel@tonic-gate  */
19577c478bd9Sstevel@tonic-gate static void
restore_inode(ino_t inum)1958d1a180b0Smaheshvs restore_inode(ino_t inum)
19597c478bd9Sstevel@tonic-gate {
19607c478bd9Sstevel@tonic-gate 	errinum = cur_inum = inum;
19617c478bd9Sstevel@tonic-gate 	addr = errino = cur_ino = itob(inum);
19627c478bd9Sstevel@tonic-gate }
19637c478bd9Sstevel@tonic-gate 
19647c478bd9Sstevel@tonic-gate /*
19657c478bd9Sstevel@tonic-gate  * match - return false if the input does not match string up to
19667c478bd9Sstevel@tonic-gate  *	upto letters.   Then proceed to chew up extraneous letters.
19677c478bd9Sstevel@tonic-gate  */
19687c478bd9Sstevel@tonic-gate static int
match(char * string,int upto)1969d1a180b0Smaheshvs match(char *string, int upto)
19707c478bd9Sstevel@tonic-gate {
1971d1a180b0Smaheshvs 	int	i, length = strlen(string) - 1;
1972d1a180b0Smaheshvs 	char	c;
19737c478bd9Sstevel@tonic-gate 	int	save_upto = upto;
19747c478bd9Sstevel@tonic-gate 
19757c478bd9Sstevel@tonic-gate 	while (--upto) {
19767c478bd9Sstevel@tonic-gate 		string++;
19777c478bd9Sstevel@tonic-gate 		if ((c = getachar()) != *string) {
19787c478bd9Sstevel@tonic-gate 			for (i = save_upto - upto; i; i--) {
19797c478bd9Sstevel@tonic-gate 				ungetachar(c);
19807c478bd9Sstevel@tonic-gate 				c = *--string;
19817c478bd9Sstevel@tonic-gate 			}
19827c478bd9Sstevel@tonic-gate 			return (0);
19837c478bd9Sstevel@tonic-gate 		}
19847c478bd9Sstevel@tonic-gate 		length--;
19857c478bd9Sstevel@tonic-gate 	}
19867c478bd9Sstevel@tonic-gate 	while (length--) {
19877c478bd9Sstevel@tonic-gate 		string++;
19887c478bd9Sstevel@tonic-gate 		if ((c = getachar()) != *string) {
19897c478bd9Sstevel@tonic-gate 			ungetachar(c);
19907c478bd9Sstevel@tonic-gate 			return (1);
19917c478bd9Sstevel@tonic-gate 		}
19927c478bd9Sstevel@tonic-gate 	}
19937c478bd9Sstevel@tonic-gate 	return (1);
19947c478bd9Sstevel@tonic-gate }
19957c478bd9Sstevel@tonic-gate 
19967c478bd9Sstevel@tonic-gate /*
19977c478bd9Sstevel@tonic-gate  * expr - expression evaluator.  Will evaluate expressions from
19987c478bd9Sstevel@tonic-gate  *	left to right with no operator precedence.  Parentheses may
19997c478bd9Sstevel@tonic-gate  *	be used.
20007c478bd9Sstevel@tonic-gate  */
20017c478bd9Sstevel@tonic-gate static long
expr()20027c478bd9Sstevel@tonic-gate expr()
20037c478bd9Sstevel@tonic-gate {
2004d1a180b0Smaheshvs 	long	numb = 0, temp;
2005d1a180b0Smaheshvs 	char	c;
20067c478bd9Sstevel@tonic-gate 
20077c478bd9Sstevel@tonic-gate 	numb = term();
20087c478bd9Sstevel@tonic-gate 	for (;;) {
20097c478bd9Sstevel@tonic-gate 		if (error)
20107c478bd9Sstevel@tonic-gate 			return (~0);	/* error is set so value is ignored */
20117c478bd9Sstevel@tonic-gate 		c = getachar();
20127c478bd9Sstevel@tonic-gate 		switch (c) {
20137c478bd9Sstevel@tonic-gate 
20147c478bd9Sstevel@tonic-gate 		case '+':
20157c478bd9Sstevel@tonic-gate 			numb += term();
20167c478bd9Sstevel@tonic-gate 			continue;
20177c478bd9Sstevel@tonic-gate 
20187c478bd9Sstevel@tonic-gate 		case '-':
20197c478bd9Sstevel@tonic-gate 			numb -= term();
20207c478bd9Sstevel@tonic-gate 			continue;
20217c478bd9Sstevel@tonic-gate 
20227c478bd9Sstevel@tonic-gate 		case '*':
20237c478bd9Sstevel@tonic-gate 			numb *= term();
20247c478bd9Sstevel@tonic-gate 			continue;
20257c478bd9Sstevel@tonic-gate 
20267c478bd9Sstevel@tonic-gate 		case '%':
20277c478bd9Sstevel@tonic-gate 			temp = term();
20287c478bd9Sstevel@tonic-gate 			if (!temp) {
20297c478bd9Sstevel@tonic-gate 				printf("divide by zero\n");
20307c478bd9Sstevel@tonic-gate 				error++;
20317c478bd9Sstevel@tonic-gate 				return (~0);
20327c478bd9Sstevel@tonic-gate 			}
20337c478bd9Sstevel@tonic-gate 			numb /= temp;
20347c478bd9Sstevel@tonic-gate 			continue;
20357c478bd9Sstevel@tonic-gate 
20367c478bd9Sstevel@tonic-gate 		case ')':
20377c478bd9Sstevel@tonic-gate 			paren--;
20387c478bd9Sstevel@tonic-gate 			return (numb);
20397c478bd9Sstevel@tonic-gate 
20407c478bd9Sstevel@tonic-gate 		default:
20417c478bd9Sstevel@tonic-gate 			ungetachar(c);
20427c478bd9Sstevel@tonic-gate 			if (paren && !error) {
20437c478bd9Sstevel@tonic-gate 				printf("missing ')'\n");
20447c478bd9Sstevel@tonic-gate 				error++;
20457c478bd9Sstevel@tonic-gate 			}
20467c478bd9Sstevel@tonic-gate 			return (numb);
20477c478bd9Sstevel@tonic-gate 		}
20487c478bd9Sstevel@tonic-gate 	}
20497c478bd9Sstevel@tonic-gate }
20507c478bd9Sstevel@tonic-gate 
20517c478bd9Sstevel@tonic-gate /*
20527c478bd9Sstevel@tonic-gate  * term - used by expression evaluator to get an operand.
20537c478bd9Sstevel@tonic-gate  */
20547c478bd9Sstevel@tonic-gate static long
term()20557c478bd9Sstevel@tonic-gate term()
20567c478bd9Sstevel@tonic-gate {
2057d1a180b0Smaheshvs 	char	c;
20587c478bd9Sstevel@tonic-gate 
20597c478bd9Sstevel@tonic-gate 	switch (c = getachar()) {
20607c478bd9Sstevel@tonic-gate 
20617c478bd9Sstevel@tonic-gate 	default:
20627c478bd9Sstevel@tonic-gate 		ungetachar(c);
20637c478bd9Sstevel@tonic-gate 		/*FALLTHRU*/
20647c478bd9Sstevel@tonic-gate 	case '+':
20657c478bd9Sstevel@tonic-gate 		return (getnumb());
20667c478bd9Sstevel@tonic-gate 
20677c478bd9Sstevel@tonic-gate 	case '-':
20687c478bd9Sstevel@tonic-gate 		return (-getnumb());
20697c478bd9Sstevel@tonic-gate 
20707c478bd9Sstevel@tonic-gate 	case '(':
20717c478bd9Sstevel@tonic-gate 		paren++;
20727c478bd9Sstevel@tonic-gate 		return (expr());
20737c478bd9Sstevel@tonic-gate 	}
20747c478bd9Sstevel@tonic-gate }
20757c478bd9Sstevel@tonic-gate 
20767c478bd9Sstevel@tonic-gate /*
20777c478bd9Sstevel@tonic-gate  * getnumb - read a number from the input stream.  A leading
20787c478bd9Sstevel@tonic-gate  *	zero signifies octal interpretation, a leading '0x'
20797c478bd9Sstevel@tonic-gate  *	signifies hexadecimal, and a leading '0t' signifies
20807c478bd9Sstevel@tonic-gate  *	decimal.  If the first character is a character,
20817c478bd9Sstevel@tonic-gate  *	return an error.
20827c478bd9Sstevel@tonic-gate  */
20837c478bd9Sstevel@tonic-gate static long
getnumb()20847c478bd9Sstevel@tonic-gate getnumb()
20857c478bd9Sstevel@tonic-gate {
20867c478bd9Sstevel@tonic-gate 
2087d1a180b0Smaheshvs 	char		c, savec;
20887c478bd9Sstevel@tonic-gate 	long		number = 0, tbase, num;
20897c478bd9Sstevel@tonic-gate 	extern short	error;
20907c478bd9Sstevel@tonic-gate 
20917c478bd9Sstevel@tonic-gate 	c = getachar();
20927c478bd9Sstevel@tonic-gate 	if (!digit(c)) {
20937c478bd9Sstevel@tonic-gate 		error++;
20947c478bd9Sstevel@tonic-gate 		ungetachar(c);
20957c478bd9Sstevel@tonic-gate 		return (-1);
20967c478bd9Sstevel@tonic-gate 	}
20977c478bd9Sstevel@tonic-gate 	if (c == '0') {
20987c478bd9Sstevel@tonic-gate 		tbase = OCTAL;
20997c478bd9Sstevel@tonic-gate 		if ((c = getachar()) == 'x')
21007c478bd9Sstevel@tonic-gate 			tbase = HEX;
21017c478bd9Sstevel@tonic-gate 		else if (c == 't')
21027c478bd9Sstevel@tonic-gate 			tbase = DECIMAL;
21037c478bd9Sstevel@tonic-gate 		else ungetachar(c);
21047c478bd9Sstevel@tonic-gate 	} else {
21057c478bd9Sstevel@tonic-gate 		tbase = base;
21067c478bd9Sstevel@tonic-gate 		ungetachar(c);
21077c478bd9Sstevel@tonic-gate 	}
21087c478bd9Sstevel@tonic-gate 	for (;;) {
21097c478bd9Sstevel@tonic-gate 		num = tbase;
21107c478bd9Sstevel@tonic-gate 		c = savec = getachar();
21117c478bd9Sstevel@tonic-gate 		if (HEXLETTER(c))
21127c478bd9Sstevel@tonic-gate 			c = uppertolower(c);
21137c478bd9Sstevel@tonic-gate 		switch (tbase) {
21147c478bd9Sstevel@tonic-gate 		case HEX:
21157c478bd9Sstevel@tonic-gate 			if (hexletter(c)) {
21167c478bd9Sstevel@tonic-gate 				num = hextodigit(c);
21177c478bd9Sstevel@tonic-gate 				break;
21187c478bd9Sstevel@tonic-gate 			}
21197c478bd9Sstevel@tonic-gate 			/*FALLTHRU*/
21207c478bd9Sstevel@tonic-gate 		case DECIMAL:
21217c478bd9Sstevel@tonic-gate 			if (digit(c))
21227c478bd9Sstevel@tonic-gate 				num = numtodigit(c);
21237c478bd9Sstevel@tonic-gate 			break;
21247c478bd9Sstevel@tonic-gate 		case OCTAL:
21257c478bd9Sstevel@tonic-gate 			if (octaldigit(c))
21267c478bd9Sstevel@tonic-gate 				num = numtodigit(c);
21277c478bd9Sstevel@tonic-gate 		}
21287c478bd9Sstevel@tonic-gate 		if (num == tbase)
21297c478bd9Sstevel@tonic-gate 			break;
21307c478bd9Sstevel@tonic-gate 		number = number * tbase + num;
21317c478bd9Sstevel@tonic-gate 	}
21327c478bd9Sstevel@tonic-gate 	ungetachar(savec);
21337c478bd9Sstevel@tonic-gate 	return (number);
21347c478bd9Sstevel@tonic-gate }
21357c478bd9Sstevel@tonic-gate 
21367c478bd9Sstevel@tonic-gate /*
21377c478bd9Sstevel@tonic-gate  * find - the syntax is almost identical to the unix command.
21387c478bd9Sstevel@tonic-gate  *		find dir [-name pattern] [-inum number]
21397c478bd9Sstevel@tonic-gate  *	Note:  only one of -name or -inum may be used at a time.
21407c478bd9Sstevel@tonic-gate  *	       Also, the -print is not needed (implied).
21417c478bd9Sstevel@tonic-gate  */
21427c478bd9Sstevel@tonic-gate static void
find()21437c478bd9Sstevel@tonic-gate find()
21447c478bd9Sstevel@tonic-gate {
2145d1a180b0Smaheshvs 	struct filenames	*fn;
2146d1a180b0Smaheshvs 	char			c;
21477c478bd9Sstevel@tonic-gate 	long			temp;
21487c478bd9Sstevel@tonic-gate 	short			mode;
21497c478bd9Sstevel@tonic-gate 
21507c478bd9Sstevel@tonic-gate 	eat_spaces();
21517c478bd9Sstevel@tonic-gate 	temp = cur_inum;
21527c478bd9Sstevel@tonic-gate 	top = filenames - 1;
21537c478bd9Sstevel@tonic-gate 	doing_cd = 1;
21547c478bd9Sstevel@tonic-gate 	parse();
21557c478bd9Sstevel@tonic-gate 	doing_cd = 0;
21567c478bd9Sstevel@tonic-gate 	if (nfiles != 1) {
21577c478bd9Sstevel@tonic-gate 		restore_inode((ino_t)temp);
21587c478bd9Sstevel@tonic-gate 		if (!error) {
21597c478bd9Sstevel@tonic-gate 			print_path(input_path, (int)input_pathp);
21607c478bd9Sstevel@tonic-gate 			if (nfiles == 0)
21617c478bd9Sstevel@tonic-gate 				printf(" not found\n");
21627c478bd9Sstevel@tonic-gate 			else
21637c478bd9Sstevel@tonic-gate 				printf(" ambiguous\n");
21647c478bd9Sstevel@tonic-gate 			error++;
21657c478bd9Sstevel@tonic-gate 			return;
21667c478bd9Sstevel@tonic-gate 		}
21677c478bd9Sstevel@tonic-gate 	}
21687c478bd9Sstevel@tonic-gate 	restore_inode(filenames->ino);
21697c478bd9Sstevel@tonic-gate 	freemem(filenames, nfiles);
21707c478bd9Sstevel@tonic-gate 	nfiles = 0;
21717c478bd9Sstevel@tonic-gate 	top = filenames - 1;
21727c478bd9Sstevel@tonic-gate 	if ((mode = icheck(addr)) == 0)
21737c478bd9Sstevel@tonic-gate 		return;
21747c478bd9Sstevel@tonic-gate 	if ((mode & IFMT) != IFDIR) {
21757c478bd9Sstevel@tonic-gate 		print_path(input_path, (int)input_pathp);
21767c478bd9Sstevel@tonic-gate 		printf(" not a directory\n");
21777c478bd9Sstevel@tonic-gate 		error++;
21787c478bd9Sstevel@tonic-gate 		return;
21797c478bd9Sstevel@tonic-gate 	}
21807c478bd9Sstevel@tonic-gate 	eat_spaces();
21817c478bd9Sstevel@tonic-gate 	if ((c = getachar()) != '-') {
21827c478bd9Sstevel@tonic-gate 		restore_inode((ino_t)temp);
21837c478bd9Sstevel@tonic-gate 		printf("missing '-'\n");
21847c478bd9Sstevel@tonic-gate 		error++;
21857c478bd9Sstevel@tonic-gate 		return;
21867c478bd9Sstevel@tonic-gate 	}
21877c478bd9Sstevel@tonic-gate 	find_by_name = find_by_inode = 0;
21887c478bd9Sstevel@tonic-gate 	c = getachar();
21897c478bd9Sstevel@tonic-gate 	if (match("name", 4)) {
21907c478bd9Sstevel@tonic-gate 		eat_spaces();
21917c478bd9Sstevel@tonic-gate 		find_by_name = 1;
21927c478bd9Sstevel@tonic-gate 	} else if (match("inum", 4)) {
21937c478bd9Sstevel@tonic-gate 		eat_spaces();
21947c478bd9Sstevel@tonic-gate 		find_ino = expr();
21957c478bd9Sstevel@tonic-gate 		if (error) {
21967c478bd9Sstevel@tonic-gate 			restore_inode((ino_t)temp);
21977c478bd9Sstevel@tonic-gate 			return;
21987c478bd9Sstevel@tonic-gate 		}
21997c478bd9Sstevel@tonic-gate 		while ((c = getachar()) != '\n')
22007c478bd9Sstevel@tonic-gate 			;
22017c478bd9Sstevel@tonic-gate 		ungetachar(c);
22027c478bd9Sstevel@tonic-gate 		find_by_inode = 1;
22037c478bd9Sstevel@tonic-gate 	} else {
22047c478bd9Sstevel@tonic-gate 		restore_inode((ino_t)temp);
22057c478bd9Sstevel@tonic-gate 		printf("use -name or -inum with find\n");
22067c478bd9Sstevel@tonic-gate 		error++;
22077c478bd9Sstevel@tonic-gate 		return;
22087c478bd9Sstevel@tonic-gate 	}
22097c478bd9Sstevel@tonic-gate 	doing_find = 1;
22107c478bd9Sstevel@tonic-gate 	parse();
22117c478bd9Sstevel@tonic-gate 	doing_find = 0;
22127c478bd9Sstevel@tonic-gate 	if (error) {
22137c478bd9Sstevel@tonic-gate 		restore_inode((ino_t)temp);
22147c478bd9Sstevel@tonic-gate 		return;
22157c478bd9Sstevel@tonic-gate 	}
22167c478bd9Sstevel@tonic-gate 	for (fn = filenames; fn <= top; fn++) {
22177c478bd9Sstevel@tonic-gate 		if (fn->find == 0)
22187c478bd9Sstevel@tonic-gate 			continue;
22197c478bd9Sstevel@tonic-gate 		printf("i#: ");
22207c478bd9Sstevel@tonic-gate 		print(fn->ino, 12, -8, 0);
22217c478bd9Sstevel@tonic-gate 		print_path(fn->fname, (int)fn->len);
22227c478bd9Sstevel@tonic-gate 		printf("\n");
22237c478bd9Sstevel@tonic-gate 	}
22247c478bd9Sstevel@tonic-gate 	restore_inode((ino_t)temp);
22257c478bd9Sstevel@tonic-gate }
22267c478bd9Sstevel@tonic-gate 
22277c478bd9Sstevel@tonic-gate /*
22287c478bd9Sstevel@tonic-gate  * ls - do an ls.  Should behave exactly as ls(1).
22297c478bd9Sstevel@tonic-gate  *	Only -R and -l is supported and -l gives different results.
22307c478bd9Sstevel@tonic-gate  */
22317c478bd9Sstevel@tonic-gate static void
ls(struct filenames * fn0,struct filenames * fnlast,short level)2232d1a180b0Smaheshvs ls(struct filenames *fn0, struct filenames *fnlast, short level)
22337c478bd9Sstevel@tonic-gate {
2234d1a180b0Smaheshvs 	struct filenames	*fn, *fnn;
22357c478bd9Sstevel@tonic-gate 
22367c478bd9Sstevel@tonic-gate 	fn = fn0;
22377c478bd9Sstevel@tonic-gate 	for (;;) {
22387c478bd9Sstevel@tonic-gate 		fn0 = fn;
22397c478bd9Sstevel@tonic-gate 		if (fn0->len) {
22407c478bd9Sstevel@tonic-gate 			cmp_level = level;
22417c478bd9Sstevel@tonic-gate 			qsort((char *)fn0, fnlast - fn0 + 1,
22427c478bd9Sstevel@tonic-gate 				sizeof (struct filenames), fcmp);
22437c478bd9Sstevel@tonic-gate 		}
22447c478bd9Sstevel@tonic-gate 		for (fnn = fn, fn++; fn <= fnlast; fnn = fn, fn++) {
22457c478bd9Sstevel@tonic-gate 			if (fnn->len != fn->len && level == fnn->len - 1)
22467c478bd9Sstevel@tonic-gate 				break;
22477c478bd9Sstevel@tonic-gate 			if (fnn->len == 0)
22487c478bd9Sstevel@tonic-gate 				continue;
22497c478bd9Sstevel@tonic-gate 			if (strcmp(fn->fname[level], fnn->fname[level]))
22507c478bd9Sstevel@tonic-gate 				break;
22517c478bd9Sstevel@tonic-gate 		}
22527c478bd9Sstevel@tonic-gate 		if (fn0->len && level != fn0->len - 1)
22537c478bd9Sstevel@tonic-gate 			ls(fn0, fnn, level + 1);
22547c478bd9Sstevel@tonic-gate 		else {
22557c478bd9Sstevel@tonic-gate 			if (fn0 != filenames)
22567c478bd9Sstevel@tonic-gate 				printf("\n");
22577c478bd9Sstevel@tonic-gate 			print_path(fn0->fname, (int)(fn0->len - 1));
22587c478bd9Sstevel@tonic-gate 			printf(":\n");
22597c478bd9Sstevel@tonic-gate 			if (fn0->len == 0)
22607c478bd9Sstevel@tonic-gate 				cmp_level = level;
22617c478bd9Sstevel@tonic-gate 			else
22627c478bd9Sstevel@tonic-gate 				cmp_level = level + 1;
22637c478bd9Sstevel@tonic-gate 			qsort((char *)fn0, fnn - fn0 + 1,
22647c478bd9Sstevel@tonic-gate 				sizeof (struct filenames), fcmp);
22657c478bd9Sstevel@tonic-gate 			formatf(fn0, fnn);
22667c478bd9Sstevel@tonic-gate 			nfiles -= fnn - fn0 + 1;
22677c478bd9Sstevel@tonic-gate 		}
22687c478bd9Sstevel@tonic-gate 		if (fn > fnlast)
22697c478bd9Sstevel@tonic-gate 			return;
22707c478bd9Sstevel@tonic-gate 	}
22717c478bd9Sstevel@tonic-gate }
22727c478bd9Sstevel@tonic-gate 
22737c478bd9Sstevel@tonic-gate /*
22747c478bd9Sstevel@tonic-gate  * formatf - code lifted from ls.
22757c478bd9Sstevel@tonic-gate  */
22767c478bd9Sstevel@tonic-gate static void
formatf(struct filenames * fn0,struct filenames * fnlast)2277d1a180b0Smaheshvs formatf(struct filenames *fn0, struct filenames *fnlast)
22787c478bd9Sstevel@tonic-gate {
2279d1a180b0Smaheshvs 	struct filenames	*fn;
22807c478bd9Sstevel@tonic-gate 	int			width = 0, w, nentry = fnlast - fn0 + 1;
22817c478bd9Sstevel@tonic-gate 	int			i, j, columns, lines;
22827c478bd9Sstevel@tonic-gate 	char			*cp;
22837c478bd9Sstevel@tonic-gate 
22847c478bd9Sstevel@tonic-gate 	if (long_list) {
22857c478bd9Sstevel@tonic-gate 		columns = 1;
22867c478bd9Sstevel@tonic-gate 	} else {
22877c478bd9Sstevel@tonic-gate 		for (fn = fn0; fn <= fnlast; fn++) {
22887c478bd9Sstevel@tonic-gate 			int len = strlen(fn->fname[cmp_level]) + 2;
22897c478bd9Sstevel@tonic-gate 
22907c478bd9Sstevel@tonic-gate 			if (len > width)
22917c478bd9Sstevel@tonic-gate 				width = len;
22927c478bd9Sstevel@tonic-gate 		}
22937c478bd9Sstevel@tonic-gate 		width = (width + 8) &~ 7;
22947c478bd9Sstevel@tonic-gate 		columns = 80 / width;
22957c478bd9Sstevel@tonic-gate 		if (columns == 0)
22967c478bd9Sstevel@tonic-gate 			columns = 1;
22977c478bd9Sstevel@tonic-gate 	}
22987c478bd9Sstevel@tonic-gate 	lines = (nentry + columns - 1) / columns;
22997c478bd9Sstevel@tonic-gate 	for (i = 0; i < lines; i++) {
23007c478bd9Sstevel@tonic-gate 		for (j = 0; j < columns; j++) {
23017c478bd9Sstevel@tonic-gate 			fn = fn0 + j * lines + i;
23027c478bd9Sstevel@tonic-gate 			if (long_list) {
23037c478bd9Sstevel@tonic-gate 				printf("i#: ");
23047c478bd9Sstevel@tonic-gate 				print(fn->ino, 12, -8, 0);
23057c478bd9Sstevel@tonic-gate 			}
23067c478bd9Sstevel@tonic-gate 			if ((cp = fmtentry(fn)) == NULL) {
23077c478bd9Sstevel@tonic-gate 				printf("cannot read inode %ld\n", fn->ino);
23087c478bd9Sstevel@tonic-gate 				return;
23097c478bd9Sstevel@tonic-gate 			}
23107c478bd9Sstevel@tonic-gate 			printf("%s", cp);
23117c478bd9Sstevel@tonic-gate 			if (fn + lines > fnlast) {
23127c478bd9Sstevel@tonic-gate 				printf("\n");
23137c478bd9Sstevel@tonic-gate 				break;
23147c478bd9Sstevel@tonic-gate 			}
23157c478bd9Sstevel@tonic-gate 			w = strlen(cp);
23167c478bd9Sstevel@tonic-gate 			while (w < width) {
23177c478bd9Sstevel@tonic-gate 				w = (w + 8) &~ 7;
23187c478bd9Sstevel@tonic-gate 				(void) putchar('\t');
23197c478bd9Sstevel@tonic-gate 			}
23207c478bd9Sstevel@tonic-gate 		}
23217c478bd9Sstevel@tonic-gate 	}
23227c478bd9Sstevel@tonic-gate }
23237c478bd9Sstevel@tonic-gate 
23247c478bd9Sstevel@tonic-gate /*
23257c478bd9Sstevel@tonic-gate  * fmtentry - code lifted from ls.
23267c478bd9Sstevel@tonic-gate  */
23277c478bd9Sstevel@tonic-gate static char *
fmtentry(struct filenames * fn)2328d1a180b0Smaheshvs fmtentry(struct filenames *fn)
23297c478bd9Sstevel@tonic-gate {
23307c478bd9Sstevel@tonic-gate 	static char	fmtres[BUFSIZ];
2331d1a180b0Smaheshvs 	struct dinode	*ip;
2332d1a180b0Smaheshvs 	char		*cptr, *cp, *dp;
23337c478bd9Sstevel@tonic-gate 
23347c478bd9Sstevel@tonic-gate 	dp = &fmtres[0];
23357c478bd9Sstevel@tonic-gate 	for (cp = fn->fname[cmp_level]; *cp; cp++) {
23367c478bd9Sstevel@tonic-gate 		if (*cp < ' ' || *cp >= 0177)
23377c478bd9Sstevel@tonic-gate 			*dp++ = '?';
23387c478bd9Sstevel@tonic-gate 		else
23397c478bd9Sstevel@tonic-gate 			*dp++ = *cp;
23407c478bd9Sstevel@tonic-gate 	}
23417c478bd9Sstevel@tonic-gate 	addr = itob(fn->ino);
23427c478bd9Sstevel@tonic-gate 	if ((cptr = getblk(addr)) == 0)
23437c478bd9Sstevel@tonic-gate 		return (NULL);
23447c478bd9Sstevel@tonic-gate 	cptr += blkoff(fs, addr);
23457c478bd9Sstevel@tonic-gate 	/*LINTED*/
23467c478bd9Sstevel@tonic-gate 	ip = (struct dinode *)cptr;
23477c478bd9Sstevel@tonic-gate 	switch (ip->di_mode & IFMT) {
23487c478bd9Sstevel@tonic-gate 	case IFDIR:
23497c478bd9Sstevel@tonic-gate 		*dp++ = '/';
23507c478bd9Sstevel@tonic-gate 		break;
23517c478bd9Sstevel@tonic-gate 	case IFLNK:
23527c478bd9Sstevel@tonic-gate 		*dp++ = '@';
23537c478bd9Sstevel@tonic-gate 		break;
23547c478bd9Sstevel@tonic-gate 	case IFSOCK:
23557c478bd9Sstevel@tonic-gate 		*dp++ = '=';
23567c478bd9Sstevel@tonic-gate 		break;
23577c478bd9Sstevel@tonic-gate #ifdef IFIFO
23587c478bd9Sstevel@tonic-gate 	case IFIFO:
23597c478bd9Sstevel@tonic-gate 		*dp++ = 'p';
23607c478bd9Sstevel@tonic-gate 		break;
23617c478bd9Sstevel@tonic-gate #endif
23627c478bd9Sstevel@tonic-gate 	case IFCHR:
23637c478bd9Sstevel@tonic-gate 	case IFBLK:
23647c478bd9Sstevel@tonic-gate 	case IFREG:
23657c478bd9Sstevel@tonic-gate 		if (ip->di_mode & 0111)
23667c478bd9Sstevel@tonic-gate 			*dp++ = '*';
23677c478bd9Sstevel@tonic-gate 		else
23687c478bd9Sstevel@tonic-gate 			*dp++ = ' ';
23697c478bd9Sstevel@tonic-gate 		break;
23707c478bd9Sstevel@tonic-gate 	default:
23717c478bd9Sstevel@tonic-gate 		*dp++ = '?';
23727c478bd9Sstevel@tonic-gate 
23737c478bd9Sstevel@tonic-gate 	}
23747c478bd9Sstevel@tonic-gate 	*dp++ = 0;
23757c478bd9Sstevel@tonic-gate 	return (fmtres);
23767c478bd9Sstevel@tonic-gate }
23777c478bd9Sstevel@tonic-gate 
23787c478bd9Sstevel@tonic-gate /*
23797c478bd9Sstevel@tonic-gate  * fcmp - routine used by qsort.  Will sort first by name, then
23807c478bd9Sstevel@tonic-gate  *	then by pathname length if names are equal.  Uses global
23817c478bd9Sstevel@tonic-gate  *	cmp_level to tell what component of the path name we are comparing.
23827c478bd9Sstevel@tonic-gate  */
23837c478bd9Sstevel@tonic-gate static int
fcmp(struct filenames * f1,struct filenames * f2)2384d1a180b0Smaheshvs fcmp(struct filenames *f1, struct filenames *f2)
23857c478bd9Sstevel@tonic-gate {
23867c478bd9Sstevel@tonic-gate 	int value;
23877c478bd9Sstevel@tonic-gate 
23887c478bd9Sstevel@tonic-gate 	if ((value = strcmp(f1->fname[cmp_level], f2->fname[cmp_level])))
23897c478bd9Sstevel@tonic-gate 		return (value);
23907c478bd9Sstevel@tonic-gate 	return (f1->len - f2->len);
23917c478bd9Sstevel@tonic-gate }
23927c478bd9Sstevel@tonic-gate 
23937c478bd9Sstevel@tonic-gate /*
23947c478bd9Sstevel@tonic-gate  * ffcmp - routine used by qsort.  Sort only by pathname length.
23957c478bd9Sstevel@tonic-gate  */
23967c478bd9Sstevel@tonic-gate static int
ffcmp(struct filenames * f1,struct filenames * f2)2397d1a180b0Smaheshvs ffcmp(struct filenames *f1, struct filenames *f2)
23987c478bd9Sstevel@tonic-gate {
23997c478bd9Sstevel@tonic-gate 	return (f1->len - f2->len);
24007c478bd9Sstevel@tonic-gate }
24017c478bd9Sstevel@tonic-gate 
24027c478bd9Sstevel@tonic-gate /*
24037c478bd9Sstevel@tonic-gate  * parse - set up the call to follow_path.
24047c478bd9Sstevel@tonic-gate  */
24057c478bd9Sstevel@tonic-gate static void
parse()24067c478bd9Sstevel@tonic-gate parse()
24077c478bd9Sstevel@tonic-gate {
2408d1a180b0Smaheshvs 	int	i;
24097c478bd9Sstevel@tonic-gate 	char	c;
24107c478bd9Sstevel@tonic-gate 
24117c478bd9Sstevel@tonic-gate 	stack_pathp = input_pathp = -1;
24127c478bd9Sstevel@tonic-gate 	if ((c = getachar()) == '/') {
24137c478bd9Sstevel@tonic-gate 		while ((c = getachar()) == '/')
24147c478bd9Sstevel@tonic-gate 			;
24157c478bd9Sstevel@tonic-gate 		ungetachar(c);
24167c478bd9Sstevel@tonic-gate 		cur_inum = 2;
24177c478bd9Sstevel@tonic-gate 		c = getachar();
24187c478bd9Sstevel@tonic-gate 		if ((c == '\n') || ((doing_cd) && (c == ' '))) {
24197c478bd9Sstevel@tonic-gate 			ungetachar(c);
24207c478bd9Sstevel@tonic-gate 			if (doing_cd) {
24217c478bd9Sstevel@tonic-gate 				top++;
24227c478bd9Sstevel@tonic-gate 				top->ino = 2;
24237c478bd9Sstevel@tonic-gate 				top->len = -1;
24247c478bd9Sstevel@tonic-gate 				nfiles = 1;
24257c478bd9Sstevel@tonic-gate 				return;
24267c478bd9Sstevel@tonic-gate 			}
24277c478bd9Sstevel@tonic-gate 		} else
24287c478bd9Sstevel@tonic-gate 			ungetachar(c);
24297c478bd9Sstevel@tonic-gate 	} else {
24307c478bd9Sstevel@tonic-gate 		ungetachar(c);
24317c478bd9Sstevel@tonic-gate 		stack_pathp = current_pathp;
24327c478bd9Sstevel@tonic-gate 		if (!doing_find)
24337c478bd9Sstevel@tonic-gate 			input_pathp = current_pathp;
24347c478bd9Sstevel@tonic-gate 		for (i = 0; i <= current_pathp; i++) {
24357c478bd9Sstevel@tonic-gate 			if (!doing_find)
24367c478bd9Sstevel@tonic-gate 				(void) strcpy(input_path[i], current_path[i]);
24377c478bd9Sstevel@tonic-gate 			(void) strcpy(stack_path[i], current_path[i]);
24387c478bd9Sstevel@tonic-gate 		}
24397c478bd9Sstevel@tonic-gate 	}
24407c478bd9Sstevel@tonic-gate 	getname();
24417c478bd9Sstevel@tonic-gate 	follow_path((long)(stack_pathp + 1), cur_inum);
24427c478bd9Sstevel@tonic-gate }
24437c478bd9Sstevel@tonic-gate 
24447c478bd9Sstevel@tonic-gate /*
24457c478bd9Sstevel@tonic-gate  * follow_path - called by cd, find, and ls.
24467c478bd9Sstevel@tonic-gate  *	input_path holds the name typed by the user.
24477c478bd9Sstevel@tonic-gate  *	stack_path holds the name at the current depth.
24487c478bd9Sstevel@tonic-gate  */
24497c478bd9Sstevel@tonic-gate static void
follow_path(long level,long inum)2450d1a180b0Smaheshvs follow_path(long level, long inum)
24517c478bd9Sstevel@tonic-gate {
2452d1a180b0Smaheshvs 	struct direct		*dirp;
2453d1a180b0Smaheshvs 	char			**ccptr, *cptr;
2454d1a180b0Smaheshvs 	int			i;
24557c478bd9Sstevel@tonic-gate 	struct filenames	*tos, *bos, *fn, *fnn, *fnnn;
24567c478bd9Sstevel@tonic-gate 	long			block;
24577c478bd9Sstevel@tonic-gate 	short			mode;
24587c478bd9Sstevel@tonic-gate 
24597c478bd9Sstevel@tonic-gate 	tos = top + 1;
24607c478bd9Sstevel@tonic-gate 	restore_inode((ino_t)inum);
24617c478bd9Sstevel@tonic-gate 	if ((mode = icheck(addr)) == 0)
24627c478bd9Sstevel@tonic-gate 		return;
24637c478bd9Sstevel@tonic-gate 	if ((mode & IFMT) != IFDIR)
24647c478bd9Sstevel@tonic-gate 	    return;
24657c478bd9Sstevel@tonic-gate 	block = cur_bytes = 0;
24667c478bd9Sstevel@tonic-gate 	while (cur_bytes < filesize) {
24677c478bd9Sstevel@tonic-gate 	    if (block == 0 || bcomp(addr)) {
24687c478bd9Sstevel@tonic-gate 		error = 0;
24697c478bd9Sstevel@tonic-gate 		if ((addr = ((u_offset_t)bmap(block++) <<
24707c478bd9Sstevel@tonic-gate 				(u_offset_t)FRGSHIFT)) == 0)
24717c478bd9Sstevel@tonic-gate 		    break;
24727c478bd9Sstevel@tonic-gate 		if ((cptr = getblk(addr)) == 0)
24737c478bd9Sstevel@tonic-gate 		    break;
24747c478bd9Sstevel@tonic-gate 		cptr += blkoff(fs, addr);
24757c478bd9Sstevel@tonic-gate 	    }
24767c478bd9Sstevel@tonic-gate 		/*LINTED*/
24777c478bd9Sstevel@tonic-gate 	    dirp = (struct direct *)cptr;
24787c478bd9Sstevel@tonic-gate 	    if (dirp->d_ino) {
24797c478bd9Sstevel@tonic-gate 		if (level > input_pathp || doing_find ||
24807c478bd9Sstevel@tonic-gate 			compare(input_path[level], &dirp->d_name[0], 1)) {
24817c478bd9Sstevel@tonic-gate 		    if ((doing_find) &&
24827c478bd9Sstevel@tonic-gate 			((strcmp(dirp->d_name, ".") == 0 ||
24837c478bd9Sstevel@tonic-gate 					strcmp(dirp->d_name, "..") == 0)))
24847c478bd9Sstevel@tonic-gate 			goto duplicate;
24857c478bd9Sstevel@tonic-gate 		    if (++top - filenames >= maxfiles) {
24867c478bd9Sstevel@tonic-gate 			printf("too many files\n");
24877c478bd9Sstevel@tonic-gate 			error++;
24887c478bd9Sstevel@tonic-gate 			return;
24897c478bd9Sstevel@tonic-gate 		    }
24907c478bd9Sstevel@tonic-gate 		    top->fname = (char **)calloc(FIRST_DEPTH, sizeof (char **));
24917c478bd9Sstevel@tonic-gate 		    top->flag = 0;
24927c478bd9Sstevel@tonic-gate 		    if (top->fname == 0) {
24937c478bd9Sstevel@tonic-gate 			printf("out of memory\n");
24947c478bd9Sstevel@tonic-gate 			error++;
24957c478bd9Sstevel@tonic-gate 			return;
24967c478bd9Sstevel@tonic-gate 		    }
24977c478bd9Sstevel@tonic-gate 		    nfiles++;
24987c478bd9Sstevel@tonic-gate 		    top->ino = dirp->d_ino;
24997c478bd9Sstevel@tonic-gate 		    top->len = stack_pathp;
25007c478bd9Sstevel@tonic-gate 		    top->find = 0;
25017c478bd9Sstevel@tonic-gate 		    if (doing_find) {
25027c478bd9Sstevel@tonic-gate 			if (find_by_name) {
25037c478bd9Sstevel@tonic-gate 			    if (compare(input_path[0], &dirp->d_name[0], 1))
25047c478bd9Sstevel@tonic-gate 				top->find = 1;
25057c478bd9Sstevel@tonic-gate 			} else if (find_by_inode)
25067c478bd9Sstevel@tonic-gate 			    if (find_ino == dirp->d_ino)
25077c478bd9Sstevel@tonic-gate 				top->find = 1;
25087c478bd9Sstevel@tonic-gate 		    }
25097c478bd9Sstevel@tonic-gate 		    if (top->len + 1 >= FIRST_DEPTH && top->flag == 0) {
25107c478bd9Sstevel@tonic-gate 			ccptr = (char **)calloc(SECOND_DEPTH, sizeof (char **));
25117c478bd9Sstevel@tonic-gate 			if (ccptr == 0) {
25127c478bd9Sstevel@tonic-gate 			    printf("out of memory\n");
25137c478bd9Sstevel@tonic-gate 			    error++;
25147c478bd9Sstevel@tonic-gate 			    return;
25157c478bd9Sstevel@tonic-gate 			}
25167c478bd9Sstevel@tonic-gate 			for (i = 0; i < FIRST_DEPTH; i++)
25177c478bd9Sstevel@tonic-gate 				ccptr[i] = top->fname[i];
25187c478bd9Sstevel@tonic-gate 			free((char *)top->fname);
25197c478bd9Sstevel@tonic-gate 			top->fname = ccptr;
25207c478bd9Sstevel@tonic-gate 			top->flag = 1;
25217c478bd9Sstevel@tonic-gate 		    }
25227c478bd9Sstevel@tonic-gate 		    if (top->len >= SECOND_DEPTH) {
25237c478bd9Sstevel@tonic-gate 			printf("maximum depth exceeded, try to cd lower\n");
25247c478bd9Sstevel@tonic-gate 			error++;
25257c478bd9Sstevel@tonic-gate 			return;
25267c478bd9Sstevel@tonic-gate 		    }
25277c478bd9Sstevel@tonic-gate 			/*
25287c478bd9Sstevel@tonic-gate 			 * Copy current depth.
25297c478bd9Sstevel@tonic-gate 			 */
25307c478bd9Sstevel@tonic-gate 		    for (i = 0; i <= stack_pathp; i++) {
25317c478bd9Sstevel@tonic-gate 			top->fname[i] = calloc(1, strlen(stack_path[i])+1);
25327c478bd9Sstevel@tonic-gate 			if (top->fname[i] == 0) {
25337c478bd9Sstevel@tonic-gate 			    printf("out of memory\n");
25347c478bd9Sstevel@tonic-gate 			    error++;
25357c478bd9Sstevel@tonic-gate 			    return;
25367c478bd9Sstevel@tonic-gate 			}
25377c478bd9Sstevel@tonic-gate 			(void) strcpy(top->fname[i], stack_path[i]);
25387c478bd9Sstevel@tonic-gate 		    }
25397c478bd9Sstevel@tonic-gate 			/*
25407c478bd9Sstevel@tonic-gate 			 * Check for '.' or '..' typed.
25417c478bd9Sstevel@tonic-gate 			 */
25427c478bd9Sstevel@tonic-gate 		    if ((level <= input_pathp) &&
25437c478bd9Sstevel@tonic-gate 				(strcmp(input_path[level], ".") == 0 ||
25447c478bd9Sstevel@tonic-gate 					strcmp(input_path[level], "..") == 0)) {
25457c478bd9Sstevel@tonic-gate 			if (strcmp(input_path[level], "..") == 0 &&
25467c478bd9Sstevel@tonic-gate 							top->len >= 0) {
25477c478bd9Sstevel@tonic-gate 			    free(top->fname[top->len]);
25487c478bd9Sstevel@tonic-gate 			    top->len -= 1;
25497c478bd9Sstevel@tonic-gate 			}
25507c478bd9Sstevel@tonic-gate 		    } else {
25517c478bd9Sstevel@tonic-gate 			/*
25527c478bd9Sstevel@tonic-gate 			 * Check for duplicates.
25537c478bd9Sstevel@tonic-gate 			 */
25547c478bd9Sstevel@tonic-gate 			if (!doing_cd && !doing_find) {
25557c478bd9Sstevel@tonic-gate 			    for (fn = filenames; fn < top; fn++) {
25567c478bd9Sstevel@tonic-gate 				if (fn->ino == dirp->d_ino &&
25577c478bd9Sstevel@tonic-gate 					    fn->len == stack_pathp + 1) {
25587c478bd9Sstevel@tonic-gate 				    for (i = 0; i < fn->len; i++)
25597c478bd9Sstevel@tonic-gate 					if (strcmp(fn->fname[i], stack_path[i]))
25607c478bd9Sstevel@tonic-gate 					    break;
25617c478bd9Sstevel@tonic-gate 				    if (i != fn->len ||
25627c478bd9Sstevel@tonic-gate 					    strcmp(fn->fname[i], dirp->d_name))
25637c478bd9Sstevel@tonic-gate 					continue;
25647c478bd9Sstevel@tonic-gate 				    freemem(top, 1);
25657c478bd9Sstevel@tonic-gate 				    if (top == filenames)
25667c478bd9Sstevel@tonic-gate 					top = NULL;
25677c478bd9Sstevel@tonic-gate 				    else
25687c478bd9Sstevel@tonic-gate 					top--;
25697c478bd9Sstevel@tonic-gate 					nfiles--;
25707c478bd9Sstevel@tonic-gate 					goto duplicate;
25717c478bd9Sstevel@tonic-gate 				}
25727c478bd9Sstevel@tonic-gate 			    }
25737c478bd9Sstevel@tonic-gate 			}
25747c478bd9Sstevel@tonic-gate 			top->len += 1;
25757c478bd9Sstevel@tonic-gate 			top->fname[top->len] = calloc(1,
25767c478bd9Sstevel@tonic-gate 						strlen(&dirp->d_name[0])+1);
25777c478bd9Sstevel@tonic-gate 			if (top->fname[top->len] == 0) {
25787c478bd9Sstevel@tonic-gate 			    printf("out of memory\n");
25797c478bd9Sstevel@tonic-gate 			    error++;
25807c478bd9Sstevel@tonic-gate 			    return;
25817c478bd9Sstevel@tonic-gate 			}
25827c478bd9Sstevel@tonic-gate 			(void) strcpy(top->fname[top->len], &dirp->d_name[0]);
25837c478bd9Sstevel@tonic-gate 		    }
25847c478bd9Sstevel@tonic-gate 		}
25857c478bd9Sstevel@tonic-gate 	    }
25867c478bd9Sstevel@tonic-gate duplicate:
25877c478bd9Sstevel@tonic-gate 	    addr += dirp->d_reclen;
25887c478bd9Sstevel@tonic-gate 	    cptr += dirp->d_reclen;
25897c478bd9Sstevel@tonic-gate 	    cur_bytes += dirp->d_reclen;
25907c478bd9Sstevel@tonic-gate 	}
25917c478bd9Sstevel@tonic-gate 	if (top < filenames)
25927c478bd9Sstevel@tonic-gate 	    return;
25937c478bd9Sstevel@tonic-gate 	if ((doing_cd && level == input_pathp) ||
25947c478bd9Sstevel@tonic-gate 		(!recursive && !doing_find && level > input_pathp))
25957c478bd9Sstevel@tonic-gate 	    return;
25967c478bd9Sstevel@tonic-gate 	bos = top;
25977c478bd9Sstevel@tonic-gate 	/*
25987c478bd9Sstevel@tonic-gate 	 * Check newly added entries to determine if further expansion
25997c478bd9Sstevel@tonic-gate 	 * is required.
26007c478bd9Sstevel@tonic-gate 	 */
26017c478bd9Sstevel@tonic-gate 	for (fn = tos; fn <= bos; fn++) {
26027c478bd9Sstevel@tonic-gate 		/*
26037c478bd9Sstevel@tonic-gate 		 * Avoid '.' and '..' if beyond input.
26047c478bd9Sstevel@tonic-gate 		 */
26057c478bd9Sstevel@tonic-gate 	    if ((recursive || doing_find) && (level > input_pathp) &&
26067c478bd9Sstevel@tonic-gate 		(strcmp(fn->fname[fn->len], ".") == 0 ||
26077c478bd9Sstevel@tonic-gate 			strcmp(fn->fname[fn->len], "..") == 0))
26087c478bd9Sstevel@tonic-gate 		continue;
26097c478bd9Sstevel@tonic-gate 	    restore_inode(fn->ino);
26107c478bd9Sstevel@tonic-gate 	    if ((mode = icheck(cur_ino)) == 0)
26117c478bd9Sstevel@tonic-gate 		return;
26127c478bd9Sstevel@tonic-gate 	    if ((mode & IFMT) == IFDIR || level < input_pathp) {
26137c478bd9Sstevel@tonic-gate 		/*
26147c478bd9Sstevel@tonic-gate 		 * Set up current depth, remove current entry and
26157c478bd9Sstevel@tonic-gate 		 * continue recursion.
26167c478bd9Sstevel@tonic-gate 		 */
26177c478bd9Sstevel@tonic-gate 		for (i = 0; i <= fn->len; i++)
26187c478bd9Sstevel@tonic-gate 		    (void) strcpy(stack_path[i], fn->fname[i]);
26197c478bd9Sstevel@tonic-gate 		stack_pathp = fn->len;
26207c478bd9Sstevel@tonic-gate 		if (!doing_find &&
26217c478bd9Sstevel@tonic-gate 			(!recursive || (recursive && level <= input_pathp))) {
26227c478bd9Sstevel@tonic-gate 			/*
26237c478bd9Sstevel@tonic-gate 			 * Remove current entry by moving others up.
26247c478bd9Sstevel@tonic-gate 			 */
26257c478bd9Sstevel@tonic-gate 		    freemem(fn, 1);
26267c478bd9Sstevel@tonic-gate 		    fnn = fn;
26277c478bd9Sstevel@tonic-gate 		    for (fnnn = fnn, fnn++; fnn <= top; fnnn = fnn, fnn++) {
26287c478bd9Sstevel@tonic-gate 			fnnn->ino = fnn->ino;
26297c478bd9Sstevel@tonic-gate 			fnnn->len = fnn->len;
26307c478bd9Sstevel@tonic-gate 			if (fnnn->len + 1 < FIRST_DEPTH) {
26317c478bd9Sstevel@tonic-gate 			    fnnn->fname = (char **)calloc(FIRST_DEPTH,
26327c478bd9Sstevel@tonic-gate 							sizeof (char **));
26337c478bd9Sstevel@tonic-gate 			    fnnn->flag = 0;
26347c478bd9Sstevel@tonic-gate 			} else if (fnnn->len < SECOND_DEPTH) {
26357c478bd9Sstevel@tonic-gate 			    fnnn->fname = (char **)calloc(SECOND_DEPTH,
26367c478bd9Sstevel@tonic-gate 							sizeof (char **));
26377c478bd9Sstevel@tonic-gate 			    fnnn->flag = 1;
26387c478bd9Sstevel@tonic-gate 			} else {
26397c478bd9Sstevel@tonic-gate 			    printf("maximum depth exceeded, ");
26407c478bd9Sstevel@tonic-gate 			    printf("try to cd lower\n");
26417c478bd9Sstevel@tonic-gate 			    error++;
26427c478bd9Sstevel@tonic-gate 			    return;
26437c478bd9Sstevel@tonic-gate 			}
26447c478bd9Sstevel@tonic-gate 			for (i = 0; i <= fnn->len; i++)
26457c478bd9Sstevel@tonic-gate 			    fnnn->fname[i] = fnn->fname[i];
26467c478bd9Sstevel@tonic-gate 		    }
26477c478bd9Sstevel@tonic-gate 		    if (fn == tos)
26487c478bd9Sstevel@tonic-gate 			fn--;
26497c478bd9Sstevel@tonic-gate 		    top--;
26507c478bd9Sstevel@tonic-gate 		    bos--;
26517c478bd9Sstevel@tonic-gate 		    nfiles--;
26527c478bd9Sstevel@tonic-gate 		}
26537c478bd9Sstevel@tonic-gate 		follow_path(level + 1, cur_inum);
26547c478bd9Sstevel@tonic-gate 		if (error)
26557c478bd9Sstevel@tonic-gate 			return;
26567c478bd9Sstevel@tonic-gate 	    }
26577c478bd9Sstevel@tonic-gate 	}
26587c478bd9Sstevel@tonic-gate }
26597c478bd9Sstevel@tonic-gate 
26607c478bd9Sstevel@tonic-gate /*
26617c478bd9Sstevel@tonic-gate  * getname - break up the pathname entered by the user into components.
26627c478bd9Sstevel@tonic-gate  */
26637c478bd9Sstevel@tonic-gate static void
getname()26647c478bd9Sstevel@tonic-gate getname()
26657c478bd9Sstevel@tonic-gate {
2666d1a180b0Smaheshvs 	int	i;
26677c478bd9Sstevel@tonic-gate 	char	c;
26687c478bd9Sstevel@tonic-gate 
26697c478bd9Sstevel@tonic-gate 	if ((c = getachar()) == '\n') {
26707c478bd9Sstevel@tonic-gate 	    ungetachar(c);
26717c478bd9Sstevel@tonic-gate 	    return;
26727c478bd9Sstevel@tonic-gate 	}
26737c478bd9Sstevel@tonic-gate 	ungetachar(c);
26747c478bd9Sstevel@tonic-gate 	input_pathp++;
26757c478bd9Sstevel@tonic-gate clear:
26767c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAXNAMLEN; i++)
26777c478bd9Sstevel@tonic-gate 	    input_path[input_pathp][i] = '\0';
26787c478bd9Sstevel@tonic-gate 	for (;;) {
26797c478bd9Sstevel@tonic-gate 	    c = getachar();
26807c478bd9Sstevel@tonic-gate 	    if (c == '\\') {
26817c478bd9Sstevel@tonic-gate 		if ((int)strlen(input_path[input_pathp]) + 1 >= MAXNAMLEN) {
26827c478bd9Sstevel@tonic-gate 		    printf("maximum name length exceeded, ");
26837c478bd9Sstevel@tonic-gate 		    printf("truncating\n");
26847c478bd9Sstevel@tonic-gate 		    return;
26857c478bd9Sstevel@tonic-gate 		}
26867c478bd9Sstevel@tonic-gate 		input_path[input_pathp][strlen(input_path[input_pathp])] = c;
26877c478bd9Sstevel@tonic-gate 		input_path[input_pathp][strlen(input_path[input_pathp])] =
26887c478bd9Sstevel@tonic-gate 						getachar();
26897c478bd9Sstevel@tonic-gate 		continue;
26907c478bd9Sstevel@tonic-gate 	    }
26917c478bd9Sstevel@tonic-gate 	    if (c == ' ' || c == '\n') {
26927c478bd9Sstevel@tonic-gate 		ungetachar(c);
26937c478bd9Sstevel@tonic-gate 		return;
26947c478bd9Sstevel@tonic-gate 	    }
26957c478bd9Sstevel@tonic-gate 	    if (!doing_find && c == '/') {
26967c478bd9Sstevel@tonic-gate 		if (++input_pathp >= MAXPATHLEN) {
26977c478bd9Sstevel@tonic-gate 		    printf("maximum path length exceeded, ");
26987c478bd9Sstevel@tonic-gate 		    printf("truncating\n");
26997c478bd9Sstevel@tonic-gate 		    input_pathp--;
27007c478bd9Sstevel@tonic-gate 		    return;
27017c478bd9Sstevel@tonic-gate 		}
27027c478bd9Sstevel@tonic-gate 		goto clear;
27037c478bd9Sstevel@tonic-gate 	    }
27047c478bd9Sstevel@tonic-gate 	    if ((int)strlen(input_path[input_pathp]) >= MAXNAMLEN) {
27057c478bd9Sstevel@tonic-gate 		printf("maximum name length exceeded, truncating\n");
27067c478bd9Sstevel@tonic-gate 		return;
27077c478bd9Sstevel@tonic-gate 	    }
27087c478bd9Sstevel@tonic-gate 	    input_path[input_pathp][strlen(input_path[input_pathp])] = c;
27097c478bd9Sstevel@tonic-gate 	}
27107c478bd9Sstevel@tonic-gate }
27117c478bd9Sstevel@tonic-gate 
27127c478bd9Sstevel@tonic-gate /*
27137c478bd9Sstevel@tonic-gate  * compare - check if a filename matches the pattern entered by the user.
27147c478bd9Sstevel@tonic-gate  *	Handles '*', '?', and '[]'.
27157c478bd9Sstevel@tonic-gate  */
27167c478bd9Sstevel@tonic-gate static int
compare(char * s1,char * s2,short at_start)2717d1a180b0Smaheshvs compare(char *s1, char *s2, short at_start)
27187c478bd9Sstevel@tonic-gate {
2719d1a180b0Smaheshvs 	char	c, *s;
27207c478bd9Sstevel@tonic-gate 
27217c478bd9Sstevel@tonic-gate 	s = s2;
27227c478bd9Sstevel@tonic-gate 	while ((c = *s1) != NULL) {
27237c478bd9Sstevel@tonic-gate 		if (c == '*') {
27247c478bd9Sstevel@tonic-gate 			if (at_start && s == s2 && !letter(*s2) && !digit(*s2))
27257c478bd9Sstevel@tonic-gate 				return (0);
27267c478bd9Sstevel@tonic-gate 			if (*++s1 == 0)
27277c478bd9Sstevel@tonic-gate 				return (1);
27287c478bd9Sstevel@tonic-gate 			while (*s2) {
27297c478bd9Sstevel@tonic-gate 				if (compare(s1, s2, 0))
27307c478bd9Sstevel@tonic-gate 					return (1);
27317c478bd9Sstevel@tonic-gate 				if (error)
27327c478bd9Sstevel@tonic-gate 					return (0);
27337c478bd9Sstevel@tonic-gate 				s2++;
27347c478bd9Sstevel@tonic-gate 			}
27357c478bd9Sstevel@tonic-gate 		}
27367c478bd9Sstevel@tonic-gate 		if (*s2 == 0)
27377c478bd9Sstevel@tonic-gate 			return (0);
27387c478bd9Sstevel@tonic-gate 		if (c == '\\') {
27397c478bd9Sstevel@tonic-gate 			s1++;
27407c478bd9Sstevel@tonic-gate 			goto compare_chars;
27417c478bd9Sstevel@tonic-gate 		}
27427c478bd9Sstevel@tonic-gate 		if (c == '?') {
27437c478bd9Sstevel@tonic-gate 			if (at_start && s == s2 && !letter(*s2) && !digit(*s2))
27447c478bd9Sstevel@tonic-gate 				return (0);
27457c478bd9Sstevel@tonic-gate 			s1++;
27467c478bd9Sstevel@tonic-gate 			s2++;
27477c478bd9Sstevel@tonic-gate 			continue;
27487c478bd9Sstevel@tonic-gate 		}
27497c478bd9Sstevel@tonic-gate 		if (c == '[') {
27507c478bd9Sstevel@tonic-gate 			s1++;
27517c478bd9Sstevel@tonic-gate 			if (*s2 >= *s1++) {
27527c478bd9Sstevel@tonic-gate 				if (*s1++ != '-') {
27537c478bd9Sstevel@tonic-gate 					printf("missing '-'\n");
27547c478bd9Sstevel@tonic-gate 					error++;
27557c478bd9Sstevel@tonic-gate 					return (0);
27567c478bd9Sstevel@tonic-gate 				}
27577c478bd9Sstevel@tonic-gate 				if (*s2 <= *s1++) {
27587c478bd9Sstevel@tonic-gate 					if (*s1++ != ']') {
27597c478bd9Sstevel@tonic-gate 						printf("missing ']'");
27607c478bd9Sstevel@tonic-gate 						error++;
27617c478bd9Sstevel@tonic-gate 						return (0);
27627c478bd9Sstevel@tonic-gate 					}
27637c478bd9Sstevel@tonic-gate 					s2++;
27647c478bd9Sstevel@tonic-gate 					continue;
27657c478bd9Sstevel@tonic-gate 				}
27667c478bd9Sstevel@tonic-gate 			}
27677c478bd9Sstevel@tonic-gate 		}
27687c478bd9Sstevel@tonic-gate compare_chars:
27697c478bd9Sstevel@tonic-gate 		if (*s1++ == *s2++)
27707c478bd9Sstevel@tonic-gate 			continue;
27717c478bd9Sstevel@tonic-gate 		else
27727c478bd9Sstevel@tonic-gate 			return (0);
27737c478bd9Sstevel@tonic-gate 	}
27747c478bd9Sstevel@tonic-gate 	if (*s1 == *s2)
27757c478bd9Sstevel@tonic-gate 		return (1);
27767c478bd9Sstevel@tonic-gate 	return (0);
27777c478bd9Sstevel@tonic-gate }
27787c478bd9Sstevel@tonic-gate 
27797c478bd9Sstevel@tonic-gate /*
27807c478bd9Sstevel@tonic-gate  * freemem - free the memory allocated to the filenames structure.
27817c478bd9Sstevel@tonic-gate  */
27827c478bd9Sstevel@tonic-gate static void
freemem(struct filenames * p,int numb)2783d1a180b0Smaheshvs freemem(struct filenames *p, int numb)
27847c478bd9Sstevel@tonic-gate {
2785d1a180b0Smaheshvs 	int	i, j;
27867c478bd9Sstevel@tonic-gate 
27877c478bd9Sstevel@tonic-gate 	if (numb == 0)
27887c478bd9Sstevel@tonic-gate 		return;
27897c478bd9Sstevel@tonic-gate 	for (i = 0; i < numb; i++, p++) {
27907c478bd9Sstevel@tonic-gate 		for (j = 0; j <= p->len; j++)
27917c478bd9Sstevel@tonic-gate 			free(p->fname[j]);
27927c478bd9Sstevel@tonic-gate 		free((char *)p->fname);
27937c478bd9Sstevel@tonic-gate 	}
27947c478bd9Sstevel@tonic-gate }
27957c478bd9Sstevel@tonic-gate 
27967c478bd9Sstevel@tonic-gate /*
27977c478bd9Sstevel@tonic-gate  * print_path - print the pathname held in p.
27987c478bd9Sstevel@tonic-gate  */
27997c478bd9Sstevel@tonic-gate static void
print_path(char * p[],int pntr)2800d1a180b0Smaheshvs print_path(char *p[], int pntr)
28017c478bd9Sstevel@tonic-gate {
2802d1a180b0Smaheshvs 	int	i;
28037c478bd9Sstevel@tonic-gate 
28047c478bd9Sstevel@tonic-gate 	printf("/");
28057c478bd9Sstevel@tonic-gate 	if (pntr >= 0) {
28067c478bd9Sstevel@tonic-gate 		for (i = 0; i < pntr; i++)
28077c478bd9Sstevel@tonic-gate 			printf("%s/", p[i]);
28087c478bd9Sstevel@tonic-gate 		printf("%s", p[pntr]);
28097c478bd9Sstevel@tonic-gate 	}
28107c478bd9Sstevel@tonic-gate }
28117c478bd9Sstevel@tonic-gate 
28127c478bd9Sstevel@tonic-gate /*
28137c478bd9Sstevel@tonic-gate  * fill - fill a section with a value or string.
28147c478bd9Sstevel@tonic-gate  *	addr,count:fill=[value, "string"].
28157c478bd9Sstevel@tonic-gate  */
28167c478bd9Sstevel@tonic-gate static void
fill()28177c478bd9Sstevel@tonic-gate fill()
28187c478bd9Sstevel@tonic-gate {
2819d1a180b0Smaheshvs 	char		*cptr;
2820d1a180b0Smaheshvs 	int		i;
28217c478bd9Sstevel@tonic-gate 	short		eof_flag, end = 0, eof = 0;
28227c478bd9Sstevel@tonic-gate 	long		temp, tcount;
28237c478bd9Sstevel@tonic-gate 	u_offset_t	taddr;
28247c478bd9Sstevel@tonic-gate 
28257c478bd9Sstevel@tonic-gate 	if (wrtflag == O_RDONLY) {
28267c478bd9Sstevel@tonic-gate 		printf("not opened for write '-w'\n");
28277c478bd9Sstevel@tonic-gate 		error++;
28287c478bd9Sstevel@tonic-gate 		return;
28297c478bd9Sstevel@tonic-gate 	}
28307c478bd9Sstevel@tonic-gate 	temp = expr();
28317c478bd9Sstevel@tonic-gate 	if (error)
28327c478bd9Sstevel@tonic-gate 		return;
28337c478bd9Sstevel@tonic-gate 	if ((cptr = getblk(addr)) == 0)
28347c478bd9Sstevel@tonic-gate 		return;
28357c478bd9Sstevel@tonic-gate 	if (type == NUMB)
28367c478bd9Sstevel@tonic-gate 		eof_flag = 0;
28377c478bd9Sstevel@tonic-gate 	else
28387c478bd9Sstevel@tonic-gate 		eof_flag = 1;
28397c478bd9Sstevel@tonic-gate 	taddr = addr;
28407c478bd9Sstevel@tonic-gate 	switch (objsz) {
28417c478bd9Sstevel@tonic-gate 	case LONG:
28427c478bd9Sstevel@tonic-gate 		addr &= ~(LONG - 1);
28437c478bd9Sstevel@tonic-gate 		break;
28447c478bd9Sstevel@tonic-gate 	case SHORT:
28457c478bd9Sstevel@tonic-gate 		addr &= ~(SHORT - 1);
28467c478bd9Sstevel@tonic-gate 		temp &= 0177777L;
28477c478bd9Sstevel@tonic-gate 		break;
28487c478bd9Sstevel@tonic-gate 	case CHAR:
28497c478bd9Sstevel@tonic-gate 		temp &= 0377;
28507c478bd9Sstevel@tonic-gate 	}
28517c478bd9Sstevel@tonic-gate 	cur_bytes -= taddr - addr;
28527c478bd9Sstevel@tonic-gate 	cptr += blkoff(fs, addr);
28537c478bd9Sstevel@tonic-gate 	tcount = check_addr(eof_flag, &end, &eof, 0);
28547c478bd9Sstevel@tonic-gate 	for (i = 0; i < tcount; i++) {
28557c478bd9Sstevel@tonic-gate 		switch (objsz) {
28567c478bd9Sstevel@tonic-gate 		case LONG:
28577c478bd9Sstevel@tonic-gate 			/*LINTED*/
28587c478bd9Sstevel@tonic-gate 			*(long *)cptr = temp;
28597c478bd9Sstevel@tonic-gate 			break;
28607c478bd9Sstevel@tonic-gate 		case SHORT:
28617c478bd9Sstevel@tonic-gate 			/*LINTED*/
28627c478bd9Sstevel@tonic-gate 			*(short *)cptr = temp;
28637c478bd9Sstevel@tonic-gate 			break;
28647c478bd9Sstevel@tonic-gate 		case CHAR:
28657c478bd9Sstevel@tonic-gate 			*cptr = temp;
28667c478bd9Sstevel@tonic-gate 		}
28677c478bd9Sstevel@tonic-gate 		cptr += objsz;
28687c478bd9Sstevel@tonic-gate 	}
28697c478bd9Sstevel@tonic-gate 	addr += (tcount - 1) * objsz;
28707c478bd9Sstevel@tonic-gate 	cur_bytes += (tcount - 1) * objsz;
28717c478bd9Sstevel@tonic-gate 	put((u_offset_t)temp, objsz);
28727c478bd9Sstevel@tonic-gate 	if (eof) {
28737c478bd9Sstevel@tonic-gate 		printf("end of file\n");
28747c478bd9Sstevel@tonic-gate 		error++;
28757c478bd9Sstevel@tonic-gate 	} else if (end) {
28767c478bd9Sstevel@tonic-gate 		printf("end of block\n");
28777c478bd9Sstevel@tonic-gate 		error++;
28787c478bd9Sstevel@tonic-gate 	}
28797c478bd9Sstevel@tonic-gate }
28807c478bd9Sstevel@tonic-gate 
28817c478bd9Sstevel@tonic-gate /*
28827c478bd9Sstevel@tonic-gate  * get - read a byte, short or long from the file system.
28837c478bd9Sstevel@tonic-gate  *	The entire block containing the desired item is read
28847c478bd9Sstevel@tonic-gate  *	and the appropriate data is extracted and returned.
28857c478bd9Sstevel@tonic-gate  */
28867c478bd9Sstevel@tonic-gate static offset_t
get(short lngth)2887d1a180b0Smaheshvs get(short lngth)
28887c478bd9Sstevel@tonic-gate {
28897c478bd9Sstevel@tonic-gate 
2890d1a180b0Smaheshvs 	char		*bptr;
28917c478bd9Sstevel@tonic-gate 	u_offset_t	temp = addr;
28927c478bd9Sstevel@tonic-gate 
28937c478bd9Sstevel@tonic-gate 	objsz = lngth;
28947c478bd9Sstevel@tonic-gate 	if (objsz == INODE || objsz == SHORT)
28957c478bd9Sstevel@tonic-gate 		temp &= ~(SHORT - 1);
28967c478bd9Sstevel@tonic-gate 	else if (objsz == DIRECTORY || objsz == LONG || objsz == SHADOW_DATA)
28977c478bd9Sstevel@tonic-gate 		temp &= ~(LONG - 1);
28987c478bd9Sstevel@tonic-gate 	if ((bptr = getblk(temp)) == 0)
28997c478bd9Sstevel@tonic-gate 		return (-1);
29007c478bd9Sstevel@tonic-gate 	bptr += blkoff(fs, temp);
29017c478bd9Sstevel@tonic-gate 	switch (objsz) {
29027c478bd9Sstevel@tonic-gate 	case CHAR:
29037c478bd9Sstevel@tonic-gate 		return ((offset_t)*bptr);
29047c478bd9Sstevel@tonic-gate 	case SHORT:
29057c478bd9Sstevel@tonic-gate 	case INODE:
29067c478bd9Sstevel@tonic-gate 		/*LINTED*/
29077c478bd9Sstevel@tonic-gate 		return ((offset_t)(*(short *)bptr));
29087c478bd9Sstevel@tonic-gate 	case LONG:
29097c478bd9Sstevel@tonic-gate 	case DIRECTORY:
29107c478bd9Sstevel@tonic-gate 	case SHADOW_DATA:
29117c478bd9Sstevel@tonic-gate 		/*LINTED*/
29127c478bd9Sstevel@tonic-gate 		return ((offset_t)(*(long *)bptr));
29137c478bd9Sstevel@tonic-gate 	case U_OFFSET_T:
29147c478bd9Sstevel@tonic-gate 		/*LINTED*/
29157c478bd9Sstevel@tonic-gate 		return (*(offset_t *)bptr);
29167c478bd9Sstevel@tonic-gate 	}
29177c478bd9Sstevel@tonic-gate 	return (0);
29187c478bd9Sstevel@tonic-gate }
29197c478bd9Sstevel@tonic-gate 
29207c478bd9Sstevel@tonic-gate /*
29217c478bd9Sstevel@tonic-gate  * cgrp_check - make sure that we don't bump the cylinder group
29227c478bd9Sstevel@tonic-gate  *	beyond the total number of cylinder groups or before the start.
29237c478bd9Sstevel@tonic-gate  */
29247c478bd9Sstevel@tonic-gate static int
cgrp_check(long cgrp)2925d1a180b0Smaheshvs cgrp_check(long cgrp)
29267c478bd9Sstevel@tonic-gate {
29277c478bd9Sstevel@tonic-gate 	if (cgrp < 0) {
29287c478bd9Sstevel@tonic-gate 		if (objsz == CGRP)
29297c478bd9Sstevel@tonic-gate 			printf("beginning of cylinder groups\n");
29307c478bd9Sstevel@tonic-gate 		else
29317c478bd9Sstevel@tonic-gate 			printf("beginning of super blocks\n");
29327c478bd9Sstevel@tonic-gate 		error++;
29337c478bd9Sstevel@tonic-gate 		return (0);
29347c478bd9Sstevel@tonic-gate 	}
29357c478bd9Sstevel@tonic-gate 	if (cgrp >= fs->fs_ncg) {
29367c478bd9Sstevel@tonic-gate 		if (objsz == CGRP)
29377c478bd9Sstevel@tonic-gate 			printf("end of cylinder groups\n");
29387c478bd9Sstevel@tonic-gate 		else
29397c478bd9Sstevel@tonic-gate 			printf("end of super blocks\n");
29407c478bd9Sstevel@tonic-gate 		error++;
29417c478bd9Sstevel@tonic-gate 		return (0);
29427c478bd9Sstevel@tonic-gate 	}
29437c478bd9Sstevel@tonic-gate 	if (objsz == CGRP)
29447c478bd9Sstevel@tonic-gate 		return (cgtod(fs, cgrp) << FRGSHIFT);
29457c478bd9Sstevel@tonic-gate 	else
29467c478bd9Sstevel@tonic-gate 		return (cgsblock(fs, cgrp) << FRGSHIFT);
29477c478bd9Sstevel@tonic-gate }
29487c478bd9Sstevel@tonic-gate 
29497c478bd9Sstevel@tonic-gate /*
29507c478bd9Sstevel@tonic-gate  * icheck -  make sure we can read the block containing the inode
29517c478bd9Sstevel@tonic-gate  *	and determine the filesize (0 if inode not allocated).  Return
29527c478bd9Sstevel@tonic-gate  *	0 if error otherwise return the mode.
29537c478bd9Sstevel@tonic-gate  */
2954d1a180b0Smaheshvs int
icheck(u_offset_t address)2955d1a180b0Smaheshvs icheck(u_offset_t address)
29567c478bd9Sstevel@tonic-gate {
2957d1a180b0Smaheshvs 	char		*cptr;
2958d1a180b0Smaheshvs 	struct dinode	*ip;
29597c478bd9Sstevel@tonic-gate 
29607c478bd9Sstevel@tonic-gate 	if ((cptr = getblk(address)) == 0)
29617c478bd9Sstevel@tonic-gate 		return (0);
29627c478bd9Sstevel@tonic-gate 	cptr += blkoff(fs, address);
29637c478bd9Sstevel@tonic-gate 	/*LINTED*/
29647c478bd9Sstevel@tonic-gate 	ip = (struct dinode *)cptr;
29657c478bd9Sstevel@tonic-gate 	if ((ip->di_mode & IFMT) == 0) {
29667c478bd9Sstevel@tonic-gate 		if (!override) {
29677c478bd9Sstevel@tonic-gate 			printf("inode not allocated\n");
29687c478bd9Sstevel@tonic-gate 			error++;
29697c478bd9Sstevel@tonic-gate 			return (0);
29707c478bd9Sstevel@tonic-gate 		}
29717c478bd9Sstevel@tonic-gate 		blocksize = filesize = 0;
29727c478bd9Sstevel@tonic-gate 	} else {
29737c478bd9Sstevel@tonic-gate 		trapped++;
29747c478bd9Sstevel@tonic-gate 		filesize = ip->di_size;
29757c478bd9Sstevel@tonic-gate 		blocksize = filesize * 2;
29767c478bd9Sstevel@tonic-gate 	}
29777c478bd9Sstevel@tonic-gate 	return (ip->di_mode);
29787c478bd9Sstevel@tonic-gate }
29797c478bd9Sstevel@tonic-gate 
29807c478bd9Sstevel@tonic-gate /*
29817c478bd9Sstevel@tonic-gate  * getdirslot - get the address of the directory slot desired.
29827c478bd9Sstevel@tonic-gate  */
29837c478bd9Sstevel@tonic-gate static u_offset_t
getdirslot(long slot)2984d1a180b0Smaheshvs getdirslot(long slot)
29857c478bd9Sstevel@tonic-gate {
2986d1a180b0Smaheshvs 	char		*cptr;
2987d1a180b0Smaheshvs 	struct direct	*dirp;
2988d1a180b0Smaheshvs 	short		i;
29897c478bd9Sstevel@tonic-gate 	char		*string = &scratch[0];
29907c478bd9Sstevel@tonic-gate 	short		bod = 0, mode, temp;
29917c478bd9Sstevel@tonic-gate 
29927c478bd9Sstevel@tonic-gate 	if (slot < 0) {
29937c478bd9Sstevel@tonic-gate 		slot = 0;
29947c478bd9Sstevel@tonic-gate 		bod++;
29957c478bd9Sstevel@tonic-gate 	}
29967c478bd9Sstevel@tonic-gate 	if (type != DIRECTORY) {
29977c478bd9Sstevel@tonic-gate 		if (type == BLOCK)
29987c478bd9Sstevel@tonic-gate 			string = "block";
29997c478bd9Sstevel@tonic-gate 		else
30007c478bd9Sstevel@tonic-gate 			string = "fragment";
30017c478bd9Sstevel@tonic-gate 		addr = bod_addr;
30027c478bd9Sstevel@tonic-gate 		if ((cptr = getblk(addr)) == 0)
30037c478bd9Sstevel@tonic-gate 			return (0);
30047c478bd9Sstevel@tonic-gate 		cptr += blkoff(fs, addr);
30057c478bd9Sstevel@tonic-gate 		cur_bytes = 0;
30067c478bd9Sstevel@tonic-gate 		/*LINTED*/
30077c478bd9Sstevel@tonic-gate 		dirp = (struct direct *)cptr;
30087c478bd9Sstevel@tonic-gate 		for (dirslot = 0; dirslot < slot; dirslot++) {
30097c478bd9Sstevel@tonic-gate 			/*LINTED*/
30107c478bd9Sstevel@tonic-gate 			dirp = (struct direct *)cptr;
30117c478bd9Sstevel@tonic-gate 			if (blocksize > filesize) {
30127c478bd9Sstevel@tonic-gate 				if (cur_bytes + (long)dirp->d_reclen >=
30137c478bd9Sstevel@tonic-gate 								filesize) {
30147c478bd9Sstevel@tonic-gate 					printf("end of file\n");
30157c478bd9Sstevel@tonic-gate 					erraddr = addr;
30167c478bd9Sstevel@tonic-gate 					errcur_bytes = cur_bytes;
30177c478bd9Sstevel@tonic-gate 					stringsize = STRINGSIZE(dirp);
30187c478bd9Sstevel@tonic-gate 					error++;
30197c478bd9Sstevel@tonic-gate 					return (addr);
30207c478bd9Sstevel@tonic-gate 				}
30217c478bd9Sstevel@tonic-gate 			} else {
30227c478bd9Sstevel@tonic-gate 				if (cur_bytes + (long)dirp->d_reclen >=
30237c478bd9Sstevel@tonic-gate 								blocksize) {
30247c478bd9Sstevel@tonic-gate 					printf("end of %s\n", string);
30257c478bd9Sstevel@tonic-gate 					erraddr = addr;
30267c478bd9Sstevel@tonic-gate 					errcur_bytes = cur_bytes;
30277c478bd9Sstevel@tonic-gate 					stringsize = STRINGSIZE(dirp);
30287c478bd9Sstevel@tonic-gate 					error++;
30297c478bd9Sstevel@tonic-gate 					return (addr);
30307c478bd9Sstevel@tonic-gate 				}
30317c478bd9Sstevel@tonic-gate 			}
30327c478bd9Sstevel@tonic-gate 			cptr += dirp->d_reclen;
30337c478bd9Sstevel@tonic-gate 			addr += dirp->d_reclen;
30347c478bd9Sstevel@tonic-gate 			cur_bytes += dirp->d_reclen;
30357c478bd9Sstevel@tonic-gate 		}
30367c478bd9Sstevel@tonic-gate 		if (bod) {
30377c478bd9Sstevel@tonic-gate 			if (blocksize > filesize)
30387c478bd9Sstevel@tonic-gate 				printf("beginning of file\n");
30397c478bd9Sstevel@tonic-gate 			else
30407c478bd9Sstevel@tonic-gate 				printf("beginning of %s\n", string);
30417c478bd9Sstevel@tonic-gate 			erraddr = addr;
30427c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
30437c478bd9Sstevel@tonic-gate 			error++;
30447c478bd9Sstevel@tonic-gate 		}
30457c478bd9Sstevel@tonic-gate 		stringsize = STRINGSIZE(dirp);
30467c478bd9Sstevel@tonic-gate 		return (addr);
30477c478bd9Sstevel@tonic-gate 	} else {
30487c478bd9Sstevel@tonic-gate 		addr = cur_ino;
30497c478bd9Sstevel@tonic-gate 		if ((mode = icheck(addr)) == 0)
30507c478bd9Sstevel@tonic-gate 			return (0);
30517c478bd9Sstevel@tonic-gate 		if (!override && (mode & IFDIR) == 0) {
30527c478bd9Sstevel@tonic-gate 			printf("inode is not a directory\n");
30537c478bd9Sstevel@tonic-gate 			error++;
30547c478bd9Sstevel@tonic-gate 			return (0);
30557c478bd9Sstevel@tonic-gate 		}
30567c478bd9Sstevel@tonic-gate 		temp = slot;
30577c478bd9Sstevel@tonic-gate 		i = cur_bytes = 0;
30587c478bd9Sstevel@tonic-gate 		for (;;) {
30597c478bd9Sstevel@tonic-gate 			if (i == 0 || bcomp(addr)) {
30607c478bd9Sstevel@tonic-gate 				error = 0;
30617c478bd9Sstevel@tonic-gate 				if ((addr = (bmap((long)i++) << FRGSHIFT)) == 0)
30627c478bd9Sstevel@tonic-gate 					break;
30637c478bd9Sstevel@tonic-gate 				if ((cptr = getblk(addr)) == 0)
30647c478bd9Sstevel@tonic-gate 					break;
30657c478bd9Sstevel@tonic-gate 				cptr += blkoff(fs, addr);
30667c478bd9Sstevel@tonic-gate 			}
30677c478bd9Sstevel@tonic-gate 			/*LINTED*/
30687c478bd9Sstevel@tonic-gate 			dirp = (struct direct *)cptr;
30697c478bd9Sstevel@tonic-gate 			value = dirp->d_ino;
30707c478bd9Sstevel@tonic-gate 			if (!temp--)
30717c478bd9Sstevel@tonic-gate 				break;
30727c478bd9Sstevel@tonic-gate 			if (cur_bytes + (long)dirp->d_reclen >= filesize) {
30737c478bd9Sstevel@tonic-gate 				printf("end of file\n");
30747c478bd9Sstevel@tonic-gate 				dirslot = slot - temp - 1;
30757c478bd9Sstevel@tonic-gate 				objsz = DIRECTORY;
30767c478bd9Sstevel@tonic-gate 				erraddr = addr;
30777c478bd9Sstevel@tonic-gate 				errcur_bytes = cur_bytes;
30787c478bd9Sstevel@tonic-gate 				stringsize = STRINGSIZE(dirp);
30797c478bd9Sstevel@tonic-gate 				error++;
30807c478bd9Sstevel@tonic-gate 				return (addr);
30817c478bd9Sstevel@tonic-gate 			}
30827c478bd9Sstevel@tonic-gate 			addr += dirp->d_reclen;
30837c478bd9Sstevel@tonic-gate 			cptr += dirp->d_reclen;
30847c478bd9Sstevel@tonic-gate 			cur_bytes += dirp->d_reclen;
30857c478bd9Sstevel@tonic-gate 		}
30867c478bd9Sstevel@tonic-gate 		dirslot = slot;
30877c478bd9Sstevel@tonic-gate 		objsz = DIRECTORY;
30887c478bd9Sstevel@tonic-gate 		if (bod) {
30897c478bd9Sstevel@tonic-gate 			printf("beginning of file\n");
30907c478bd9Sstevel@tonic-gate 			erraddr = addr;
30917c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
30927c478bd9Sstevel@tonic-gate 			error++;
30937c478bd9Sstevel@tonic-gate 		}
30947c478bd9Sstevel@tonic-gate 		stringsize = STRINGSIZE(dirp);
30957c478bd9Sstevel@tonic-gate 		return (addr);
30967c478bd9Sstevel@tonic-gate 	}
30977c478bd9Sstevel@tonic-gate }
30987c478bd9Sstevel@tonic-gate 
30997c478bd9Sstevel@tonic-gate 
31007c478bd9Sstevel@tonic-gate /*
31017c478bd9Sstevel@tonic-gate  * getshadowslot - get the address of the shadow data desired
31027c478bd9Sstevel@tonic-gate  */
31037c478bd9Sstevel@tonic-gate static int
getshadowslot(long shadow)3104d1a180b0Smaheshvs getshadowslot(long shadow)
31057c478bd9Sstevel@tonic-gate {
31067c478bd9Sstevel@tonic-gate 	struct ufs_fsd		fsd;
31077c478bd9Sstevel@tonic-gate 	short			bod = 0, mode;
31087c478bd9Sstevel@tonic-gate 	long			taddr, tcurbytes;
31097c478bd9Sstevel@tonic-gate 
31107c478bd9Sstevel@tonic-gate 	if (shadow < 0) {
31117c478bd9Sstevel@tonic-gate 		shadow = 0;
31127c478bd9Sstevel@tonic-gate 		bod++;
31137c478bd9Sstevel@tonic-gate 	}
31147c478bd9Sstevel@tonic-gate 	if (type != SHADOW_DATA) {
31157c478bd9Sstevel@tonic-gate 		if (shadow < cur_shad) {
31167c478bd9Sstevel@tonic-gate 			printf("can't scan shadow data in reverse\n");
31177c478bd9Sstevel@tonic-gate 			error++;
31187c478bd9Sstevel@tonic-gate 			return (0);
31197c478bd9Sstevel@tonic-gate 		}
31207c478bd9Sstevel@tonic-gate 	} else {
31217c478bd9Sstevel@tonic-gate 		addr = cur_ino;
31227c478bd9Sstevel@tonic-gate 		if ((mode = icheck(addr)) == 0)
31237c478bd9Sstevel@tonic-gate 			return (0);
31247c478bd9Sstevel@tonic-gate 		if (!override && (mode & IFMT) != IFSHAD) {
31257c478bd9Sstevel@tonic-gate 			printf("inode is not a shadow\n");
31267c478bd9Sstevel@tonic-gate 			error++;
31277c478bd9Sstevel@tonic-gate 			return (0);
31287c478bd9Sstevel@tonic-gate 		}
31297c478bd9Sstevel@tonic-gate 		cur_bytes = 0;
31307c478bd9Sstevel@tonic-gate 		cur_shad = 0;
31317c478bd9Sstevel@tonic-gate 		syncshadowscan(1);	/* force synchronization */
31327c478bd9Sstevel@tonic-gate 	}
31337c478bd9Sstevel@tonic-gate 
31347c478bd9Sstevel@tonic-gate 	for (; cur_shad < shadow; cur_shad++) {
31357c478bd9Sstevel@tonic-gate 		taddr = addr;
31367c478bd9Sstevel@tonic-gate 		tcurbytes = cur_bytes;
31377c478bd9Sstevel@tonic-gate 		getshadowdata((long *)&fsd, LONG + LONG);
31387c478bd9Sstevel@tonic-gate 		addr = taddr;
31397c478bd9Sstevel@tonic-gate 		cur_bytes = tcurbytes;
31407c478bd9Sstevel@tonic-gate 		if (cur_bytes + (long)fsd.fsd_size > filesize) {
31417c478bd9Sstevel@tonic-gate 			syncshadowscan(0);
31427c478bd9Sstevel@tonic-gate 			printf("end of file\n");
31437c478bd9Sstevel@tonic-gate 			erraddr = addr;
31447c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
31457c478bd9Sstevel@tonic-gate 			error++;
31467c478bd9Sstevel@tonic-gate 			return (addr);
31477c478bd9Sstevel@tonic-gate 		}
31487c478bd9Sstevel@tonic-gate 		addr += fsd.fsd_size;
31497c478bd9Sstevel@tonic-gate 		cur_bytes += fsd.fsd_size;
31507c478bd9Sstevel@tonic-gate 		syncshadowscan(0);
31517c478bd9Sstevel@tonic-gate 	}
31527c478bd9Sstevel@tonic-gate 	if (type == SHADOW_DATA)
31537c478bd9Sstevel@tonic-gate 		objsz = SHADOW_DATA;
31547c478bd9Sstevel@tonic-gate 	if (bod) {
31557c478bd9Sstevel@tonic-gate 		printf("beginning of file\n");
31567c478bd9Sstevel@tonic-gate 		erraddr = addr;
31577c478bd9Sstevel@tonic-gate 		errcur_bytes = cur_bytes;
31587c478bd9Sstevel@tonic-gate 		error++;
31597c478bd9Sstevel@tonic-gate 	}
31607c478bd9Sstevel@tonic-gate 	return (addr);
31617c478bd9Sstevel@tonic-gate }
31627c478bd9Sstevel@tonic-gate 
31637c478bd9Sstevel@tonic-gate static void
getshadowdata(long * buf,int len)3164d1a180b0Smaheshvs getshadowdata(long *buf, int len)
31657c478bd9Sstevel@tonic-gate {
31667c478bd9Sstevel@tonic-gate 	long	tfsd;
31677c478bd9Sstevel@tonic-gate 
31687c478bd9Sstevel@tonic-gate 	len /= LONG;
31697c478bd9Sstevel@tonic-gate 	for (tfsd = 0; tfsd < len; tfsd++) {
31707c478bd9Sstevel@tonic-gate 		buf[tfsd] = get(SHADOW_DATA);
31717c478bd9Sstevel@tonic-gate 		addr += LONG;
31727c478bd9Sstevel@tonic-gate 		cur_bytes += LONG;
31737c478bd9Sstevel@tonic-gate 		syncshadowscan(0);
31747c478bd9Sstevel@tonic-gate 	}
31757c478bd9Sstevel@tonic-gate }
31767c478bd9Sstevel@tonic-gate 
31777c478bd9Sstevel@tonic-gate static void
syncshadowscan(int force)3178d1a180b0Smaheshvs syncshadowscan(int force)
31797c478bd9Sstevel@tonic-gate {
31807c478bd9Sstevel@tonic-gate 	long	curblkoff;
31817c478bd9Sstevel@tonic-gate 	if (type == SHADOW_DATA && (force ||
31827c478bd9Sstevel@tonic-gate 	    lblkno(fs, addr) != (bhdr.fwd)->blkno)) {
31837c478bd9Sstevel@tonic-gate 		curblkoff = blkoff(fs, cur_bytes);
31847c478bd9Sstevel@tonic-gate 		addr = bmap(lblkno(fs, cur_bytes)) << FRGSHIFT;
31857c478bd9Sstevel@tonic-gate 		addr += curblkoff;
31867c478bd9Sstevel@tonic-gate 		cur_bytes += curblkoff;
31877c478bd9Sstevel@tonic-gate 		(void) getblk(addr);
31887c478bd9Sstevel@tonic-gate 		objsz = SHADOW_DATA;
31897c478bd9Sstevel@tonic-gate 	}
31907c478bd9Sstevel@tonic-gate }
31917c478bd9Sstevel@tonic-gate 
31927c478bd9Sstevel@tonic-gate 
31937c478bd9Sstevel@tonic-gate 
31947c478bd9Sstevel@tonic-gate /*
31957c478bd9Sstevel@tonic-gate  * putf - print a byte as an ascii character if possible.
31967c478bd9Sstevel@tonic-gate  *	The exceptions are tabs, newlines, backslashes
31977c478bd9Sstevel@tonic-gate  *	and nulls which are printed as the standard C
31987c478bd9Sstevel@tonic-gate  *	language escapes. Characters which are not
31997c478bd9Sstevel@tonic-gate  *	recognized are printed as \?.
32007c478bd9Sstevel@tonic-gate  */
32017c478bd9Sstevel@tonic-gate static void
putf(char c)3202d1a180b0Smaheshvs putf(char c)
32037c478bd9Sstevel@tonic-gate {
32047c478bd9Sstevel@tonic-gate 
32057c478bd9Sstevel@tonic-gate 	if (c <= 037 || c >= 0177 || c == '\\') {
32067c478bd9Sstevel@tonic-gate 		printf("\\");
32077c478bd9Sstevel@tonic-gate 		switch (c) {
32087c478bd9Sstevel@tonic-gate 		case '\\':
32097c478bd9Sstevel@tonic-gate 			printf("\\");
32107c478bd9Sstevel@tonic-gate 			break;
32117c478bd9Sstevel@tonic-gate 		case '\t':
32127c478bd9Sstevel@tonic-gate 			printf("t");
32137c478bd9Sstevel@tonic-gate 			break;
32147c478bd9Sstevel@tonic-gate 		case '\n':
32157c478bd9Sstevel@tonic-gate 			printf("n");
32167c478bd9Sstevel@tonic-gate 			break;
32177c478bd9Sstevel@tonic-gate 		case '\0':
32187c478bd9Sstevel@tonic-gate 			printf("0");
32197c478bd9Sstevel@tonic-gate 			break;
32207c478bd9Sstevel@tonic-gate 		default:
32217c478bd9Sstevel@tonic-gate 			printf("?");
32227c478bd9Sstevel@tonic-gate 		}
32237c478bd9Sstevel@tonic-gate 	} else {
32247c478bd9Sstevel@tonic-gate 		printf("%c", c);
32257c478bd9Sstevel@tonic-gate 		printf(" ");
32267c478bd9Sstevel@tonic-gate 	}
32277c478bd9Sstevel@tonic-gate }
32287c478bd9Sstevel@tonic-gate 
32297c478bd9Sstevel@tonic-gate /*
32307c478bd9Sstevel@tonic-gate  * put - write an item into the buffer for the current address
32317c478bd9Sstevel@tonic-gate  *	block.  The value is checked to make sure that it will
32327c478bd9Sstevel@tonic-gate  *	fit in the size given without truncation.  If successful,
32337c478bd9Sstevel@tonic-gate  *	the entire block is written back to the file system.
32347c478bd9Sstevel@tonic-gate  */
32357c478bd9Sstevel@tonic-gate static void
put(u_offset_t item,short lngth)3236d1a180b0Smaheshvs put(u_offset_t item, short lngth)
32377c478bd9Sstevel@tonic-gate {
32387c478bd9Sstevel@tonic-gate 
3239d1a180b0Smaheshvs 	char	*bptr, *sbptr;
32407c478bd9Sstevel@tonic-gate 	long	s_err, nbytes;
32417c478bd9Sstevel@tonic-gate 	long	olditem;
32427c478bd9Sstevel@tonic-gate 
32437c478bd9Sstevel@tonic-gate 	if (wrtflag == O_RDONLY) {
32447c478bd9Sstevel@tonic-gate 		printf("not opened for write '-w'\n");
32457c478bd9Sstevel@tonic-gate 		error++;
32467c478bd9Sstevel@tonic-gate 		return;
32477c478bd9Sstevel@tonic-gate 	}
32487c478bd9Sstevel@tonic-gate 	objsz = lngth;
32497c478bd9Sstevel@tonic-gate 	if ((sbptr = getblk(addr)) == 0)
32507c478bd9Sstevel@tonic-gate 		return;
32517c478bd9Sstevel@tonic-gate 	bptr = sbptr + blkoff(fs, addr);
32527c478bd9Sstevel@tonic-gate 	switch (objsz) {
32537c478bd9Sstevel@tonic-gate 	case LONG:
32547c478bd9Sstevel@tonic-gate 	case DIRECTORY:
32557c478bd9Sstevel@tonic-gate 		/*LINTED*/
32567c478bd9Sstevel@tonic-gate 		olditem = *(long *)bptr;
32577c478bd9Sstevel@tonic-gate 		/*LINTED*/
32587c478bd9Sstevel@tonic-gate 		*(long *)bptr = item;
32597c478bd9Sstevel@tonic-gate 		break;
32607c478bd9Sstevel@tonic-gate 	case SHORT:
32617c478bd9Sstevel@tonic-gate 	case INODE:
32627c478bd9Sstevel@tonic-gate 		/*LINTED*/
32637c478bd9Sstevel@tonic-gate 		olditem = (long)*(short *)bptr;
32647c478bd9Sstevel@tonic-gate 		item &= 0177777L;
32657c478bd9Sstevel@tonic-gate 		/*LINTED*/
32667c478bd9Sstevel@tonic-gate 		*(short *)bptr = item;
32677c478bd9Sstevel@tonic-gate 		break;
32687c478bd9Sstevel@tonic-gate 	case CHAR:
32697c478bd9Sstevel@tonic-gate 		olditem = (long)*bptr;
32707c478bd9Sstevel@tonic-gate 		item &= 0377;
32717c478bd9Sstevel@tonic-gate 		*bptr = lobyte(loword(item));
32727c478bd9Sstevel@tonic-gate 		break;
32737c478bd9Sstevel@tonic-gate 	default:
32747c478bd9Sstevel@tonic-gate 		error++;
32757c478bd9Sstevel@tonic-gate 		return;
32767c478bd9Sstevel@tonic-gate 	}
32777c478bd9Sstevel@tonic-gate 	if ((s_err = llseek(fd, (offset_t)(addr & fs->fs_bmask), 0)) == -1) {
32787c478bd9Sstevel@tonic-gate 		error++;
32797c478bd9Sstevel@tonic-gate 		printf("seek error : %" PRIx64 "\n", addr);
32807c478bd9Sstevel@tonic-gate 		return;
32817c478bd9Sstevel@tonic-gate 	}
32827c478bd9Sstevel@tonic-gate 	if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) {
32837c478bd9Sstevel@tonic-gate 		error++;
32847c478bd9Sstevel@tonic-gate 		printf("write error : addr   = %" PRIx64 "\n", addr);
32857c478bd9Sstevel@tonic-gate 		printf("            : s_err  = %lx\n", s_err);
32867c478bd9Sstevel@tonic-gate 		printf("            : nbytes = %lx\n", nbytes);
32877c478bd9Sstevel@tonic-gate 		return;
32887c478bd9Sstevel@tonic-gate 	}
32897c478bd9Sstevel@tonic-gate 	if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) {
32907c478bd9Sstevel@tonic-gate 		index(base);
32917c478bd9Sstevel@tonic-gate 		print(olditem, 8, -8, 0);
32927c478bd9Sstevel@tonic-gate 		printf("\t=\t");
32937c478bd9Sstevel@tonic-gate 		print(item, 8, -8, 0);
32947c478bd9Sstevel@tonic-gate 		printf("\n");
32957c478bd9Sstevel@tonic-gate 	} else {
32967c478bd9Sstevel@tonic-gate 		if (objsz == DIRECTORY) {
32977c478bd9Sstevel@tonic-gate 			addr = cur_dir;
32987c478bd9Sstevel@tonic-gate 			fprnt('?', 'd');
32997c478bd9Sstevel@tonic-gate 		} else {
33007c478bd9Sstevel@tonic-gate 			addr = cur_ino;
33017c478bd9Sstevel@tonic-gate 			objsz = INODE;
33027c478bd9Sstevel@tonic-gate 			fprnt('?', 'i');
33037c478bd9Sstevel@tonic-gate 		}
33047c478bd9Sstevel@tonic-gate 	}
33057c478bd9Sstevel@tonic-gate }
33067c478bd9Sstevel@tonic-gate 
33077c478bd9Sstevel@tonic-gate /*
33087c478bd9Sstevel@tonic-gate  * getblk - check if the desired block is in the file system.
33097c478bd9Sstevel@tonic-gate  *	Search the incore buffers to see if the block is already
33107c478bd9Sstevel@tonic-gate  *	available. If successful, unlink the buffer control block
33117c478bd9Sstevel@tonic-gate  *	from its position in the buffer list and re-insert it at
33127c478bd9Sstevel@tonic-gate  *	the head of the list.  If failure, use the last buffer
33137c478bd9Sstevel@tonic-gate  *	in the list for the desired block. Again, this control
33147c478bd9Sstevel@tonic-gate  *	block is placed at the head of the list. This process
33157c478bd9Sstevel@tonic-gate  *	will leave commonly requested blocks in the in-core buffers.
33167c478bd9Sstevel@tonic-gate  *	Finally, a pointer to the buffer is returned.
33177c478bd9Sstevel@tonic-gate  */
33187c478bd9Sstevel@tonic-gate static char *
getblk(u_offset_t address)3319d1a180b0Smaheshvs getblk(u_offset_t address)
33207c478bd9Sstevel@tonic-gate {
33217c478bd9Sstevel@tonic-gate 
3322d1a180b0Smaheshvs 	struct lbuf	*bp;
33237c478bd9Sstevel@tonic-gate 	long		s_err, nbytes;
33247c478bd9Sstevel@tonic-gate 	unsigned long	block;
33257c478bd9Sstevel@tonic-gate 
33267c478bd9Sstevel@tonic-gate 	read_requests++;
33277c478bd9Sstevel@tonic-gate 	block = lblkno(fs, address);
33287c478bd9Sstevel@tonic-gate 	if (block >= fragstoblks(fs, fs->fs_size)) {
33297c478bd9Sstevel@tonic-gate 		printf("cannot read block %lu\n", block);
33307c478bd9Sstevel@tonic-gate 		error++;
33317c478bd9Sstevel@tonic-gate 		return (0);
33327c478bd9Sstevel@tonic-gate 	}
33337c478bd9Sstevel@tonic-gate 	for (bp = bhdr.fwd; bp != &bhdr; bp = bp->fwd)
33347c478bd9Sstevel@tonic-gate 		if (bp->valid && bp->blkno == block)
33357c478bd9Sstevel@tonic-gate 			goto xit;
33367c478bd9Sstevel@tonic-gate 	actual_disk_reads++;
33377c478bd9Sstevel@tonic-gate 	bp = bhdr.back;
33387c478bd9Sstevel@tonic-gate 	bp->blkno = block;
33397c478bd9Sstevel@tonic-gate 	bp->valid = 0;
33407c478bd9Sstevel@tonic-gate 	if ((s_err = llseek(fd, (offset_t)(address & fs->fs_bmask), 0)) == -1) {
33417c478bd9Sstevel@tonic-gate 		error++;
33427c478bd9Sstevel@tonic-gate 		printf("seek error : %" PRIx64 "\n", address);
33437c478bd9Sstevel@tonic-gate 		return (0);
33447c478bd9Sstevel@tonic-gate 	}
33457c478bd9Sstevel@tonic-gate 	if ((nbytes = read(fd, bp->blkaddr, BLKSIZE)) != BLKSIZE) {
33467c478bd9Sstevel@tonic-gate 		error++;
33477c478bd9Sstevel@tonic-gate 		printf("read error : addr   = %" PRIx64 "\n", address);
33487c478bd9Sstevel@tonic-gate 		printf("           : s_err  = %lx\n", s_err);
33497c478bd9Sstevel@tonic-gate 		printf("           : nbytes = %lx\n", nbytes);
33507c478bd9Sstevel@tonic-gate 		return (0);
33517c478bd9Sstevel@tonic-gate 	}
33527c478bd9Sstevel@tonic-gate 	bp->valid++;
33537c478bd9Sstevel@tonic-gate xit:	bp->back->fwd = bp->fwd;
33547c478bd9Sstevel@tonic-gate 	bp->fwd->back = bp->back;
33557c478bd9Sstevel@tonic-gate 	insert(bp);
33567c478bd9Sstevel@tonic-gate 	return (bp->blkaddr);
33577c478bd9Sstevel@tonic-gate }
33587c478bd9Sstevel@tonic-gate 
33597c478bd9Sstevel@tonic-gate /*
33607c478bd9Sstevel@tonic-gate  * insert - place the designated buffer control block
33617c478bd9Sstevel@tonic-gate  *	at the head of the linked list of buffers.
33627c478bd9Sstevel@tonic-gate  */
33637c478bd9Sstevel@tonic-gate static void
insert(struct lbuf * bp)3364d1a180b0Smaheshvs insert(struct lbuf *bp)
33657c478bd9Sstevel@tonic-gate {
33667c478bd9Sstevel@tonic-gate 
33677c478bd9Sstevel@tonic-gate 	bp->back = &bhdr;
33687c478bd9Sstevel@tonic-gate 	bp->fwd = bhdr.fwd;
33697c478bd9Sstevel@tonic-gate 	bhdr.fwd->back = bp;
33707c478bd9Sstevel@tonic-gate 	bhdr.fwd = bp;
33717c478bd9Sstevel@tonic-gate }
33727c478bd9Sstevel@tonic-gate 
33737c478bd9Sstevel@tonic-gate /*
33747c478bd9Sstevel@tonic-gate  * err - called on interrupts.  Set the current address
33757c478bd9Sstevel@tonic-gate  *	back to the last address stored in erraddr. Reset all
33767c478bd9Sstevel@tonic-gate  *	appropriate flags.  A reset call is made to return
33777c478bd9Sstevel@tonic-gate  *	to the main loop;
33787c478bd9Sstevel@tonic-gate  */
33797c478bd9Sstevel@tonic-gate #ifdef sun
33807c478bd9Sstevel@tonic-gate /*ARGSUSED*/
33817c478bd9Sstevel@tonic-gate static void
err(int sig)3382d1a180b0Smaheshvs err(int sig)
33837c478bd9Sstevel@tonic-gate #else
33847c478bd9Sstevel@tonic-gate err()
33857c478bd9Sstevel@tonic-gate #endif /* sun */
33867c478bd9Sstevel@tonic-gate {
33877c478bd9Sstevel@tonic-gate 	freemem(filenames, nfiles);
33887c478bd9Sstevel@tonic-gate 	nfiles = 0;
33897c478bd9Sstevel@tonic-gate 	(void) signal(2, err);
33907c478bd9Sstevel@tonic-gate 	addr = erraddr;
33917c478bd9Sstevel@tonic-gate 	cur_ino = errino;
33927c478bd9Sstevel@tonic-gate 	cur_inum = errinum;
33937c478bd9Sstevel@tonic-gate 	cur_bytes = errcur_bytes;
33947c478bd9Sstevel@tonic-gate 	error = 0;
33957c478bd9Sstevel@tonic-gate 	c_count = 0;
33967c478bd9Sstevel@tonic-gate 	printf("\n?\n");
33977c478bd9Sstevel@tonic-gate 	(void) fseek(stdin, 0L, 2);
33987c478bd9Sstevel@tonic-gate 	longjmp(env, 0);
33997c478bd9Sstevel@tonic-gate }
34007c478bd9Sstevel@tonic-gate 
34017c478bd9Sstevel@tonic-gate /*
34027c478bd9Sstevel@tonic-gate  * devcheck - check that the given mode represents a
34037c478bd9Sstevel@tonic-gate  *	special device. The IFCHR bit is on for both
34047c478bd9Sstevel@tonic-gate  *	character and block devices.
34057c478bd9Sstevel@tonic-gate  */
34067c478bd9Sstevel@tonic-gate static int
devcheck(short md)3407d1a180b0Smaheshvs devcheck(short md)
34087c478bd9Sstevel@tonic-gate {
34097c478bd9Sstevel@tonic-gate 	if (override)
34107c478bd9Sstevel@tonic-gate 		return (0);
34117c478bd9Sstevel@tonic-gate 	switch (md & IFMT) {
34127c478bd9Sstevel@tonic-gate 	case IFCHR:
34137c478bd9Sstevel@tonic-gate 	case IFBLK:
34147c478bd9Sstevel@tonic-gate 		return (0);
34157c478bd9Sstevel@tonic-gate 	}
34167c478bd9Sstevel@tonic-gate 
34177c478bd9Sstevel@tonic-gate 	printf("not character or block device\n");
34187c478bd9Sstevel@tonic-gate 	error++;
34197c478bd9Sstevel@tonic-gate 	return (1);
34207c478bd9Sstevel@tonic-gate }
34217c478bd9Sstevel@tonic-gate 
34227c478bd9Sstevel@tonic-gate /*
34237c478bd9Sstevel@tonic-gate  * nullblk - return error if address is zero.  This is done
34247c478bd9Sstevel@tonic-gate  *	to prevent block 0 from being used as an indirect block
34257c478bd9Sstevel@tonic-gate  *	for a large file or as a data block for a small file.
34267c478bd9Sstevel@tonic-gate  */
34277c478bd9Sstevel@tonic-gate static int
nullblk(long bn)3428d1a180b0Smaheshvs nullblk(long bn)
34297c478bd9Sstevel@tonic-gate {
34307c478bd9Sstevel@tonic-gate 	if (bn != 0)
34317c478bd9Sstevel@tonic-gate 		return (0);
34327c478bd9Sstevel@tonic-gate 	printf("non existent block\n");
34337c478bd9Sstevel@tonic-gate 	error++;
34347c478bd9Sstevel@tonic-gate 	return (1);
34357c478bd9Sstevel@tonic-gate }
34367c478bd9Sstevel@tonic-gate 
34377c478bd9Sstevel@tonic-gate /*
34387c478bd9Sstevel@tonic-gate  * puta - put ascii characters into a buffer.  The string
34397c478bd9Sstevel@tonic-gate  *	terminates with a quote or newline.  The leading quote,
34407c478bd9Sstevel@tonic-gate  *	which is optional for directory names, was stripped off
34417c478bd9Sstevel@tonic-gate  *	by the assignment case in the main loop.
34427c478bd9Sstevel@tonic-gate  */
34437c478bd9Sstevel@tonic-gate static void
puta()34447c478bd9Sstevel@tonic-gate puta()
34457c478bd9Sstevel@tonic-gate {
3446d1a180b0Smaheshvs 	char		*cptr, c;
3447d1a180b0Smaheshvs 	int		i;
34487c478bd9Sstevel@tonic-gate 	char		*sbptr;
34497c478bd9Sstevel@tonic-gate 	short		terror = 0;
34507c478bd9Sstevel@tonic-gate 	long		maxchars, s_err, nbytes, temp;
34517c478bd9Sstevel@tonic-gate 	u_offset_t	taddr = addr;
34527c478bd9Sstevel@tonic-gate 	long		tcount = 0, item, olditem = 0;
34537c478bd9Sstevel@tonic-gate 
34547c478bd9Sstevel@tonic-gate 	if (wrtflag == O_RDONLY) {
34557c478bd9Sstevel@tonic-gate 		printf("not opened for write '-w'\n");
34567c478bd9Sstevel@tonic-gate 		error++;
34577c478bd9Sstevel@tonic-gate 		return;
34587c478bd9Sstevel@tonic-gate 	}
34597c478bd9Sstevel@tonic-gate 	if ((sbptr = getblk(addr)) == 0)
34607c478bd9Sstevel@tonic-gate 		return;
34617c478bd9Sstevel@tonic-gate 	cptr = sbptr + blkoff(fs, addr);
34627c478bd9Sstevel@tonic-gate 	if (objsz == DIRECTORY) {
34637c478bd9Sstevel@tonic-gate 		if (acting_on_directory)
34647c478bd9Sstevel@tonic-gate 			maxchars = stringsize - 1;
34657c478bd9Sstevel@tonic-gate 		else
34667c478bd9Sstevel@tonic-gate 			maxchars = LONG;
34677c478bd9Sstevel@tonic-gate 	} else if (objsz == INODE)
34687c478bd9Sstevel@tonic-gate 		maxchars = objsz - (addr - cur_ino);
34697c478bd9Sstevel@tonic-gate 	else
34707c478bd9Sstevel@tonic-gate 		maxchars = min(blocksize - cur_bytes, filesize - cur_bytes);
34717c478bd9Sstevel@tonic-gate 	while ((c = getachar()) != '"') {
34727c478bd9Sstevel@tonic-gate 		if (tcount >= maxchars) {
34737c478bd9Sstevel@tonic-gate 			printf("string too long\n");
34747c478bd9Sstevel@tonic-gate 			if (objsz == DIRECTORY)
34757c478bd9Sstevel@tonic-gate 				addr = cur_dir;
34767c478bd9Sstevel@tonic-gate 			else if (acting_on_inode || objsz == INODE)
34777c478bd9Sstevel@tonic-gate 				addr = cur_ino;
34787c478bd9Sstevel@tonic-gate 			else
34797c478bd9Sstevel@tonic-gate 				addr = taddr;
34807c478bd9Sstevel@tonic-gate 			erraddr = addr;
34817c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
34827c478bd9Sstevel@tonic-gate 			terror++;
34837c478bd9Sstevel@tonic-gate 			break;
34847c478bd9Sstevel@tonic-gate 		}
34857c478bd9Sstevel@tonic-gate 		tcount++;
34867c478bd9Sstevel@tonic-gate 		if (c == '\n') {
34877c478bd9Sstevel@tonic-gate 			ungetachar(c);
34887c478bd9Sstevel@tonic-gate 			break;
34897c478bd9Sstevel@tonic-gate 		}
34907c478bd9Sstevel@tonic-gate 		temp = (long)*cptr;
34917c478bd9Sstevel@tonic-gate 		olditem <<= BITSPERCHAR;
34927c478bd9Sstevel@tonic-gate 		olditem += temp & 0xff;
34937c478bd9Sstevel@tonic-gate 		if (c == '\\') {
34947c478bd9Sstevel@tonic-gate 			switch (c = getachar()) {
34957c478bd9Sstevel@tonic-gate 			case 't':
34967c478bd9Sstevel@tonic-gate 				*cptr++ = '\t';
34977c478bd9Sstevel@tonic-gate 				break;
34987c478bd9Sstevel@tonic-gate 			case 'n':
34997c478bd9Sstevel@tonic-gate 				*cptr++ = '\n';
35007c478bd9Sstevel@tonic-gate 				break;
35017c478bd9Sstevel@tonic-gate 			case '0':
35027c478bd9Sstevel@tonic-gate 				*cptr++ = '\0';
35037c478bd9Sstevel@tonic-gate 				break;
35047c478bd9Sstevel@tonic-gate 			default:
35057c478bd9Sstevel@tonic-gate 				*cptr++ = c;
35067c478bd9Sstevel@tonic-gate 				break;
35077c478bd9Sstevel@tonic-gate 			}
35087c478bd9Sstevel@tonic-gate 		}
35097c478bd9Sstevel@tonic-gate 		else
35107c478bd9Sstevel@tonic-gate 			*cptr++ = c;
35117c478bd9Sstevel@tonic-gate 	}
35127c478bd9Sstevel@tonic-gate 	if (objsz == DIRECTORY && acting_on_directory)
35137c478bd9Sstevel@tonic-gate 		for (i = tcount; i <= maxchars; i++)
35147c478bd9Sstevel@tonic-gate 			*cptr++ = '\0';
35157c478bd9Sstevel@tonic-gate 	if ((s_err = llseek(fd, (offset_t)(addr & fs->fs_bmask), 0)) == -1) {
35167c478bd9Sstevel@tonic-gate 		error++;
35177c478bd9Sstevel@tonic-gate 		printf("seek error : %" PRIx64 "\n", addr);
35187c478bd9Sstevel@tonic-gate 		return;
35197c478bd9Sstevel@tonic-gate 	}
35207c478bd9Sstevel@tonic-gate 	if ((nbytes = write(fd, sbptr, BLKSIZE)) != BLKSIZE) {
35217c478bd9Sstevel@tonic-gate 		error++;
35227c478bd9Sstevel@tonic-gate 		printf("write error : addr   = %" PRIx64 "\n", addr);
35237c478bd9Sstevel@tonic-gate 		printf("            : s_err  = %lx\n", s_err);
35247c478bd9Sstevel@tonic-gate 		printf("            : nbytes = %lx\n", nbytes);
35257c478bd9Sstevel@tonic-gate 		return;
35267c478bd9Sstevel@tonic-gate 	}
35277c478bd9Sstevel@tonic-gate 	if (!acting_on_inode && objsz != INODE && objsz != DIRECTORY) {
35287c478bd9Sstevel@tonic-gate 		addr += tcount;
35297c478bd9Sstevel@tonic-gate 		cur_bytes += tcount;
35307c478bd9Sstevel@tonic-gate 		taddr = addr;
35317c478bd9Sstevel@tonic-gate 		if (objsz != CHAR) {
35327c478bd9Sstevel@tonic-gate 			addr &= ~(objsz - 1);
35337c478bd9Sstevel@tonic-gate 			cur_bytes -= taddr - addr;
35347c478bd9Sstevel@tonic-gate 		}
35357c478bd9Sstevel@tonic-gate 		if (addr == taddr) {
35367c478bd9Sstevel@tonic-gate 			addr -= objsz;
35377c478bd9Sstevel@tonic-gate 			taddr = addr;
35387c478bd9Sstevel@tonic-gate 		}
35397c478bd9Sstevel@tonic-gate 		tcount = LONG - (taddr - addr);
35407c478bd9Sstevel@tonic-gate 		index(base);
35417c478bd9Sstevel@tonic-gate 		if ((cptr = getblk(addr)) == 0)
35427c478bd9Sstevel@tonic-gate 			return;
35437c478bd9Sstevel@tonic-gate 		cptr += blkoff(fs, addr);
35447c478bd9Sstevel@tonic-gate 		switch (objsz) {
35457c478bd9Sstevel@tonic-gate 		case LONG:
35467c478bd9Sstevel@tonic-gate 			/*LINTED*/
35477c478bd9Sstevel@tonic-gate 			item = *(long *)cptr;
35487c478bd9Sstevel@tonic-gate 			if (tcount < LONG) {
35497c478bd9Sstevel@tonic-gate 				olditem <<= tcount * BITSPERCHAR;
35507c478bd9Sstevel@tonic-gate 				temp = 1;
35517c478bd9Sstevel@tonic-gate 				for (i = 0; i < (tcount*BITSPERCHAR); i++)
35527c478bd9Sstevel@tonic-gate 					temp <<= 1;
35537c478bd9Sstevel@tonic-gate 				olditem += item & (temp - 1);
35547c478bd9Sstevel@tonic-gate 			}
35557c478bd9Sstevel@tonic-gate 			break;
35567c478bd9Sstevel@tonic-gate 		case SHORT:
35577c478bd9Sstevel@tonic-gate 			/*LINTED*/
35587c478bd9Sstevel@tonic-gate 			item = (long)*(short *)cptr;
35597c478bd9Sstevel@tonic-gate 			if (tcount < SHORT) {
35607c478bd9Sstevel@tonic-gate 				olditem <<= tcount * BITSPERCHAR;
35617c478bd9Sstevel@tonic-gate 				temp = 1;
35627c478bd9Sstevel@tonic-gate 				for (i = 0; i < (tcount * BITSPERCHAR); i++)
35637c478bd9Sstevel@tonic-gate 					temp <<= 1;
35647c478bd9Sstevel@tonic-gate 				olditem += item & (temp - 1);
35657c478bd9Sstevel@tonic-gate 			}
35667c478bd9Sstevel@tonic-gate 			olditem &= 0177777L;
35677c478bd9Sstevel@tonic-gate 			break;
35687c478bd9Sstevel@tonic-gate 		case CHAR:
35697c478bd9Sstevel@tonic-gate 			item = (long)*cptr;
35707c478bd9Sstevel@tonic-gate 			olditem &= 0377;
35717c478bd9Sstevel@tonic-gate 		}
35727c478bd9Sstevel@tonic-gate 		print(olditem, 8, -8, 0);
35737c478bd9Sstevel@tonic-gate 		printf("\t=\t");
35747c478bd9Sstevel@tonic-gate 		print(item, 8, -8, 0);
35757c478bd9Sstevel@tonic-gate 		printf("\n");
35767c478bd9Sstevel@tonic-gate 	} else {
35777c478bd9Sstevel@tonic-gate 		if (objsz == DIRECTORY) {
35787c478bd9Sstevel@tonic-gate 			addr = cur_dir;
35797c478bd9Sstevel@tonic-gate 			fprnt('?', 'd');
35807c478bd9Sstevel@tonic-gate 		} else {
35817c478bd9Sstevel@tonic-gate 			addr = cur_ino;
35827c478bd9Sstevel@tonic-gate 			objsz = INODE;
35837c478bd9Sstevel@tonic-gate 			fprnt('?', 'i');
35847c478bd9Sstevel@tonic-gate 		}
35857c478bd9Sstevel@tonic-gate 	}
35867c478bd9Sstevel@tonic-gate 	if (terror)
35877c478bd9Sstevel@tonic-gate 		error++;
35887c478bd9Sstevel@tonic-gate }
35897c478bd9Sstevel@tonic-gate 
35907c478bd9Sstevel@tonic-gate /*
35917c478bd9Sstevel@tonic-gate  * fprnt - print data.  'count' elements are printed where '*' will
35927c478bd9Sstevel@tonic-gate  *	print an entire blocks worth or up to the eof, whichever
35937c478bd9Sstevel@tonic-gate  *	occurs first.  An error will occur if crossing a block boundary
35947c478bd9Sstevel@tonic-gate  *	is attempted since consecutive blocks don't usually have
35957c478bd9Sstevel@tonic-gate  *	meaning.  Current print types:
35967c478bd9Sstevel@tonic-gate  *		/		b   - print as bytes (base sensitive)
35977c478bd9Sstevel@tonic-gate  *				c   - print as characters
35987c478bd9Sstevel@tonic-gate  *				o O - print as octal shorts (longs)
35997c478bd9Sstevel@tonic-gate  *				d D - print as decimal shorts (longs)
36007c478bd9Sstevel@tonic-gate  *				x X - print as hexadecimal shorts (longs)
36017c478bd9Sstevel@tonic-gate  *		?		c   - print as cylinder groups
36027c478bd9Sstevel@tonic-gate  *				d   - print as directories
36037c478bd9Sstevel@tonic-gate  *				i   - print as inodes
36047c478bd9Sstevel@tonic-gate  *				s   - print as super blocks
36057c478bd9Sstevel@tonic-gate  *				S   - print as shadow data
36067c478bd9Sstevel@tonic-gate  */
36077c478bd9Sstevel@tonic-gate static void
fprnt(char style,char po)3608d1a180b0Smaheshvs fprnt(char style, char po)
36097c478bd9Sstevel@tonic-gate {
3610d1a180b0Smaheshvs 	int		i;
3611d1a180b0Smaheshvs 	struct fs	*sb;
3612d1a180b0Smaheshvs 	struct cg	*cg;
3613d1a180b0Smaheshvs 	struct direct	*dirp;
3614d1a180b0Smaheshvs 	struct dinode	*ip;
36157c478bd9Sstevel@tonic-gate 	int		tbase;
36167c478bd9Sstevel@tonic-gate 	char		c, *cptr, *p;
36177c478bd9Sstevel@tonic-gate 	long		tinode, tcount, temp;
36187c478bd9Sstevel@tonic-gate 	u_offset_t	taddr;
36197c478bd9Sstevel@tonic-gate 	short		offset, mode, end = 0, eof = 0, eof_flag;
36207c478bd9Sstevel@tonic-gate 	unsigned short	*sptr;
36217c478bd9Sstevel@tonic-gate 	unsigned long	*lptr;
36227c478bd9Sstevel@tonic-gate 	offset_t	curoff, curioff;
36237c478bd9Sstevel@tonic-gate 
36247c478bd9Sstevel@tonic-gate 	laststyle = style;
36257c478bd9Sstevel@tonic-gate 	lastpo = po;
36267c478bd9Sstevel@tonic-gate 	should_print = 0;
36277c478bd9Sstevel@tonic-gate 	if (count != 1) {
36287c478bd9Sstevel@tonic-gate 		if (clear) {
36297c478bd9Sstevel@tonic-gate 			count = 1;
36307c478bd9Sstevel@tonic-gate 			star = 0;
36317c478bd9Sstevel@tonic-gate 			clear = 0;
36327c478bd9Sstevel@tonic-gate 		} else
36337c478bd9Sstevel@tonic-gate 			clear = 1;
36347c478bd9Sstevel@tonic-gate 	}
36357c478bd9Sstevel@tonic-gate 	tcount = count;
36367c478bd9Sstevel@tonic-gate 	offset = blkoff(fs, addr);
36377c478bd9Sstevel@tonic-gate 
36387c478bd9Sstevel@tonic-gate 	if (style == '/') {
36397c478bd9Sstevel@tonic-gate 		if (type == NUMB)
36407c478bd9Sstevel@tonic-gate 			eof_flag = 0;
36417c478bd9Sstevel@tonic-gate 		else
36427c478bd9Sstevel@tonic-gate 			eof_flag = 1;
36437c478bd9Sstevel@tonic-gate 		switch (po) {
36447c478bd9Sstevel@tonic-gate 
36457c478bd9Sstevel@tonic-gate 		case 'c': /* print as characters */
36467c478bd9Sstevel@tonic-gate 		case 'b': /* or bytes */
36477c478bd9Sstevel@tonic-gate 			if ((cptr = getblk(addr)) == 0)
36487c478bd9Sstevel@tonic-gate 				return;
36497c478bd9Sstevel@tonic-gate 			cptr += offset;
36507c478bd9Sstevel@tonic-gate 			objsz = CHAR;
36517c478bd9Sstevel@tonic-gate 			tcount = check_addr(eof_flag, &end, &eof, 0);
36527c478bd9Sstevel@tonic-gate 			if (tcount) {
36537c478bd9Sstevel@tonic-gate 				for (i = 0; tcount--; i++) {
36547c478bd9Sstevel@tonic-gate 					if (i % 16 == 0) {
36557c478bd9Sstevel@tonic-gate 						if (i)
36567c478bd9Sstevel@tonic-gate 							printf("\n");
36577c478bd9Sstevel@tonic-gate 						index(base);
36587c478bd9Sstevel@tonic-gate 					}
36597c478bd9Sstevel@tonic-gate 					if (po == 'c') {
36607c478bd9Sstevel@tonic-gate 						putf(*cptr++);
36617c478bd9Sstevel@tonic-gate 						if ((i + 1) % 16)
36627c478bd9Sstevel@tonic-gate 							printf("  ");
36637c478bd9Sstevel@tonic-gate 					} else {
36647c478bd9Sstevel@tonic-gate 						if ((i + 1) % 16 == 0)
36657c478bd9Sstevel@tonic-gate 							print(*cptr++ & 0377L,
36667c478bd9Sstevel@tonic-gate 								2, -2, 0);
36677c478bd9Sstevel@tonic-gate 						else
36687c478bd9Sstevel@tonic-gate 							print(*cptr++ & 0377L,
36697c478bd9Sstevel@tonic-gate 								4, -2, 0);
36707c478bd9Sstevel@tonic-gate 					}
36717c478bd9Sstevel@tonic-gate 					addr += CHAR;
36727c478bd9Sstevel@tonic-gate 					cur_bytes += CHAR;
36737c478bd9Sstevel@tonic-gate 				}
36747c478bd9Sstevel@tonic-gate 				printf("\n");
36757c478bd9Sstevel@tonic-gate 			}
36767c478bd9Sstevel@tonic-gate 			addr -= CHAR;
36777c478bd9Sstevel@tonic-gate 			erraddr = addr;
36787c478bd9Sstevel@tonic-gate 			cur_bytes -= CHAR;
36797c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
36807c478bd9Sstevel@tonic-gate 			if (eof) {
36817c478bd9Sstevel@tonic-gate 				printf("end of file\n");
36827c478bd9Sstevel@tonic-gate 				error++;
36837c478bd9Sstevel@tonic-gate 			} else if (end) {
36847c478bd9Sstevel@tonic-gate 				if (type == BLOCK)
36857c478bd9Sstevel@tonic-gate 					printf("end of block\n");
36867c478bd9Sstevel@tonic-gate 				else
36877c478bd9Sstevel@tonic-gate 					printf("end of fragment\n");
36887c478bd9Sstevel@tonic-gate 				error++;
36897c478bd9Sstevel@tonic-gate 			}
36907c478bd9Sstevel@tonic-gate 			return;
36917c478bd9Sstevel@tonic-gate 
36927c478bd9Sstevel@tonic-gate 		case 'o': /* print as octal shorts */
36937c478bd9Sstevel@tonic-gate 			tbase = OCTAL;
36947c478bd9Sstevel@tonic-gate 			goto otx;
36957c478bd9Sstevel@tonic-gate 		case 'd': /* print as decimal shorts */
36967c478bd9Sstevel@tonic-gate 			tbase = DECIMAL;
36977c478bd9Sstevel@tonic-gate 			goto otx;
36987c478bd9Sstevel@tonic-gate 		case 'x': /* print as hex shorts */
36997c478bd9Sstevel@tonic-gate 			tbase = HEX;
37007c478bd9Sstevel@tonic-gate otx:
37017c478bd9Sstevel@tonic-gate 			if ((cptr = getblk(addr)) == 0)
37027c478bd9Sstevel@tonic-gate 				return;
37037c478bd9Sstevel@tonic-gate 			taddr = addr;
37047c478bd9Sstevel@tonic-gate 			addr &= ~(SHORT - 1);
37057c478bd9Sstevel@tonic-gate 			cur_bytes -= taddr - addr;
37067c478bd9Sstevel@tonic-gate 			cptr += blkoff(fs, addr);
37077c478bd9Sstevel@tonic-gate 			/*LINTED*/
37087c478bd9Sstevel@tonic-gate 			sptr = (unsigned short *)cptr;
37097c478bd9Sstevel@tonic-gate 			objsz = SHORT;
37107c478bd9Sstevel@tonic-gate 			tcount = check_addr(eof_flag, &end, &eof, 0);
37117c478bd9Sstevel@tonic-gate 			if (tcount) {
37127c478bd9Sstevel@tonic-gate 				for (i = 0; tcount--; i++) {
37137c478bd9Sstevel@tonic-gate 					sptr = (unsigned short *)print_check(
37147c478bd9Sstevel@tonic-gate 							/*LINTED*/
37157c478bd9Sstevel@tonic-gate 							(unsigned long *)sptr,
37167c478bd9Sstevel@tonic-gate 							&tcount, tbase, i);
37177c478bd9Sstevel@tonic-gate 					switch (po) {
37187c478bd9Sstevel@tonic-gate 					case 'o':
37197c478bd9Sstevel@tonic-gate 						printf("%06o ", *sptr++);
37207c478bd9Sstevel@tonic-gate 						break;
37217c478bd9Sstevel@tonic-gate 					case 'd':
37227c478bd9Sstevel@tonic-gate 						printf("%05d  ", *sptr++);
37237c478bd9Sstevel@tonic-gate 						break;
37247c478bd9Sstevel@tonic-gate 					case 'x':
37257c478bd9Sstevel@tonic-gate 						printf("%04x   ", *sptr++);
37267c478bd9Sstevel@tonic-gate 					}
37277c478bd9Sstevel@tonic-gate 					addr += SHORT;
37287c478bd9Sstevel@tonic-gate 					cur_bytes += SHORT;
37297c478bd9Sstevel@tonic-gate 				}
37307c478bd9Sstevel@tonic-gate 				printf("\n");
37317c478bd9Sstevel@tonic-gate 			}
37327c478bd9Sstevel@tonic-gate 			addr -= SHORT;
37337c478bd9Sstevel@tonic-gate 			erraddr = addr;
37347c478bd9Sstevel@tonic-gate 			cur_bytes -= SHORT;
37357c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
37367c478bd9Sstevel@tonic-gate 			if (eof) {
37377c478bd9Sstevel@tonic-gate 				printf("end of file\n");
37387c478bd9Sstevel@tonic-gate 				error++;
37397c478bd9Sstevel@tonic-gate 			} else if (end) {
37407c478bd9Sstevel@tonic-gate 				if (type == BLOCK)
37417c478bd9Sstevel@tonic-gate 					printf("end of block\n");
37427c478bd9Sstevel@tonic-gate 				else
37437c478bd9Sstevel@tonic-gate 					printf("end of fragment\n");
37447c478bd9Sstevel@tonic-gate 				error++;
37457c478bd9Sstevel@tonic-gate 			}
37467c478bd9Sstevel@tonic-gate 			return;
37477c478bd9Sstevel@tonic-gate 
37487c478bd9Sstevel@tonic-gate 		case 'O': /* print as octal longs */
37497c478bd9Sstevel@tonic-gate 			tbase = OCTAL;
37507c478bd9Sstevel@tonic-gate 			goto OTX;
37517c478bd9Sstevel@tonic-gate 		case 'D': /* print as decimal longs */
37527c478bd9Sstevel@tonic-gate 			tbase = DECIMAL;
37537c478bd9Sstevel@tonic-gate 			goto OTX;
37547c478bd9Sstevel@tonic-gate 		case 'X': /* print as hex longs */
37557c478bd9Sstevel@tonic-gate 			tbase = HEX;
37567c478bd9Sstevel@tonic-gate OTX:
37577c478bd9Sstevel@tonic-gate 			if ((cptr = getblk(addr)) == 0)
37587c478bd9Sstevel@tonic-gate 				return;
37597c478bd9Sstevel@tonic-gate 			taddr = addr;
37607c478bd9Sstevel@tonic-gate 			addr &= ~(LONG - 1);
37617c478bd9Sstevel@tonic-gate 			cur_bytes -= taddr - addr;
37627c478bd9Sstevel@tonic-gate 			cptr += blkoff(fs, addr);
37637c478bd9Sstevel@tonic-gate 			/*LINTED*/
37647c478bd9Sstevel@tonic-gate 			lptr = (unsigned long *)cptr;
37657c478bd9Sstevel@tonic-gate 			objsz = LONG;
37667c478bd9Sstevel@tonic-gate 			tcount = check_addr(eof_flag, &end, &eof, 0);
37677c478bd9Sstevel@tonic-gate 			if (tcount) {
37687c478bd9Sstevel@tonic-gate 				for (i = 0; tcount--; i++) {
37697c478bd9Sstevel@tonic-gate 					lptr = print_check(lptr, &tcount,
37707c478bd9Sstevel@tonic-gate 								tbase, i);
37717c478bd9Sstevel@tonic-gate 					switch (po) {
37727c478bd9Sstevel@tonic-gate 					case 'O':
37737c478bd9Sstevel@tonic-gate 						printf("%011lo    ", *lptr++);
37747c478bd9Sstevel@tonic-gate 						break;
37757c478bd9Sstevel@tonic-gate 					case 'D':
37767c478bd9Sstevel@tonic-gate 						printf("%010lu     ", *lptr++);
37777c478bd9Sstevel@tonic-gate 						break;
37787c478bd9Sstevel@tonic-gate 					case 'X':
37797c478bd9Sstevel@tonic-gate 						printf("%08lx       ", *lptr++);
37807c478bd9Sstevel@tonic-gate 					}
37817c478bd9Sstevel@tonic-gate 					addr += LONG;
37827c478bd9Sstevel@tonic-gate 					cur_bytes += LONG;
37837c478bd9Sstevel@tonic-gate 				}
37847c478bd9Sstevel@tonic-gate 				printf("\n");
37857c478bd9Sstevel@tonic-gate 			}
37867c478bd9Sstevel@tonic-gate 			addr -= LONG;
37877c478bd9Sstevel@tonic-gate 			erraddr = addr;
37887c478bd9Sstevel@tonic-gate 			cur_bytes -= LONG;
37897c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
37907c478bd9Sstevel@tonic-gate 			if (eof) {
37917c478bd9Sstevel@tonic-gate 				printf("end of file\n");
37927c478bd9Sstevel@tonic-gate 				error++;
37937c478bd9Sstevel@tonic-gate 			} else if (end) {
37947c478bd9Sstevel@tonic-gate 				if (type == BLOCK)
37957c478bd9Sstevel@tonic-gate 					printf("end of block\n");
37967c478bd9Sstevel@tonic-gate 				else
37977c478bd9Sstevel@tonic-gate 					printf("end of fragment\n");
37987c478bd9Sstevel@tonic-gate 				error++;
37997c478bd9Sstevel@tonic-gate 			}
38007c478bd9Sstevel@tonic-gate 			return;
38017c478bd9Sstevel@tonic-gate 
38027c478bd9Sstevel@tonic-gate 		default:
38037c478bd9Sstevel@tonic-gate 			error++;
38047c478bd9Sstevel@tonic-gate 			printf("no such print option\n");
38057c478bd9Sstevel@tonic-gate 			return;
38067c478bd9Sstevel@tonic-gate 		}
38077c478bd9Sstevel@tonic-gate 	} else
38087c478bd9Sstevel@tonic-gate 		switch (po) {
38097c478bd9Sstevel@tonic-gate 
38107c478bd9Sstevel@tonic-gate 		case 'c': /* print as cylinder group */
38117c478bd9Sstevel@tonic-gate 			if (type != NUMB)
38127c478bd9Sstevel@tonic-gate 				if (cur_cgrp + count > fs->fs_ncg) {
38137c478bd9Sstevel@tonic-gate 					tcount = fs->fs_ncg - cur_cgrp;
38147c478bd9Sstevel@tonic-gate 					if (!star)
38157c478bd9Sstevel@tonic-gate 						end++;
38167c478bd9Sstevel@tonic-gate 				}
38177c478bd9Sstevel@tonic-gate 			addr &= ~(LONG - 1);
38187c478bd9Sstevel@tonic-gate 			for (/* void */; tcount--; /* void */) {
38197c478bd9Sstevel@tonic-gate 				erraddr = addr;
38207c478bd9Sstevel@tonic-gate 				errcur_bytes = cur_bytes;
38217c478bd9Sstevel@tonic-gate 				if (type != NUMB) {
38227c478bd9Sstevel@tonic-gate 					addr = cgtod(fs, cur_cgrp)
38237c478bd9Sstevel@tonic-gate 						<< FRGSHIFT;
38247c478bd9Sstevel@tonic-gate 					cur_cgrp++;
38257c478bd9Sstevel@tonic-gate 				}
38267c478bd9Sstevel@tonic-gate 				if ((cptr = getblk(addr)) == 0) {
38277c478bd9Sstevel@tonic-gate 					if (cur_cgrp)
38287c478bd9Sstevel@tonic-gate 						cur_cgrp--;
38297c478bd9Sstevel@tonic-gate 					return;
38307c478bd9Sstevel@tonic-gate 				}
38317c478bd9Sstevel@tonic-gate 				cptr += blkoff(fs, addr);
38327c478bd9Sstevel@tonic-gate 				/*LINTED*/
38337c478bd9Sstevel@tonic-gate 				cg = (struct cg *)cptr;
38347c478bd9Sstevel@tonic-gate 				if (type == NUMB) {
38357c478bd9Sstevel@tonic-gate 					cur_cgrp = cg->cg_cgx + 1;
38367c478bd9Sstevel@tonic-gate 					type = objsz = CGRP;
38377c478bd9Sstevel@tonic-gate 					if (cur_cgrp + count - 1 > fs->fs_ncg) {
38387c478bd9Sstevel@tonic-gate 						tcount = fs->fs_ncg - cur_cgrp;
38397c478bd9Sstevel@tonic-gate 						if (!star)
38407c478bd9Sstevel@tonic-gate 							end++;
38417c478bd9Sstevel@tonic-gate 					}
38427c478bd9Sstevel@tonic-gate 				}
38437c478bd9Sstevel@tonic-gate 				if (! override && !cg_chkmagic(cg)) {
38447c478bd9Sstevel@tonic-gate 					printf("invalid cylinder group ");
38457c478bd9Sstevel@tonic-gate 					printf("magic word\n");
38467c478bd9Sstevel@tonic-gate 					if (cur_cgrp)
38477c478bd9Sstevel@tonic-gate 						cur_cgrp--;
38487c478bd9Sstevel@tonic-gate 					error++;
38497c478bd9Sstevel@tonic-gate 					return;
38507c478bd9Sstevel@tonic-gate 				}
38517c478bd9Sstevel@tonic-gate 				printcg(cg);
38527c478bd9Sstevel@tonic-gate 				if (tcount)
38537c478bd9Sstevel@tonic-gate 					printf("\n");
38547c478bd9Sstevel@tonic-gate 			}
38557c478bd9Sstevel@tonic-gate 			cur_cgrp--;
38567c478bd9Sstevel@tonic-gate 			if (end) {
38577c478bd9Sstevel@tonic-gate 				printf("end of cylinder groups\n");
38587c478bd9Sstevel@tonic-gate 				error++;
38597c478bd9Sstevel@tonic-gate 			}
38607c478bd9Sstevel@tonic-gate 			return;
38617c478bd9Sstevel@tonic-gate 
38627c478bd9Sstevel@tonic-gate 		case 'd': /* print as directories */
38637c478bd9Sstevel@tonic-gate 			if ((cptr = getblk(addr)) == 0)
38647c478bd9Sstevel@tonic-gate 				return;
38657c478bd9Sstevel@tonic-gate 			if (type == NUMB) {
38667c478bd9Sstevel@tonic-gate 				if (fragoff(fs, addr)) {
38677c478bd9Sstevel@tonic-gate 					printf("address must be at the ");
38687c478bd9Sstevel@tonic-gate 					printf("beginning of a fragment\n");
38697c478bd9Sstevel@tonic-gate 					error++;
38707c478bd9Sstevel@tonic-gate 					return;
38717c478bd9Sstevel@tonic-gate 				}
38727c478bd9Sstevel@tonic-gate 				bod_addr = addr;
38737c478bd9Sstevel@tonic-gate 				type = FRAGMENT;
38747c478bd9Sstevel@tonic-gate 				dirslot = 0;
38757c478bd9Sstevel@tonic-gate 				cur_bytes = 0;
38767c478bd9Sstevel@tonic-gate 				blocksize = FRGSIZE;
38777c478bd9Sstevel@tonic-gate 				filesize = FRGSIZE * 2;
38787c478bd9Sstevel@tonic-gate 			}
38797c478bd9Sstevel@tonic-gate 			cptr += offset;
38807c478bd9Sstevel@tonic-gate 			objsz = DIRECTORY;
38817c478bd9Sstevel@tonic-gate 			while (tcount-- && cur_bytes < filesize &&
38827c478bd9Sstevel@tonic-gate 				cur_bytes < blocksize && !bcomp(addr)) {
38837c478bd9Sstevel@tonic-gate 				/*LINTED*/
38847c478bd9Sstevel@tonic-gate 				dirp = (struct direct *)cptr;
38857c478bd9Sstevel@tonic-gate 				tinode = dirp->d_ino;
38867c478bd9Sstevel@tonic-gate 				printf("i#: ");
38877c478bd9Sstevel@tonic-gate 				if (tinode == 0)
38887c478bd9Sstevel@tonic-gate 					printf("free\t");
38897c478bd9Sstevel@tonic-gate 				else
38907c478bd9Sstevel@tonic-gate 					print(tinode, 12, -8, 0);
38917c478bd9Sstevel@tonic-gate 				printf("%s\n", &dirp->d_name[0]);
38927c478bd9Sstevel@tonic-gate 				erraddr = addr;
38937c478bd9Sstevel@tonic-gate 				errcur_bytes = cur_bytes;
38947c478bd9Sstevel@tonic-gate 				addr += dirp->d_reclen;
38957c478bd9Sstevel@tonic-gate 				cptr += dirp->d_reclen;
38967c478bd9Sstevel@tonic-gate 				cur_bytes += dirp->d_reclen;
38977c478bd9Sstevel@tonic-gate 				dirslot++;
38987c478bd9Sstevel@tonic-gate 				stringsize = STRINGSIZE(dirp);
38997c478bd9Sstevel@tonic-gate 			}
39007c478bd9Sstevel@tonic-gate 			addr = erraddr;
39017c478bd9Sstevel@tonic-gate 			cur_dir = addr;
39027c478bd9Sstevel@tonic-gate 			cur_bytes = errcur_bytes;
39037c478bd9Sstevel@tonic-gate 			dirslot--;
39047c478bd9Sstevel@tonic-gate 			if (tcount >= 0 && !star) {
39057c478bd9Sstevel@tonic-gate 				switch (type) {
39067c478bd9Sstevel@tonic-gate 				case FRAGMENT:
39077c478bd9Sstevel@tonic-gate 					printf("end of fragment\n");
39087c478bd9Sstevel@tonic-gate 					break;
39097c478bd9Sstevel@tonic-gate 				case BLOCK:
39107c478bd9Sstevel@tonic-gate 					printf("end of block\n");
39117c478bd9Sstevel@tonic-gate 					break;
39127c478bd9Sstevel@tonic-gate 				default:
39137c478bd9Sstevel@tonic-gate 					printf("end of directory\n");
39147c478bd9Sstevel@tonic-gate 				}
39157c478bd9Sstevel@tonic-gate 				error++;
39167c478bd9Sstevel@tonic-gate 			} else
39177c478bd9Sstevel@tonic-gate 				error = 0;
39187c478bd9Sstevel@tonic-gate 			return;
39197c478bd9Sstevel@tonic-gate 
39207c478bd9Sstevel@tonic-gate 		case 'i': /* print as inodes */
39217c478bd9Sstevel@tonic-gate 			/*LINTED*/
39227c478bd9Sstevel@tonic-gate 			if ((ip = (struct dinode *)getblk(addr)) == 0)
39237c478bd9Sstevel@tonic-gate 				return;
39247c478bd9Sstevel@tonic-gate 			for (i = 1; i < fs->fs_ncg; i++)
39257c478bd9Sstevel@tonic-gate 				if (addr < (cgimin(fs, i) << FRGSHIFT))
39267c478bd9Sstevel@tonic-gate 					break;
39277c478bd9Sstevel@tonic-gate 			i--;
39287c478bd9Sstevel@tonic-gate 			offset /= INODE;
39297c478bd9Sstevel@tonic-gate 			temp = (addr - (cgimin(fs, i) << FRGSHIFT)) >> FRGSHIFT;
39307c478bd9Sstevel@tonic-gate 			temp = (i * fs->fs_ipg) + fragstoblks(fs, temp) *
39317c478bd9Sstevel@tonic-gate 							INOPB(fs) + offset;
39327c478bd9Sstevel@tonic-gate 			if (count + offset > INOPB(fs)) {
39337c478bd9Sstevel@tonic-gate 				tcount = INOPB(fs) - offset;
39347c478bd9Sstevel@tonic-gate 				if (!star)
39357c478bd9Sstevel@tonic-gate 					end++;
39367c478bd9Sstevel@tonic-gate 			}
39377c478bd9Sstevel@tonic-gate 			objsz = INODE;
39387c478bd9Sstevel@tonic-gate 			ip += offset;
39397c478bd9Sstevel@tonic-gate 			for (i = 0; tcount--; ip++, temp++) {
39407c478bd9Sstevel@tonic-gate 				if ((mode = icheck(addr)) == 0)
39417c478bd9Sstevel@tonic-gate 					if (!override)
39427c478bd9Sstevel@tonic-gate 						continue;
39437c478bd9Sstevel@tonic-gate 				p = " ugtrwxrwxrwx";
39447c478bd9Sstevel@tonic-gate 
39457c478bd9Sstevel@tonic-gate 				switch (mode & IFMT) {
39467c478bd9Sstevel@tonic-gate 				case IFDIR:
39477c478bd9Sstevel@tonic-gate 					c = 'd';
39487c478bd9Sstevel@tonic-gate 					break;
39497c478bd9Sstevel@tonic-gate 				case IFCHR:
39507c478bd9Sstevel@tonic-gate 					c = 'c';
39517c478bd9Sstevel@tonic-gate 					break;
39527c478bd9Sstevel@tonic-gate 				case IFBLK:
39537c478bd9Sstevel@tonic-gate 					c = 'b';
39547c478bd9Sstevel@tonic-gate 					break;
39557c478bd9Sstevel@tonic-gate 				case IFREG:
39567c478bd9Sstevel@tonic-gate 					c = '-';
39577c478bd9Sstevel@tonic-gate 					break;
39587c478bd9Sstevel@tonic-gate 				case IFLNK:
39597c478bd9Sstevel@tonic-gate 					c = 'l';
39607c478bd9Sstevel@tonic-gate 					break;
39617c478bd9Sstevel@tonic-gate 				case IFSOCK:
39627c478bd9Sstevel@tonic-gate 					c = 's';
39637c478bd9Sstevel@tonic-gate 					break;
39647c478bd9Sstevel@tonic-gate 				case IFSHAD:
39657c478bd9Sstevel@tonic-gate 					c = 'S';
39667c478bd9Sstevel@tonic-gate 					break;
39677c478bd9Sstevel@tonic-gate 				case IFATTRDIR:
39687c478bd9Sstevel@tonic-gate 					c = 'A';
39697c478bd9Sstevel@tonic-gate 					break;
39707c478bd9Sstevel@tonic-gate 				default:
39717c478bd9Sstevel@tonic-gate 					c = '?';
39727c478bd9Sstevel@tonic-gate 					if (!override)
39737c478bd9Sstevel@tonic-gate 						goto empty;
39747c478bd9Sstevel@tonic-gate 
39757c478bd9Sstevel@tonic-gate 				}
39767c478bd9Sstevel@tonic-gate 				printf("i#: ");
39777c478bd9Sstevel@tonic-gate 				print(temp, 12, -8, 0);
39787c478bd9Sstevel@tonic-gate 				printf("   md: ");
39797c478bd9Sstevel@tonic-gate 				printf("%c", c);
39807c478bd9Sstevel@tonic-gate 				for (mode = mode << 4; *++p; mode = mode << 1) {
39817c478bd9Sstevel@tonic-gate 					if (mode & IFREG)
39827c478bd9Sstevel@tonic-gate 						printf("%c", *p);
39837c478bd9Sstevel@tonic-gate 					else
39847c478bd9Sstevel@tonic-gate 						printf("-");
39857c478bd9Sstevel@tonic-gate 				}
39867c478bd9Sstevel@tonic-gate 				printf("  uid: ");
39877c478bd9Sstevel@tonic-gate 				print(ip->di_uid, 8, -4, 0);
39887c478bd9Sstevel@tonic-gate 				printf("      gid: ");
39897c478bd9Sstevel@tonic-gate 				print(ip->di_gid, 8, -4, 0);
39907c478bd9Sstevel@tonic-gate 				printf("\n");
39917c478bd9Sstevel@tonic-gate 				printf("ln: ");
39927c478bd9Sstevel@tonic-gate 				print((long)ip->di_nlink, 8, -4, 0);
39937c478bd9Sstevel@tonic-gate 				printf("       bs: ");
39947c478bd9Sstevel@tonic-gate 				print(ip->di_blocks, 12, -8, 0);
39957c478bd9Sstevel@tonic-gate 				printf("c_flags : ");
39967c478bd9Sstevel@tonic-gate 				print(ip->di_cflags, 12, -8, 0);
399785651ed9SJohn.Zolnowsky@Sun.COM 				printf("   sz : ");
39987c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
39997c478bd9Sstevel@tonic-gate 				printll(ip->di_size, 20, -16, 0);
40007c478bd9Sstevel@tonic-gate #else /* !_LARGEFILE64_SOURCE */
40017c478bd9Sstevel@tonic-gate 				print(ip->di_size, 12, -8, 0);
40027c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
40037c478bd9Sstevel@tonic-gate 				if (ip->di_shadow) {
40047c478bd9Sstevel@tonic-gate 					printf("   si: ");
40057c478bd9Sstevel@tonic-gate 					print(ip->di_shadow, 12, -8, 0);
40067c478bd9Sstevel@tonic-gate 				}
40077c478bd9Sstevel@tonic-gate 				printf("\n");
40087c478bd9Sstevel@tonic-gate 				if (ip->di_oeftflag) {
40097c478bd9Sstevel@tonic-gate 					printf("ai: ");
40107c478bd9Sstevel@tonic-gate 					print(ip->di_oeftflag, 12, -8, 0);
40117c478bd9Sstevel@tonic-gate 					printf("\n");
40127c478bd9Sstevel@tonic-gate 				}
40137c478bd9Sstevel@tonic-gate 				printf("\n");
40147c478bd9Sstevel@tonic-gate 				switch (ip->di_mode & IFMT) {
40157c478bd9Sstevel@tonic-gate 				case IFBLK:
40167c478bd9Sstevel@tonic-gate 				case IFCHR:
40177c478bd9Sstevel@tonic-gate 					printf("maj: ");
40187c478bd9Sstevel@tonic-gate 					print(major(ip->di_ordev), 4, -2, 0);
40197c478bd9Sstevel@tonic-gate 					printf("  min: ");
40207c478bd9Sstevel@tonic-gate 					print(minor(ip->di_ordev), 4, -2, 0);
40217c478bd9Sstevel@tonic-gate 					printf("\n");
40227c478bd9Sstevel@tonic-gate 					break;
40237c478bd9Sstevel@tonic-gate 				default:
40247c478bd9Sstevel@tonic-gate 					/*
40257c478bd9Sstevel@tonic-gate 					 * only display blocks below the
40267c478bd9Sstevel@tonic-gate 					 * current file size
40277c478bd9Sstevel@tonic-gate 					 */
40287c478bd9Sstevel@tonic-gate 					curoff = 0LL;
40297c478bd9Sstevel@tonic-gate 					for (i = 0; i < NDADDR; ) {
40307c478bd9Sstevel@tonic-gate 						if (ip->di_size <= curoff)
40317c478bd9Sstevel@tonic-gate 							break;
40327c478bd9Sstevel@tonic-gate 						printf("db#%x: ", i);
40337c478bd9Sstevel@tonic-gate 						print(ip->di_db[i], 11, -8, 0);
40347c478bd9Sstevel@tonic-gate 
40357c478bd9Sstevel@tonic-gate 						if (++i % 4 == 0)
40367c478bd9Sstevel@tonic-gate 							printf("\n");
40377c478bd9Sstevel@tonic-gate 						else
40387c478bd9Sstevel@tonic-gate 							printf("  ");
40397c478bd9Sstevel@tonic-gate 						curoff += fs->fs_bsize;
40407c478bd9Sstevel@tonic-gate 					}
40417c478bd9Sstevel@tonic-gate 					if (i % 4)
40427c478bd9Sstevel@tonic-gate 						printf("\n");
40437c478bd9Sstevel@tonic-gate 
40447c478bd9Sstevel@tonic-gate 					/*
40457c478bd9Sstevel@tonic-gate 					 * curioff keeps track of the number
40467c478bd9Sstevel@tonic-gate 					 * of bytes covered by each indirect
40477c478bd9Sstevel@tonic-gate 					 * pointer in the inode, and is added
40487c478bd9Sstevel@tonic-gate 					 * to curoff each time to get the
40497c478bd9Sstevel@tonic-gate 					 * actual offset into the file.
40507c478bd9Sstevel@tonic-gate 					 */
40517c478bd9Sstevel@tonic-gate 					curioff = fs->fs_bsize *
40527c478bd9Sstevel@tonic-gate 					    (fs->fs_bsize / sizeof (daddr_t));
40537c478bd9Sstevel@tonic-gate 					for (i = 0; i < NIADDR; i++) {
40547c478bd9Sstevel@tonic-gate 						if (ip->di_size <= curoff)
40557c478bd9Sstevel@tonic-gate 							break;
40567c478bd9Sstevel@tonic-gate 						printf("ib#%x: ", i);
40577c478bd9Sstevel@tonic-gate 						print(ip->di_ib[i], 11, -8, 0);
40587c478bd9Sstevel@tonic-gate 						printf("  ");
40597c478bd9Sstevel@tonic-gate 						curoff += curioff;
40607c478bd9Sstevel@tonic-gate 						curioff *= (fs->fs_bsize /
40617c478bd9Sstevel@tonic-gate 						    sizeof (daddr_t));
40627c478bd9Sstevel@tonic-gate 					}
40637c478bd9Sstevel@tonic-gate 					if (i)
40647c478bd9Sstevel@tonic-gate 						printf("\n");
40657c478bd9Sstevel@tonic-gate 					break;
40667c478bd9Sstevel@tonic-gate 				}
40677c478bd9Sstevel@tonic-gate 				if (count == 1) {
40687c478bd9Sstevel@tonic-gate 					time_t t;
40697c478bd9Sstevel@tonic-gate 
40707c478bd9Sstevel@tonic-gate 					t = ip->di_atime;
40717c478bd9Sstevel@tonic-gate 					printf("\taccessed: %s", ctime(&t));
40727c478bd9Sstevel@tonic-gate 					t = ip->di_mtime;
40737c478bd9Sstevel@tonic-gate 					printf("\tmodified: %s", ctime(&t));
40747c478bd9Sstevel@tonic-gate 					t = ip->di_ctime;
40757c478bd9Sstevel@tonic-gate 					printf("\tcreated : %s", ctime(&t));
40767c478bd9Sstevel@tonic-gate 				}
40777c478bd9Sstevel@tonic-gate 				if (tcount)
40787c478bd9Sstevel@tonic-gate 					printf("\n");
40797c478bd9Sstevel@tonic-gate empty:
40807c478bd9Sstevel@tonic-gate 				if (c == '?' && !override) {
40817c478bd9Sstevel@tonic-gate 					printf("i#: ");
40827c478bd9Sstevel@tonic-gate 					print(temp, 12, -8, 0);
40837c478bd9Sstevel@tonic-gate 					printf("  is unallocated\n");
40847c478bd9Sstevel@tonic-gate 					if (count != 1)
40857c478bd9Sstevel@tonic-gate 						printf("\n");
40867c478bd9Sstevel@tonic-gate 				}
40877c478bd9Sstevel@tonic-gate 				cur_ino = erraddr = addr;
40887c478bd9Sstevel@tonic-gate 				errcur_bytes = cur_bytes;
40897c478bd9Sstevel@tonic-gate 				cur_inum++;
40907c478bd9Sstevel@tonic-gate 				addr = addr + INODE;
40917c478bd9Sstevel@tonic-gate 			}
40927c478bd9Sstevel@tonic-gate 			addr = erraddr;
40937c478bd9Sstevel@tonic-gate 			cur_bytes = errcur_bytes;
40947c478bd9Sstevel@tonic-gate 			cur_inum--;
40957c478bd9Sstevel@tonic-gate 			if (end) {
40967c478bd9Sstevel@tonic-gate 				printf("end of block\n");
40977c478bd9Sstevel@tonic-gate 				error++;
40987c478bd9Sstevel@tonic-gate 			}
40997c478bd9Sstevel@tonic-gate 			return;
41007c478bd9Sstevel@tonic-gate 
41017c478bd9Sstevel@tonic-gate 		case 's': /* print as super block */
41027c478bd9Sstevel@tonic-gate 			if (cur_cgrp == -1) {
41037c478bd9Sstevel@tonic-gate 				addr = SBLOCK * DEV_BSIZE;
41047c478bd9Sstevel@tonic-gate 				type = NUMB;
41057c478bd9Sstevel@tonic-gate 			}
41067c478bd9Sstevel@tonic-gate 			addr &= ~(LONG - 1);
41077c478bd9Sstevel@tonic-gate 			if (type != NUMB)
41087c478bd9Sstevel@tonic-gate 				if (cur_cgrp + count > fs->fs_ncg) {
41097c478bd9Sstevel@tonic-gate 					tcount = fs->fs_ncg - cur_cgrp;
41107c478bd9Sstevel@tonic-gate 					if (!star)
41117c478bd9Sstevel@tonic-gate 						end++;
41127c478bd9Sstevel@tonic-gate 				}
41137c478bd9Sstevel@tonic-gate 			for (/* void */; tcount--; /* void */) {
41147c478bd9Sstevel@tonic-gate 				erraddr = addr;
41157c478bd9Sstevel@tonic-gate 				cur_bytes = errcur_bytes;
41167c478bd9Sstevel@tonic-gate 				if (type != NUMB) {
41177c478bd9Sstevel@tonic-gate 					addr = cgsblock(fs, cur_cgrp)
41187c478bd9Sstevel@tonic-gate 							<< FRGSHIFT;
41197c478bd9Sstevel@tonic-gate 					cur_cgrp++;
41207c478bd9Sstevel@tonic-gate 				}
41217c478bd9Sstevel@tonic-gate 				if ((cptr = getblk(addr)) == 0) {
41227c478bd9Sstevel@tonic-gate 					if (cur_cgrp)
41237c478bd9Sstevel@tonic-gate 						cur_cgrp--;
41247c478bd9Sstevel@tonic-gate 					return;
41257c478bd9Sstevel@tonic-gate 				}
41267c478bd9Sstevel@tonic-gate 				cptr += blkoff(fs, addr);
41277c478bd9Sstevel@tonic-gate 				/*LINTED*/
41287c478bd9Sstevel@tonic-gate 				sb = (struct fs *)cptr;
41297c478bd9Sstevel@tonic-gate 				if (type == NUMB) {
41307c478bd9Sstevel@tonic-gate 					for (i = 0; i < fs->fs_ncg; i++)
41317c478bd9Sstevel@tonic-gate 						if (addr == cgsblock(fs, i) <<
41327c478bd9Sstevel@tonic-gate 								FRGSHIFT)
41337c478bd9Sstevel@tonic-gate 							break;
41347c478bd9Sstevel@tonic-gate 					if (i == fs->fs_ncg)
41357c478bd9Sstevel@tonic-gate 						cur_cgrp = 0;
41367c478bd9Sstevel@tonic-gate 					else
41377c478bd9Sstevel@tonic-gate 						cur_cgrp = i + 1;
41387c478bd9Sstevel@tonic-gate 					type = objsz = SB;
41397c478bd9Sstevel@tonic-gate 					if (cur_cgrp + count - 1 > fs->fs_ncg) {
41407c478bd9Sstevel@tonic-gate 						tcount = fs->fs_ncg - cur_cgrp;
41417c478bd9Sstevel@tonic-gate 						if (!star)
41427c478bd9Sstevel@tonic-gate 							end++;
41437c478bd9Sstevel@tonic-gate 					}
41447c478bd9Sstevel@tonic-gate 				}
41457c478bd9Sstevel@tonic-gate 				if ((sb->fs_magic != FS_MAGIC) &&
41467c478bd9Sstevel@tonic-gate 				    (sb->fs_magic != MTB_UFS_MAGIC)) {
41477c478bd9Sstevel@tonic-gate 					cur_cgrp = 0;
41487c478bd9Sstevel@tonic-gate 					if (!override) {
41497c478bd9Sstevel@tonic-gate 						printf("invalid super block ");
41507c478bd9Sstevel@tonic-gate 						printf("magic word\n");
41517c478bd9Sstevel@tonic-gate 						cur_cgrp--;
41527c478bd9Sstevel@tonic-gate 						error++;
41537c478bd9Sstevel@tonic-gate 						return;
41547c478bd9Sstevel@tonic-gate 					}
41557c478bd9Sstevel@tonic-gate 				}
41566451fdbcSvsakar 				if (sb->fs_magic == FS_MAGIC &&
41576451fdbcSvsakar 				    (sb->fs_version !=
41586451fdbcSvsakar 					UFS_EFISTYLE4NONEFI_VERSION_2 &&
41596451fdbcSvsakar 				    sb->fs_version != UFS_VERSION_MIN)) {
41606451fdbcSvsakar 					cur_cgrp = 0;
41616451fdbcSvsakar 					if (!override) {
41626451fdbcSvsakar 						printf("invalid super block ");
41636451fdbcSvsakar 						printf("version number\n");
41646451fdbcSvsakar 						cur_cgrp--;
41656451fdbcSvsakar 						error++;
41666451fdbcSvsakar 						return;
41676451fdbcSvsakar 					}
41686451fdbcSvsakar 				}
41697c478bd9Sstevel@tonic-gate 				if (sb->fs_magic == MTB_UFS_MAGIC &&
41707c478bd9Sstevel@tonic-gate 				    (sb->fs_version > MTB_UFS_VERSION_1 ||
41717c478bd9Sstevel@tonic-gate 				    sb->fs_version < MTB_UFS_VERSION_MIN)) {
41727c478bd9Sstevel@tonic-gate 					cur_cgrp = 0;
41737c478bd9Sstevel@tonic-gate 					if (!override) {
41747c478bd9Sstevel@tonic-gate 						printf("invalid super block ");
41756451fdbcSvsakar 						printf("version number\n");
41767c478bd9Sstevel@tonic-gate 						cur_cgrp--;
41777c478bd9Sstevel@tonic-gate 						error++;
41787c478bd9Sstevel@tonic-gate 						return;
41797c478bd9Sstevel@tonic-gate 					}
41807c478bd9Sstevel@tonic-gate 				}
41817c478bd9Sstevel@tonic-gate 				if (cur_cgrp == 0)
41827c478bd9Sstevel@tonic-gate 					printf("\tsuper block:\n");
41837c478bd9Sstevel@tonic-gate 				else {
41847c478bd9Sstevel@tonic-gate 					printf("\tsuper block in cylinder ");
41857c478bd9Sstevel@tonic-gate 					printf("group ");
41867c478bd9Sstevel@tonic-gate 					print(cur_cgrp - 1, 0, 0, 0);
41877c478bd9Sstevel@tonic-gate 					printf(":\n");
41887c478bd9Sstevel@tonic-gate 				}
41897c478bd9Sstevel@tonic-gate 				printsb(sb);
41907c478bd9Sstevel@tonic-gate 				if (tcount)
41917c478bd9Sstevel@tonic-gate 					printf("\n");
41927c478bd9Sstevel@tonic-gate 			}
41937c478bd9Sstevel@tonic-gate 			cur_cgrp--;
41947c478bd9Sstevel@tonic-gate 			if (end) {
41957c478bd9Sstevel@tonic-gate 				printf("end of super blocks\n");
41967c478bd9Sstevel@tonic-gate 				error++;
41977c478bd9Sstevel@tonic-gate 			}
41987c478bd9Sstevel@tonic-gate 			return;
41997c478bd9Sstevel@tonic-gate 
42007c478bd9Sstevel@tonic-gate 		case 'S': /* print as shadow data */
42017c478bd9Sstevel@tonic-gate 			if (type == NUMB) {
42027c478bd9Sstevel@tonic-gate 				type = FRAGMENT;
42037c478bd9Sstevel@tonic-gate 				cur_shad = 0;
42047c478bd9Sstevel@tonic-gate 				cur_bytes = fragoff(fs, addr);
42057c478bd9Sstevel@tonic-gate 				bod_addr = addr - cur_bytes;
42067c478bd9Sstevel@tonic-gate 				/* no more than two fragments */
42077c478bd9Sstevel@tonic-gate 				filesize = fragroundup(fs,
42087c478bd9Sstevel@tonic-gate 				    bod_addr + FRGSIZE + 1);
42097c478bd9Sstevel@tonic-gate 			}
42107c478bd9Sstevel@tonic-gate 			objsz = SHADOW_DATA;
42117c478bd9Sstevel@tonic-gate 			while (tcount-- &&
42127c478bd9Sstevel@tonic-gate 			    (cur_bytes + SHADOW_DATA) <= filesize &&
42137c478bd9Sstevel@tonic-gate 			    (type != SHADOW_DATA ||
42147c478bd9Sstevel@tonic-gate 			    (cur_bytes + SHADOW_DATA)) <= blocksize) {
42157c478bd9Sstevel@tonic-gate 				/*LINTED*/
42167c478bd9Sstevel@tonic-gate 				struct ufs_fsd fsd;
42177c478bd9Sstevel@tonic-gate 				long tcur_bytes;
42187c478bd9Sstevel@tonic-gate 
42197c478bd9Sstevel@tonic-gate 				taddr = addr;
42207c478bd9Sstevel@tonic-gate 				tcur_bytes = cur_bytes;
42217c478bd9Sstevel@tonic-gate 				index(base);
42227c478bd9Sstevel@tonic-gate 				getshadowdata((long *)&fsd, LONG + LONG);
42237c478bd9Sstevel@tonic-gate 				printf("  type: ");
42247c478bd9Sstevel@tonic-gate 				print((long)fsd.fsd_type, 8, -8, 0);
42257c478bd9Sstevel@tonic-gate 				printf("  size: ");
42267c478bd9Sstevel@tonic-gate 				print((long)fsd.fsd_size, 8, -8, 0);
42277c478bd9Sstevel@tonic-gate 				tbase = fsd.fsd_size - LONG - LONG;
42287c478bd9Sstevel@tonic-gate 				if (tbase > 256)
42297c478bd9Sstevel@tonic-gate 					tbase = 256;
42307c478bd9Sstevel@tonic-gate 				for (i = 0; i < tbase; i++) {
42317c478bd9Sstevel@tonic-gate 					if (i % LONG == 0) {
42327c478bd9Sstevel@tonic-gate 						if (i % 16 == 0) {
42337c478bd9Sstevel@tonic-gate 							printf("\n");
42347c478bd9Sstevel@tonic-gate 							index(base);
42357c478bd9Sstevel@tonic-gate 						} else
42367c478bd9Sstevel@tonic-gate 							printf("  ");
42377c478bd9Sstevel@tonic-gate 						getshadowdata(&temp, LONG);
42387c478bd9Sstevel@tonic-gate 						p = (char *)&temp;
42397c478bd9Sstevel@tonic-gate 					} else
42407c478bd9Sstevel@tonic-gate 						printf(" ");
42417c478bd9Sstevel@tonic-gate 					printf("%02x", (int)(*p++ & 0377L));
42427c478bd9Sstevel@tonic-gate 				}
42437c478bd9Sstevel@tonic-gate 				printf("\n");
42447c478bd9Sstevel@tonic-gate 				addr = taddr;
42457c478bd9Sstevel@tonic-gate 				cur_bytes = tcur_bytes;
42467c478bd9Sstevel@tonic-gate 				erraddr = addr;
42477c478bd9Sstevel@tonic-gate 				errcur_bytes = cur_bytes;
42487c478bd9Sstevel@tonic-gate 				addr += FSD_RECSZ((&fsd), fsd.fsd_size);
42497c478bd9Sstevel@tonic-gate 				cur_bytes += FSD_RECSZ((&fsd), fsd.fsd_size);
42507c478bd9Sstevel@tonic-gate 				cur_shad++;
42517c478bd9Sstevel@tonic-gate 				syncshadowscan(0);
42527c478bd9Sstevel@tonic-gate 			}
42537c478bd9Sstevel@tonic-gate 			addr = erraddr;
42547c478bd9Sstevel@tonic-gate 			cur_bytes = errcur_bytes;
42557c478bd9Sstevel@tonic-gate 			cur_shad--;
42567c478bd9Sstevel@tonic-gate 			if (tcount >= 0 && !star) {
42577c478bd9Sstevel@tonic-gate 				switch (type) {
42587c478bd9Sstevel@tonic-gate 				case FRAGMENT:
42597c478bd9Sstevel@tonic-gate 					printf("end of fragment\n");
42607c478bd9Sstevel@tonic-gate 					break;
42617c478bd9Sstevel@tonic-gate 				default:
42627c478bd9Sstevel@tonic-gate 					printf("end of shadow data\n");
42637c478bd9Sstevel@tonic-gate 				}
42647c478bd9Sstevel@tonic-gate 				error++;
42657c478bd9Sstevel@tonic-gate 			} else
42667c478bd9Sstevel@tonic-gate 				error = 0;
42677c478bd9Sstevel@tonic-gate 			return;
42687c478bd9Sstevel@tonic-gate 		default:
42697c478bd9Sstevel@tonic-gate 			error++;
42707c478bd9Sstevel@tonic-gate 			printf("no such print option\n");
42717c478bd9Sstevel@tonic-gate 			return;
42727c478bd9Sstevel@tonic-gate 		}
42737c478bd9Sstevel@tonic-gate }
42747c478bd9Sstevel@tonic-gate 
42757c478bd9Sstevel@tonic-gate /*
42767c478bd9Sstevel@tonic-gate  * valid_addr - call check_addr to validate the current address.
42777c478bd9Sstevel@tonic-gate  */
42787c478bd9Sstevel@tonic-gate static int
valid_addr()42797c478bd9Sstevel@tonic-gate valid_addr()
42807c478bd9Sstevel@tonic-gate {
42817c478bd9Sstevel@tonic-gate 	short	end = 0, eof = 0;
42827c478bd9Sstevel@tonic-gate 	long	tcount = count;
42837c478bd9Sstevel@tonic-gate 
42847c478bd9Sstevel@tonic-gate 	if (!trapped)
42857c478bd9Sstevel@tonic-gate 		return (1);
42867c478bd9Sstevel@tonic-gate 	if (cur_bytes < 0) {
42877c478bd9Sstevel@tonic-gate 		cur_bytes = 0;
42887c478bd9Sstevel@tonic-gate 		if (blocksize > filesize) {
42897c478bd9Sstevel@tonic-gate 			printf("beginning of file\n");
42907c478bd9Sstevel@tonic-gate 		} else {
42917c478bd9Sstevel@tonic-gate 			if (type == BLOCK)
42927c478bd9Sstevel@tonic-gate 				printf("beginning of block\n");
42937c478bd9Sstevel@tonic-gate 			else
42947c478bd9Sstevel@tonic-gate 				printf("beginning of fragment\n");
42957c478bd9Sstevel@tonic-gate 		}
42967c478bd9Sstevel@tonic-gate 		error++;
42977c478bd9Sstevel@tonic-gate 		return (0);
42987c478bd9Sstevel@tonic-gate 	}
42997c478bd9Sstevel@tonic-gate 	count = 1;
43007c478bd9Sstevel@tonic-gate 	(void) check_addr(1, &end, &eof, (filesize < blocksize));
43017c478bd9Sstevel@tonic-gate 	count = tcount;
43027c478bd9Sstevel@tonic-gate 	if (eof) {
43037c478bd9Sstevel@tonic-gate 		printf("end of file\n");
43047c478bd9Sstevel@tonic-gate 		error++;
43057c478bd9Sstevel@tonic-gate 		return (0);
43067c478bd9Sstevel@tonic-gate 	}
43077c478bd9Sstevel@tonic-gate 	if (end == 2) {
43087c478bd9Sstevel@tonic-gate 		if (erraddr > addr) {
43097c478bd9Sstevel@tonic-gate 			if (type == BLOCK)
43107c478bd9Sstevel@tonic-gate 				printf("beginning of block\n");
43117c478bd9Sstevel@tonic-gate 			else
43127c478bd9Sstevel@tonic-gate 				printf("beginning of fragment\n");
43137c478bd9Sstevel@tonic-gate 			error++;
43147c478bd9Sstevel@tonic-gate 			return (0);
43157c478bd9Sstevel@tonic-gate 		}
43167c478bd9Sstevel@tonic-gate 	}
43177c478bd9Sstevel@tonic-gate 	if (end) {
43187c478bd9Sstevel@tonic-gate 		if (type == BLOCK)
43197c478bd9Sstevel@tonic-gate 			printf("end of block\n");
43207c478bd9Sstevel@tonic-gate 		else
43217c478bd9Sstevel@tonic-gate 			printf("end of fragment\n");
43227c478bd9Sstevel@tonic-gate 		error++;
43237c478bd9Sstevel@tonic-gate 		return (0);
43247c478bd9Sstevel@tonic-gate 	}
43257c478bd9Sstevel@tonic-gate 	return (1);
43267c478bd9Sstevel@tonic-gate }
43277c478bd9Sstevel@tonic-gate 
43287c478bd9Sstevel@tonic-gate /*
43297c478bd9Sstevel@tonic-gate  * check_addr - check if the address crosses the end of block or
43307c478bd9Sstevel@tonic-gate  *	end of file.  Return the proper count.
43317c478bd9Sstevel@tonic-gate  */
43327c478bd9Sstevel@tonic-gate static int
check_addr(short eof_flag,short * end,short * eof,short keep_on)4333d1a180b0Smaheshvs check_addr(short eof_flag, short *end, short *eof, short keep_on)
43347c478bd9Sstevel@tonic-gate {
43357c478bd9Sstevel@tonic-gate 	long	temp, tcount = count, tcur_bytes = cur_bytes;
43367c478bd9Sstevel@tonic-gate 	u_offset_t	taddr = addr;
43377c478bd9Sstevel@tonic-gate 
43387c478bd9Sstevel@tonic-gate 	if (bcomp(addr + count * objsz - 1) ||
43397c478bd9Sstevel@tonic-gate 	    (keep_on && taddr < (bmap(cur_block) << FRGSHIFT))) {
43407c478bd9Sstevel@tonic-gate 		error = 0;
43417c478bd9Sstevel@tonic-gate 		addr = taddr;
43427c478bd9Sstevel@tonic-gate 		cur_bytes = tcur_bytes;
43437c478bd9Sstevel@tonic-gate 		if (keep_on) {
43447c478bd9Sstevel@tonic-gate 			if (addr < erraddr) {
43457c478bd9Sstevel@tonic-gate 				if (cur_bytes < 0) {
43467c478bd9Sstevel@tonic-gate 					(*end) = 2;
43477c478bd9Sstevel@tonic-gate 					return (0);	/* Value ignored */
43487c478bd9Sstevel@tonic-gate 				}
43497c478bd9Sstevel@tonic-gate 				temp = cur_block - lblkno(fs, cur_bytes);
43507c478bd9Sstevel@tonic-gate 				cur_block -= temp;
43517c478bd9Sstevel@tonic-gate 				if ((addr = bmap(cur_block) << FRGSHIFT) == 0) {
43527c478bd9Sstevel@tonic-gate 					cur_block += temp;
43537c478bd9Sstevel@tonic-gate 					return (0);	/* Value ignored */
43547c478bd9Sstevel@tonic-gate 				}
43557c478bd9Sstevel@tonic-gate 				temp = tcur_bytes - cur_bytes;
43567c478bd9Sstevel@tonic-gate 				addr += temp;
43577c478bd9Sstevel@tonic-gate 				cur_bytes += temp;
43587c478bd9Sstevel@tonic-gate 				return (0);	/* Value ignored */
43597c478bd9Sstevel@tonic-gate 			} else {
43607c478bd9Sstevel@tonic-gate 				if (cur_bytes >= filesize) {
43617c478bd9Sstevel@tonic-gate 					(*eof)++;
43627c478bd9Sstevel@tonic-gate 					return (0);	/* Value ignored */
43637c478bd9Sstevel@tonic-gate 				}
43647c478bd9Sstevel@tonic-gate 				temp = lblkno(fs, cur_bytes) - cur_block;
43657c478bd9Sstevel@tonic-gate 				cur_block += temp;
43667c478bd9Sstevel@tonic-gate 				if ((addr = bmap(cur_block) << FRGSHIFT) == 0) {
43677c478bd9Sstevel@tonic-gate 					cur_block -= temp;
43687c478bd9Sstevel@tonic-gate 					return (0);	/* Value ignored */
43697c478bd9Sstevel@tonic-gate 				}
43707c478bd9Sstevel@tonic-gate 				temp = tcur_bytes - cur_bytes;
43717c478bd9Sstevel@tonic-gate 				addr += temp;
43727c478bd9Sstevel@tonic-gate 				cur_bytes += temp;
43737c478bd9Sstevel@tonic-gate 				return (0);	/* Value ignored */
43747c478bd9Sstevel@tonic-gate 			}
43757c478bd9Sstevel@tonic-gate 		}
43767c478bd9Sstevel@tonic-gate 		tcount = (blkroundup(fs, addr+1)-addr) / objsz;
43777c478bd9Sstevel@tonic-gate 		if (!star)
43787c478bd9Sstevel@tonic-gate 			(*end) = 2;
43797c478bd9Sstevel@tonic-gate 	}
43807c478bd9Sstevel@tonic-gate 	addr = taddr;
43817c478bd9Sstevel@tonic-gate 	cur_bytes = tcur_bytes;
43827c478bd9Sstevel@tonic-gate 	if (eof_flag) {
43837c478bd9Sstevel@tonic-gate 		if (blocksize > filesize) {
43847c478bd9Sstevel@tonic-gate 			if (cur_bytes >= filesize) {
43857c478bd9Sstevel@tonic-gate 				tcount = 0;
43867c478bd9Sstevel@tonic-gate 				(*eof)++;
43877c478bd9Sstevel@tonic-gate 			} else if (tcount > (filesize - cur_bytes) / objsz) {
43887c478bd9Sstevel@tonic-gate 				tcount = (filesize - cur_bytes) / objsz;
43897c478bd9Sstevel@tonic-gate 				if (!star || tcount == 0)
43907c478bd9Sstevel@tonic-gate 					(*eof)++;
43917c478bd9Sstevel@tonic-gate 			}
43927c478bd9Sstevel@tonic-gate 		} else {
43937c478bd9Sstevel@tonic-gate 			if (cur_bytes >= blocksize) {
43947c478bd9Sstevel@tonic-gate 				tcount = 0;
43957c478bd9Sstevel@tonic-gate 				(*end)++;
43967c478bd9Sstevel@tonic-gate 			} else if (tcount > (blocksize - cur_bytes) / objsz) {
43977c478bd9Sstevel@tonic-gate 				tcount = (blocksize - cur_bytes) / objsz;
43987c478bd9Sstevel@tonic-gate 				if (!star || tcount == 0)
43997c478bd9Sstevel@tonic-gate 					(*end)++;
44007c478bd9Sstevel@tonic-gate 			}
44017c478bd9Sstevel@tonic-gate 		}
44027c478bd9Sstevel@tonic-gate 	}
44037c478bd9Sstevel@tonic-gate 	return (tcount);
44047c478bd9Sstevel@tonic-gate }
44057c478bd9Sstevel@tonic-gate 
44067c478bd9Sstevel@tonic-gate /*
44077c478bd9Sstevel@tonic-gate  * print_check - check if the index needs to be printed and delete
44087c478bd9Sstevel@tonic-gate  *	rows of zeros from the output.
44097c478bd9Sstevel@tonic-gate  */
44107c478bd9Sstevel@tonic-gate unsigned long *
print_check(unsigned long * lptr,long * tcount,short tbase,int i)4411d1a180b0Smaheshvs print_check(unsigned long *lptr, long *tcount, short tbase, int i)
44127c478bd9Sstevel@tonic-gate {
4413d1a180b0Smaheshvs 	int		j, k, temp = BYTESPERLINE / objsz;
44147c478bd9Sstevel@tonic-gate 	short		first_time = 0;
44157c478bd9Sstevel@tonic-gate 	unsigned long	*tlptr;
44167c478bd9Sstevel@tonic-gate 	unsigned short	*tsptr, *sptr;
44177c478bd9Sstevel@tonic-gate 
44187c478bd9Sstevel@tonic-gate 	sptr = (unsigned short *)lptr;
44197c478bd9Sstevel@tonic-gate 	if (i == 0)
44207c478bd9Sstevel@tonic-gate 		first_time = 1;
44217c478bd9Sstevel@tonic-gate 	if (i % temp == 0) {
44227c478bd9Sstevel@tonic-gate 		if (*tcount >= temp - 1) {
44237c478bd9Sstevel@tonic-gate 			if (objsz == SHORT)
44247c478bd9Sstevel@tonic-gate 				tsptr = sptr;
44257c478bd9Sstevel@tonic-gate 			else
44267c478bd9Sstevel@tonic-gate 				tlptr = lptr;
44277c478bd9Sstevel@tonic-gate 			k = *tcount - 1;
44287c478bd9Sstevel@tonic-gate 			for (j = i; k--; j++)
44297c478bd9Sstevel@tonic-gate 				if (objsz == SHORT) {
44307c478bd9Sstevel@tonic-gate 					if (*tsptr++ != 0)
44317c478bd9Sstevel@tonic-gate 						break;
44327c478bd9Sstevel@tonic-gate 				} else {
44337c478bd9Sstevel@tonic-gate 					if (*tlptr++ != 0)
44347c478bd9Sstevel@tonic-gate 						break;
44357c478bd9Sstevel@tonic-gate 				}
44367c478bd9Sstevel@tonic-gate 			if (j > (i + temp - 1)) {
44377c478bd9Sstevel@tonic-gate 				j = (j - i) / temp;
44387c478bd9Sstevel@tonic-gate 				while (j-- > 0) {
44397c478bd9Sstevel@tonic-gate 					if (objsz == SHORT)
44407c478bd9Sstevel@tonic-gate 						sptr += temp;
44417c478bd9Sstevel@tonic-gate 					else
44427c478bd9Sstevel@tonic-gate 						lptr += temp;
44437c478bd9Sstevel@tonic-gate 					*tcount -= temp;
44447c478bd9Sstevel@tonic-gate 					i += temp;
44457c478bd9Sstevel@tonic-gate 					addr += BYTESPERLINE;
44467c478bd9Sstevel@tonic-gate 					cur_bytes += BYTESPERLINE;
44477c478bd9Sstevel@tonic-gate 				}
44487c478bd9Sstevel@tonic-gate 				if (first_time)
44497c478bd9Sstevel@tonic-gate 					printf("*");
44507c478bd9Sstevel@tonic-gate 				else
44517c478bd9Sstevel@tonic-gate 					printf("\n*");
44527c478bd9Sstevel@tonic-gate 			}
44537c478bd9Sstevel@tonic-gate 			if (i)
44547c478bd9Sstevel@tonic-gate 				printf("\n");
44557c478bd9Sstevel@tonic-gate 			index(tbase);
44567c478bd9Sstevel@tonic-gate 		} else {
44577c478bd9Sstevel@tonic-gate 			if (i)
44587c478bd9Sstevel@tonic-gate 				printf("\n");
44597c478bd9Sstevel@tonic-gate 			index(tbase);
44607c478bd9Sstevel@tonic-gate 		}
44617c478bd9Sstevel@tonic-gate 	}
44627c478bd9Sstevel@tonic-gate 	if (objsz == SHORT)
44637c478bd9Sstevel@tonic-gate 		/*LINTED*/
44647c478bd9Sstevel@tonic-gate 		return ((unsigned long *)sptr);
44657c478bd9Sstevel@tonic-gate 	else
44667c478bd9Sstevel@tonic-gate 		return (lptr);
44677c478bd9Sstevel@tonic-gate }
44687c478bd9Sstevel@tonic-gate 
44697c478bd9Sstevel@tonic-gate /*
44707c478bd9Sstevel@tonic-gate  * index - print a byte index for the printout in base b
44717c478bd9Sstevel@tonic-gate  *	with leading zeros.
44727c478bd9Sstevel@tonic-gate  */
44737c478bd9Sstevel@tonic-gate static void
index(int b)4474d1a180b0Smaheshvs index(int b)
44757c478bd9Sstevel@tonic-gate {
44767c478bd9Sstevel@tonic-gate 	int	tbase = base;
44777c478bd9Sstevel@tonic-gate 
44787c478bd9Sstevel@tonic-gate 	base = b;
44797c478bd9Sstevel@tonic-gate 	print(addr, 8, 8, 1);
44807c478bd9Sstevel@tonic-gate 	printf(":\t");
44817c478bd9Sstevel@tonic-gate 	base = tbase;
44827c478bd9Sstevel@tonic-gate }
44837c478bd9Sstevel@tonic-gate 
44847c478bd9Sstevel@tonic-gate /*
44857c478bd9Sstevel@tonic-gate  * print - print out the value to digits places with/without
44867c478bd9Sstevel@tonic-gate  *	leading zeros and right/left justified in the current base.
44877c478bd9Sstevel@tonic-gate  */
44887c478bd9Sstevel@tonic-gate static void
44897c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
printll(u_offset_t value,int fieldsz,int digits,int lead)44907c478bd9Sstevel@tonic-gate printll(u_offset_t value, int fieldsz, int digits, int lead)
44917c478bd9Sstevel@tonic-gate #else /* !_LARGEFILE64_SOURCE */
44927c478bd9Sstevel@tonic-gate print(long value, int fieldsz, int digits, int lead)
44937c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
44947c478bd9Sstevel@tonic-gate {
4495d1a180b0Smaheshvs 	int	i, left = 0;
44967c478bd9Sstevel@tonic-gate 	char	mode = BASE[base - OCTAL];
44977c478bd9Sstevel@tonic-gate 	char	*string = &scratch[0];
44987c478bd9Sstevel@tonic-gate 
44997c478bd9Sstevel@tonic-gate 	if (digits < 0) {
45007c478bd9Sstevel@tonic-gate 		left = 1;
45017c478bd9Sstevel@tonic-gate 		digits *= -1;
45027c478bd9Sstevel@tonic-gate 	}
45037c478bd9Sstevel@tonic-gate 	if (base != HEX)
45047c478bd9Sstevel@tonic-gate 		if (digits)
45057c478bd9Sstevel@tonic-gate 			digits = digits + (digits - 1)/((base >> 1) - 1) + 1;
45067c478bd9Sstevel@tonic-gate 		else
45077c478bd9Sstevel@tonic-gate 			digits = 1;
45087c478bd9Sstevel@tonic-gate 	if (lead) {
45097c478bd9Sstevel@tonic-gate 		if (left)
45107c478bd9Sstevel@tonic-gate 			(void) sprintf(string, "%%%c%d%d.%d"
45117c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45127c478bd9Sstevel@tonic-gate 				"ll"
45137c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45147c478bd9Sstevel@tonic-gate 				"%c", '-', 0, digits, lead, mode);
45157c478bd9Sstevel@tonic-gate 		else
45167c478bd9Sstevel@tonic-gate 			(void) sprintf(string, "%%%d%d.%d"
45177c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45187c478bd9Sstevel@tonic-gate 				"ll"
45197c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45207c478bd9Sstevel@tonic-gate 				"%c", 0, digits, lead, mode);
45217c478bd9Sstevel@tonic-gate 	} else {
45227c478bd9Sstevel@tonic-gate 		if (left)
45237c478bd9Sstevel@tonic-gate 			(void) sprintf(string, "%%%c%d"
45247c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45257c478bd9Sstevel@tonic-gate 				"ll"
45267c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45277c478bd9Sstevel@tonic-gate 				"%c", '-', digits, mode);
45287c478bd9Sstevel@tonic-gate 		else
45297c478bd9Sstevel@tonic-gate 			(void) sprintf(string, "%%%d"
45307c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
45317c478bd9Sstevel@tonic-gate 				"ll"
45327c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
45337c478bd9Sstevel@tonic-gate 				"%c", digits, mode);
45347c478bd9Sstevel@tonic-gate 	}
45357c478bd9Sstevel@tonic-gate 	printf(string, value);
45367c478bd9Sstevel@tonic-gate 	for (i = 0; i < fieldsz - digits; i++)
45377c478bd9Sstevel@tonic-gate 		printf(" ");
45387c478bd9Sstevel@tonic-gate }
45397c478bd9Sstevel@tonic-gate 
45407c478bd9Sstevel@tonic-gate /*
45417c478bd9Sstevel@tonic-gate  * Print out the contents of a superblock.
45427c478bd9Sstevel@tonic-gate  */
45437c478bd9Sstevel@tonic-gate static void
printsb(struct fs * fs)4544d1a180b0Smaheshvs printsb(struct fs *fs)
45457c478bd9Sstevel@tonic-gate {
45467c478bd9Sstevel@tonic-gate 	int c, i, j, k, size;
45477c478bd9Sstevel@tonic-gate 	caddr_t sip;
45487c478bd9Sstevel@tonic-gate 	time_t t;
45497c478bd9Sstevel@tonic-gate 
45507c478bd9Sstevel@tonic-gate 	t = fs->fs_time;
45517c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
45527c478bd9Sstevel@tonic-gate 	if (fs->fs_postblformat == FS_42POSTBLFMT)
45537c478bd9Sstevel@tonic-gate 		fs->fs_nrpos = 8;
45547c478bd9Sstevel@tonic-gate 	printf("magic\t%lx\tformat\t%s\ttime\t%s", fs->fs_magic,
45557c478bd9Sstevel@tonic-gate 	    fs->fs_postblformat == FS_42POSTBLFMT ? "static" : "dynamic",
45567c478bd9Sstevel@tonic-gate 	    ctime(&t));
45577c478bd9Sstevel@tonic-gate #else
45587c478bd9Sstevel@tonic-gate 	printf("magic\t%x\ttime\t%s",
45597c478bd9Sstevel@tonic-gate 	    fs->fs_magic, ctime(&t));
45607c478bd9Sstevel@tonic-gate #endif
45617c478bd9Sstevel@tonic-gate 	printf("version\t%x\n", fs->fs_version);
45627c478bd9Sstevel@tonic-gate 	printf("nbfree\t%ld\tndir\t%ld\tnifree\t%ld\tnffree\t%ld\n",
45637c478bd9Sstevel@tonic-gate 	    fs->fs_cstotal.cs_nbfree, fs->fs_cstotal.cs_ndir,
45647c478bd9Sstevel@tonic-gate 	    fs->fs_cstotal.cs_nifree, fs->fs_cstotal.cs_nffree);
45657c478bd9Sstevel@tonic-gate 	printf("ncg\t%ld\tncyl\t%ld\tsize\t%ld\tblocks\t%ld\n",
45667c478bd9Sstevel@tonic-gate 	    fs->fs_ncg, fs->fs_ncyl, fs->fs_size, fs->fs_dsize);
45677c478bd9Sstevel@tonic-gate 	printf("bsize\t%ld\tshift\t%ld\tmask\t0x%08lx\n",
45687c478bd9Sstevel@tonic-gate 	    fs->fs_bsize, fs->fs_bshift, fs->fs_bmask);
45697c478bd9Sstevel@tonic-gate 	printf("fsize\t%ld\tshift\t%ld\tmask\t0x%08lx\n",
45707c478bd9Sstevel@tonic-gate 	    fs->fs_fsize, fs->fs_fshift, fs->fs_fmask);
45717c478bd9Sstevel@tonic-gate 	printf("frag\t%ld\tshift\t%ld\tfsbtodb\t%ld\n",
45727c478bd9Sstevel@tonic-gate 	    fs->fs_frag, fs->fs_fragshift, fs->fs_fsbtodb);
45737c478bd9Sstevel@tonic-gate 	printf("cpg\t%ld\tbpg\t%ld\tfpg\t%ld\tipg\t%ld\n",
45747c478bd9Sstevel@tonic-gate 	    fs->fs_cpg, fs->fs_fpg / fs->fs_frag, fs->fs_fpg, fs->fs_ipg);
45757c478bd9Sstevel@tonic-gate 	printf("minfree\t%ld%%\toptim\t%s\tmaxcontig %ld\tmaxbpg\t%ld\n",
45767c478bd9Sstevel@tonic-gate 	    fs->fs_minfree, fs->fs_optim == FS_OPTSPACE ? "space" : "time",
45777c478bd9Sstevel@tonic-gate 	    fs->fs_maxcontig, fs->fs_maxbpg);
45787c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
45797c478bd9Sstevel@tonic-gate #ifdef sun
45807c478bd9Sstevel@tonic-gate 	printf("rotdelay %ldms\tfs_id[0] 0x%lx\tfs_id[1] 0x%lx\trps\t%ld\n",
45817c478bd9Sstevel@tonic-gate 	    fs->fs_rotdelay, fs->fs_id[0], fs->fs_id[1], fs->fs_rps);
45827c478bd9Sstevel@tonic-gate #else
45837c478bd9Sstevel@tonic-gate 	printf("rotdelay %dms\theadswitch %dus\ttrackseek %dus\trps\t%d\n",
45847c478bd9Sstevel@tonic-gate 	    fs->fs_rotdelay, fs->fs_headswitch, fs->fs_trkseek, fs->fs_rps);
45857c478bd9Sstevel@tonic-gate #endif /* sun */
45867c478bd9Sstevel@tonic-gate 	printf("ntrak\t%ld\tnsect\t%ld\tnpsect\t%ld\tspc\t%ld\n",
45877c478bd9Sstevel@tonic-gate 	    fs->fs_ntrak, fs->fs_nsect, fs->fs_npsect, fs->fs_spc);
45887c478bd9Sstevel@tonic-gate 	printf("trackskew %ld\n", fs->fs_trackskew);
45897c478bd9Sstevel@tonic-gate #else
45907c478bd9Sstevel@tonic-gate 	printf("rotdelay %ldms\trps\t%ld\n",
45917c478bd9Sstevel@tonic-gate 	    fs->fs_rotdelay, fs->fs_rps);
45927c478bd9Sstevel@tonic-gate 	printf("ntrak\t%ld\tnsect\t%ld\tspc\t%ld\n",
45937c478bd9Sstevel@tonic-gate 	    fs->fs_ntrak, fs->fs_nsect, fs->fs_spc);
45947c478bd9Sstevel@tonic-gate #endif
45957c478bd9Sstevel@tonic-gate 	printf("si %ld\n", fs->fs_si);
45967c478bd9Sstevel@tonic-gate 	printf("nindir\t%ld\tinopb\t%ld\tnspf\t%ld\n",
45977c478bd9Sstevel@tonic-gate 	    fs->fs_nindir, fs->fs_inopb, fs->fs_nspf);
45987c478bd9Sstevel@tonic-gate 	printf("sblkno\t%ld\tcblkno\t%ld\tiblkno\t%ld\tdblkno\t%ld\n",
45997c478bd9Sstevel@tonic-gate 	    fs->fs_sblkno, fs->fs_cblkno, fs->fs_iblkno, fs->fs_dblkno);
46007c478bd9Sstevel@tonic-gate 	printf("sbsize\t%ld\tcgsize\t%ld\tcgoffset %ld\tcgmask\t0x%08lx\n",
46017c478bd9Sstevel@tonic-gate 	    fs->fs_sbsize, fs->fs_cgsize, fs->fs_cgoffset, fs->fs_cgmask);
46027c478bd9Sstevel@tonic-gate 	printf("csaddr\t%ld\tcssize\t%ld\tshift\t%ld\tmask\t0x%08lx\n",
46037c478bd9Sstevel@tonic-gate 	    fs->fs_csaddr, fs->fs_cssize, fs->fs_csshift, fs->fs_csmask);
46047c478bd9Sstevel@tonic-gate 	printf("cgrotor\t%ld\tfmod\t%d\tronly\t%d\n",
46057c478bd9Sstevel@tonic-gate 	    fs->fs_cgrotor, fs->fs_fmod, fs->fs_ronly);
46067c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
46077c478bd9Sstevel@tonic-gate 	if (fs->fs_cpc != 0)
46087c478bd9Sstevel@tonic-gate 		printf("blocks available in each of %ld rotational positions",
46097c478bd9Sstevel@tonic-gate 			fs->fs_nrpos);
46107c478bd9Sstevel@tonic-gate 	else
46117c478bd9Sstevel@tonic-gate 		printf("insufficient space to maintain rotational tables\n");
46127c478bd9Sstevel@tonic-gate #endif
46137c478bd9Sstevel@tonic-gate 	for (c = 0; c < fs->fs_cpc; c++) {
46147c478bd9Sstevel@tonic-gate 		printf("\ncylinder number %d:", c);
46157c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
46167c478bd9Sstevel@tonic-gate 		for (i = 0; i < fs->fs_nrpos; i++) {
46177c478bd9Sstevel@tonic-gate 			/*LINTED*/
46187c478bd9Sstevel@tonic-gate 			if (fs_postbl(fs, c)[i] == -1)
46197c478bd9Sstevel@tonic-gate 				continue;
46207c478bd9Sstevel@tonic-gate 			printf("\n   position %d:\t", i);
46217c478bd9Sstevel@tonic-gate 			/*LINTED*/
46227c478bd9Sstevel@tonic-gate 			for (j = fs_postbl(fs, c)[i], k = 1; /* void */;
46237c478bd9Sstevel@tonic-gate 						j += fs_rotbl(fs)[j], k++) {
46247c478bd9Sstevel@tonic-gate 				printf("%5d", j);
46257c478bd9Sstevel@tonic-gate 				if (k % 12 == 0)
46267c478bd9Sstevel@tonic-gate 					printf("\n\t\t");
46277c478bd9Sstevel@tonic-gate 				if (fs_rotbl(fs)[j] == 0)
46287c478bd9Sstevel@tonic-gate 					break;
46297c478bd9Sstevel@tonic-gate 			}
46307c478bd9Sstevel@tonic-gate 		}
46317c478bd9Sstevel@tonic-gate #else
46327c478bd9Sstevel@tonic-gate 		for (i = 0; i < NRPOS; i++) {
46337c478bd9Sstevel@tonic-gate 			if (fs->fs_postbl[c][i] == -1)
46347c478bd9Sstevel@tonic-gate 				continue;
46357c478bd9Sstevel@tonic-gate 			printf("\n   position %d:\t", i);
46367c478bd9Sstevel@tonic-gate 			for (j = fs->fs_postbl[c][i], k = 1; /* void */;
46377c478bd9Sstevel@tonic-gate 						j += fs->fs_rotbl[j], k++) {
46387c478bd9Sstevel@tonic-gate 				printf("%5d", j);
46397c478bd9Sstevel@tonic-gate 				if (k % 12 == 0)
46407c478bd9Sstevel@tonic-gate 					printf("\n\t\t");
46417c478bd9Sstevel@tonic-gate 				if (fs->fs_rotbl[j] == 0)
46427c478bd9Sstevel@tonic-gate 					break;
46437c478bd9Sstevel@tonic-gate 			}
46447c478bd9Sstevel@tonic-gate 		}
46457c478bd9Sstevel@tonic-gate #endif
46467c478bd9Sstevel@tonic-gate 	}
46477c478bd9Sstevel@tonic-gate 	printf("\ncs[].cs_(nbfree, ndir, nifree, nffree):");
46487c478bd9Sstevel@tonic-gate 	sip = calloc(1, fs->fs_cssize);
46497c478bd9Sstevel@tonic-gate 	fs->fs_u.fs_csp = (struct csum *)sip;
46507c478bd9Sstevel@tonic-gate 	for (i = 0, j = 0; i < fs->fs_cssize; i += fs->fs_bsize, j++) {
46517c478bd9Sstevel@tonic-gate 		size = fs->fs_cssize - i < fs->fs_bsize ?
46527c478bd9Sstevel@tonic-gate 		    fs->fs_cssize - i : fs->fs_bsize;
46537c478bd9Sstevel@tonic-gate 		(void) llseek(fd,
46547c478bd9Sstevel@tonic-gate 			(offset_t)fsbtodb(fs, (fs->fs_csaddr + j * fs->fs_frag))
46557c478bd9Sstevel@tonic-gate 				* fs->fs_fsize / fsbtodb(fs, 1), 0);
46567c478bd9Sstevel@tonic-gate 		if (read(fd, sip, size) != size) {
46577c478bd9Sstevel@tonic-gate 			free(fs->fs_u.fs_csp);
46587c478bd9Sstevel@tonic-gate 			return;
46597c478bd9Sstevel@tonic-gate 		}
46607c478bd9Sstevel@tonic-gate 		sip += size;
46617c478bd9Sstevel@tonic-gate 	}
46627c478bd9Sstevel@tonic-gate 	for (i = 0; i < fs->fs_ncg; i++) {
46637c478bd9Sstevel@tonic-gate 		struct csum *cs = &fs->fs_cs(fs, i);
46647c478bd9Sstevel@tonic-gate 		if (i % 4 == 0)
46657c478bd9Sstevel@tonic-gate 			printf("\n     ");
46667c478bd9Sstevel@tonic-gate 		printf("%d:(%ld,%ld,%ld,%ld) ", i, cs->cs_nbfree, cs->cs_ndir,
46677c478bd9Sstevel@tonic-gate 						cs->cs_nifree, cs->cs_nffree);
46687c478bd9Sstevel@tonic-gate 	}
46697c478bd9Sstevel@tonic-gate 	free(fs->fs_u.fs_csp);
46707c478bd9Sstevel@tonic-gate 	printf("\n");
46717c478bd9Sstevel@tonic-gate 	if (fs->fs_ncyl % fs->fs_cpg) {
46727c478bd9Sstevel@tonic-gate 		printf("cylinders in last group %d\n",
46737c478bd9Sstevel@tonic-gate 		    i = fs->fs_ncyl % fs->fs_cpg);
46747c478bd9Sstevel@tonic-gate 		printf("blocks in last group %ld\n",
46757c478bd9Sstevel@tonic-gate 		    i * fs->fs_spc / NSPB(fs));
46767c478bd9Sstevel@tonic-gate 	}
46777c478bd9Sstevel@tonic-gate }
46787c478bd9Sstevel@tonic-gate 
46797c478bd9Sstevel@tonic-gate /*
46807c478bd9Sstevel@tonic-gate  * Print out the contents of a cylinder group.
46817c478bd9Sstevel@tonic-gate  */
46827c478bd9Sstevel@tonic-gate static void
printcg(struct cg * cg)4683d1a180b0Smaheshvs printcg(struct cg *cg)
46847c478bd9Sstevel@tonic-gate {
46857c478bd9Sstevel@tonic-gate 	int i, j;
46867c478bd9Sstevel@tonic-gate 	time_t t;
46877c478bd9Sstevel@tonic-gate 
46887c478bd9Sstevel@tonic-gate 	printf("\ncg %ld:\n", cg->cg_cgx);
46897c478bd9Sstevel@tonic-gate 	t = cg->cg_time;
46907c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
46917c478bd9Sstevel@tonic-gate 	printf("magic\t%lx\ttell\t%llx\ttime\t%s",
46927c478bd9Sstevel@tonic-gate 	    fs->fs_postblformat == FS_42POSTBLFMT ?
46937c478bd9Sstevel@tonic-gate 	    ((struct ocg *)cg)->cg_magic : cg->cg_magic,
46947c478bd9Sstevel@tonic-gate 	    fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1),
46957c478bd9Sstevel@tonic-gate 	    ctime(&t));
46967c478bd9Sstevel@tonic-gate #else
46977c478bd9Sstevel@tonic-gate 	printf("magic\t%x\ttell\t%llx\ttime\t%s",
46987c478bd9Sstevel@tonic-gate 	    cg->cg_magic,
46997c478bd9Sstevel@tonic-gate 	    fsbtodb(fs, cgtod(fs, cg->cg_cgx)) * fs->fs_fsize / fsbtodb(fs, 1),
47007c478bd9Sstevel@tonic-gate 	    ctime(&t));
47017c478bd9Sstevel@tonic-gate #endif
47027c478bd9Sstevel@tonic-gate 	printf("cgx\t%ld\tncyl\t%d\tniblk\t%d\tndblk\t%ld\n",
47037c478bd9Sstevel@tonic-gate 	    cg->cg_cgx, cg->cg_ncyl, cg->cg_niblk, cg->cg_ndblk);
47047c478bd9Sstevel@tonic-gate 	printf("nbfree\t%ld\tndir\t%ld\tnifree\t%ld\tnffree\t%ld\n",
47057c478bd9Sstevel@tonic-gate 	    cg->cg_cs.cs_nbfree, cg->cg_cs.cs_ndir,
47067c478bd9Sstevel@tonic-gate 	    cg->cg_cs.cs_nifree, cg->cg_cs.cs_nffree);
47077c478bd9Sstevel@tonic-gate 	printf("rotor\t%ld\tirotor\t%ld\tfrotor\t%ld\nfrsum",
47087c478bd9Sstevel@tonic-gate 	    cg->cg_rotor, cg->cg_irotor, cg->cg_frotor);
47097c478bd9Sstevel@tonic-gate 	for (i = 1, j = 0; i < fs->fs_frag; i++) {
47107c478bd9Sstevel@tonic-gate 		printf("\t%ld", cg->cg_frsum[i]);
47117c478bd9Sstevel@tonic-gate 		j += i * cg->cg_frsum[i];
47127c478bd9Sstevel@tonic-gate 	}
47137c478bd9Sstevel@tonic-gate 	printf("\nsum of frsum: %d\niused:\t", j);
47147c478bd9Sstevel@tonic-gate 	pbits((unsigned char *)cg_inosused(cg), fs->fs_ipg);
47157c478bd9Sstevel@tonic-gate 	printf("free:\t");
47167c478bd9Sstevel@tonic-gate 	pbits(cg_blksfree(cg), fs->fs_fpg);
47177c478bd9Sstevel@tonic-gate 	printf("b:\n");
47187c478bd9Sstevel@tonic-gate 	for (i = 0; i < fs->fs_cpg; i++) {
47197c478bd9Sstevel@tonic-gate 		/*LINTED*/
47207c478bd9Sstevel@tonic-gate 		if (cg_blktot(cg)[i] == 0)
47217c478bd9Sstevel@tonic-gate 			continue;
47227c478bd9Sstevel@tonic-gate 		/*LINTED*/
47237c478bd9Sstevel@tonic-gate 		printf("   c%d:\t(%ld)\t", i, cg_blktot(cg)[i]);
47247c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
47257c478bd9Sstevel@tonic-gate 		for (j = 0; j < fs->fs_nrpos; j++) {
47267c478bd9Sstevel@tonic-gate 			if (fs->fs_cpc == 0 ||
47277c478bd9Sstevel@tonic-gate 				/*LINTED*/
47287c478bd9Sstevel@tonic-gate 			    fs_postbl(fs, i % fs->fs_cpc)[j] == -1)
47297c478bd9Sstevel@tonic-gate 				continue;
47307c478bd9Sstevel@tonic-gate 			/*LINTED*/
47317c478bd9Sstevel@tonic-gate 			printf(" %d", cg_blks(fs, cg, i)[j]);
47327c478bd9Sstevel@tonic-gate 		}
47337c478bd9Sstevel@tonic-gate #else
47347c478bd9Sstevel@tonic-gate 		for (j = 0; j < NRPOS; j++) {
47357c478bd9Sstevel@tonic-gate 			if (fs->fs_cpc == 0 ||
47367c478bd9Sstevel@tonic-gate 			    fs->fs_postbl[i % fs->fs_cpc][j] == -1)
47377c478bd9Sstevel@tonic-gate 				continue;
47387c478bd9Sstevel@tonic-gate 			printf(" %d", cg->cg_b[i][j]);
47397c478bd9Sstevel@tonic-gate 		}
47407c478bd9Sstevel@tonic-gate #endif
47417c478bd9Sstevel@tonic-gate 		printf("\n");
47427c478bd9Sstevel@tonic-gate 	}
47437c478bd9Sstevel@tonic-gate }
47447c478bd9Sstevel@tonic-gate 
47457c478bd9Sstevel@tonic-gate /*
47467c478bd9Sstevel@tonic-gate  * Print out the contents of a bit array.
47477c478bd9Sstevel@tonic-gate  */
47487c478bd9Sstevel@tonic-gate static void
pbits(unsigned char * cp,int max)4749d1a180b0Smaheshvs pbits(unsigned char *cp, int max)
47507c478bd9Sstevel@tonic-gate {
4751d1a180b0Smaheshvs 	int i;
47527c478bd9Sstevel@tonic-gate 	int count = 0, j;
47537c478bd9Sstevel@tonic-gate 
47547c478bd9Sstevel@tonic-gate 	for (i = 0; i < max; i++)
47557c478bd9Sstevel@tonic-gate 		if (isset(cp, i)) {
47567c478bd9Sstevel@tonic-gate 			if (count)
47577c478bd9Sstevel@tonic-gate 				printf(",%s", count % 6 ? " " : "\n\t");
47587c478bd9Sstevel@tonic-gate 			count++;
47597c478bd9Sstevel@tonic-gate 			printf("%d", i);
47607c478bd9Sstevel@tonic-gate 			j = i;
47617c478bd9Sstevel@tonic-gate 			while ((i+1) < max && isset(cp, i+1))
47627c478bd9Sstevel@tonic-gate 				i++;
47637c478bd9Sstevel@tonic-gate 			if (i != j)
47647c478bd9Sstevel@tonic-gate 				printf("-%d", i);
47657c478bd9Sstevel@tonic-gate 		}
47667c478bd9Sstevel@tonic-gate 	printf("\n");
47677c478bd9Sstevel@tonic-gate }
47687c478bd9Sstevel@tonic-gate 
47697c478bd9Sstevel@tonic-gate /*
47707c478bd9Sstevel@tonic-gate  * bcomp - used to check for block over/under flows when stepping through
47717c478bd9Sstevel@tonic-gate  *	a file system.
47727c478bd9Sstevel@tonic-gate  */
47737c478bd9Sstevel@tonic-gate static int
bcomp(addr)47747c478bd9Sstevel@tonic-gate bcomp(addr)
47757c478bd9Sstevel@tonic-gate 	u_offset_t	addr;
47767c478bd9Sstevel@tonic-gate {
47777c478bd9Sstevel@tonic-gate 	if (override)
47787c478bd9Sstevel@tonic-gate 		return (0);
47797c478bd9Sstevel@tonic-gate 
47807c478bd9Sstevel@tonic-gate 	if (lblkno(fs, addr) == (bhdr.fwd)->blkno)
47817c478bd9Sstevel@tonic-gate 		return (0);
47827c478bd9Sstevel@tonic-gate 	error++;
47837c478bd9Sstevel@tonic-gate 	return (1);
47847c478bd9Sstevel@tonic-gate }
47857c478bd9Sstevel@tonic-gate 
47867c478bd9Sstevel@tonic-gate /*
47877c478bd9Sstevel@tonic-gate  * bmap - maps the logical block number of a file into
47887c478bd9Sstevel@tonic-gate  *	the corresponding physical block on the file
47897c478bd9Sstevel@tonic-gate  *	system.
47907c478bd9Sstevel@tonic-gate  */
47917c478bd9Sstevel@tonic-gate static long
bmap(long bn)4792d1a180b0Smaheshvs bmap(long bn)
47937c478bd9Sstevel@tonic-gate {
4794d1a180b0Smaheshvs 	int		j;
4795d1a180b0Smaheshvs 	struct dinode	*ip;
47967c478bd9Sstevel@tonic-gate 	int		sh;
47977c478bd9Sstevel@tonic-gate 	long		nb;
4798d1a180b0Smaheshvs 	char		*cptr;
47997c478bd9Sstevel@tonic-gate 
48007c478bd9Sstevel@tonic-gate 	if ((cptr = getblk(cur_ino)) == 0)
48017c478bd9Sstevel@tonic-gate 		return (0);
48027c478bd9Sstevel@tonic-gate 
48037c478bd9Sstevel@tonic-gate 	cptr += blkoff(fs, cur_ino);
48047c478bd9Sstevel@tonic-gate 
48057c478bd9Sstevel@tonic-gate 	/*LINTED*/
48067c478bd9Sstevel@tonic-gate 	ip = (struct dinode *)cptr;
48077c478bd9Sstevel@tonic-gate 
48087c478bd9Sstevel@tonic-gate 	if (bn < NDADDR) {
48097c478bd9Sstevel@tonic-gate 		nb = ip->di_db[bn];
48107c478bd9Sstevel@tonic-gate 		return (nullblk(nb) ? 0L : nb);
48117c478bd9Sstevel@tonic-gate 	}
48127c478bd9Sstevel@tonic-gate 
48137c478bd9Sstevel@tonic-gate 	sh = 1;
48147c478bd9Sstevel@tonic-gate 	bn -= NDADDR;
48157c478bd9Sstevel@tonic-gate 	for (j = NIADDR; j > 0; j--) {
48167c478bd9Sstevel@tonic-gate 		sh *= NINDIR(fs);
48177c478bd9Sstevel@tonic-gate 		if (bn < sh)
48187c478bd9Sstevel@tonic-gate 			break;
48197c478bd9Sstevel@tonic-gate 		bn -= sh;
48207c478bd9Sstevel@tonic-gate 	}
48217c478bd9Sstevel@tonic-gate 	if (j == 0) {
48227c478bd9Sstevel@tonic-gate 		printf("file too big\n");
48237c478bd9Sstevel@tonic-gate 		error++;
48247c478bd9Sstevel@tonic-gate 		return (0L);
48257c478bd9Sstevel@tonic-gate 	}
48267c478bd9Sstevel@tonic-gate 	addr = (uintptr_t)&ip->di_ib[NIADDR - j];
48277c478bd9Sstevel@tonic-gate 	nb = get(LONG);
48287c478bd9Sstevel@tonic-gate 	if (nb == 0)
48297c478bd9Sstevel@tonic-gate 		return (0L);
48307c478bd9Sstevel@tonic-gate 	for (; j <= NIADDR; j++) {
48317c478bd9Sstevel@tonic-gate 		sh /= NINDIR(fs);
48327c478bd9Sstevel@tonic-gate 		addr = (nb << FRGSHIFT) + ((bn / sh) % NINDIR(fs)) * LONG;
48337c478bd9Sstevel@tonic-gate 		if (nullblk(nb = get(LONG)))
48347c478bd9Sstevel@tonic-gate 			return (0L);
48357c478bd9Sstevel@tonic-gate 	}
48367c478bd9Sstevel@tonic-gate 	return (nb);
48377c478bd9Sstevel@tonic-gate }
48387c478bd9Sstevel@tonic-gate 
48397c478bd9Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
48407c478bd9Sstevel@tonic-gate 
48417c478bd9Sstevel@tonic-gate /*
48427c478bd9Sstevel@tonic-gate  * The following are "tacked on" to support the old fsdb functionality
48437c478bd9Sstevel@tonic-gate  * of clearing an inode. (All together now...) "It's better to use clri".
48447c478bd9Sstevel@tonic-gate  */
48457c478bd9Sstevel@tonic-gate 
48467c478bd9Sstevel@tonic-gate #define	ISIZE	(sizeof (struct dinode))
48477c478bd9Sstevel@tonic-gate #define	NI	(MAXBSIZE/ISIZE)
48487c478bd9Sstevel@tonic-gate 
48497c478bd9Sstevel@tonic-gate 
48507c478bd9Sstevel@tonic-gate static struct	dinode	di_buf[NI];
48517c478bd9Sstevel@tonic-gate 
48527c478bd9Sstevel@tonic-gate static union {
48537c478bd9Sstevel@tonic-gate 	char		dummy[SBSIZE];
48547c478bd9Sstevel@tonic-gate 	struct fs	sblk;
48557c478bd9Sstevel@tonic-gate } sb_un;
48567c478bd9Sstevel@tonic-gate 
48577c478bd9Sstevel@tonic-gate #define	sblock sb_un.sblk
48587c478bd9Sstevel@tonic-gate 
48597c478bd9Sstevel@tonic-gate static void
old_fsdb(int inum,char * special)4860d1a180b0Smaheshvs old_fsdb(int inum, char *special)
48617c478bd9Sstevel@tonic-gate {
48627c478bd9Sstevel@tonic-gate 	int		f;	/* File descriptor for "special" */
48637c478bd9Sstevel@tonic-gate 	int		j;
48647c478bd9Sstevel@tonic-gate 	int		status = 0;
48657c478bd9Sstevel@tonic-gate 	u_offset_t	off;
48667c478bd9Sstevel@tonic-gate 	long		gen;
48677c478bd9Sstevel@tonic-gate 	time_t		t;
48687c478bd9Sstevel@tonic-gate 
48697c478bd9Sstevel@tonic-gate 	f = open(special, 2);
48707c478bd9Sstevel@tonic-gate 	if (f < 0) {
48717c478bd9Sstevel@tonic-gate 		perror("open");
48727c478bd9Sstevel@tonic-gate 		printf("cannot open %s\n", special);
48737c478bd9Sstevel@tonic-gate 		exit(31+4);
48747c478bd9Sstevel@tonic-gate 	}
48757c478bd9Sstevel@tonic-gate 	(void) llseek(f, (offset_t)SBLOCK * DEV_BSIZE, 0);
48767c478bd9Sstevel@tonic-gate 	if (read(f, &sblock, SBSIZE) != SBSIZE) {
48777c478bd9Sstevel@tonic-gate 		printf("cannot read %s\n", special);
48787c478bd9Sstevel@tonic-gate 		exit(31+4);
48797c478bd9Sstevel@tonic-gate 	}
48807c478bd9Sstevel@tonic-gate 	if (sblock.fs_magic != FS_MAGIC) {
48817c478bd9Sstevel@tonic-gate 		printf("bad super block magic number\n");
48827c478bd9Sstevel@tonic-gate 		exit(31+4);
48837c478bd9Sstevel@tonic-gate 	}
48847c478bd9Sstevel@tonic-gate 	if (inum == 0) {
48857c478bd9Sstevel@tonic-gate 		printf("%d: is zero\n", inum);
48867c478bd9Sstevel@tonic-gate 		exit(31+1);
48877c478bd9Sstevel@tonic-gate 	}
48887c478bd9Sstevel@tonic-gate 	off = (u_offset_t)fsbtodb(&sblock, itod(&sblock, inum)) * DEV_BSIZE;
48897c478bd9Sstevel@tonic-gate 	(void) llseek(f, off, 0);
48907c478bd9Sstevel@tonic-gate 	if (read(f, (char *)di_buf, sblock.fs_bsize) != sblock.fs_bsize) {
48917c478bd9Sstevel@tonic-gate 		printf("%s: read error\n", special);
48927c478bd9Sstevel@tonic-gate 		status = 1;
48937c478bd9Sstevel@tonic-gate 	}
48947c478bd9Sstevel@tonic-gate 	if (status)
48957c478bd9Sstevel@tonic-gate 		exit(31+status);
48967c478bd9Sstevel@tonic-gate 
48977c478bd9Sstevel@tonic-gate 	/*
48987c478bd9Sstevel@tonic-gate 	 * Update the time in superblock, so fsck will check this filesystem.
48997c478bd9Sstevel@tonic-gate 	 */
49007c478bd9Sstevel@tonic-gate 	(void) llseek(f, (offset_t)(SBLOCK * DEV_BSIZE), 0);
49017c478bd9Sstevel@tonic-gate 	(void) time(&t);
49027c478bd9Sstevel@tonic-gate 	sblock.fs_time = (time32_t)t;
49037c478bd9Sstevel@tonic-gate 	if (write(f, &sblock, SBSIZE) != SBSIZE) {
49047c478bd9Sstevel@tonic-gate 		printf("cannot update %s\n", special);
49057c478bd9Sstevel@tonic-gate 		exit(35);
49067c478bd9Sstevel@tonic-gate 	}
49077c478bd9Sstevel@tonic-gate 
49087c478bd9Sstevel@tonic-gate 	printf("clearing %u\n", inum);
49097c478bd9Sstevel@tonic-gate 	off = (u_offset_t)fsbtodb(&sblock, itod(&sblock, inum)) * DEV_BSIZE;
49107c478bd9Sstevel@tonic-gate 	(void) llseek(f, off, 0);
49117c478bd9Sstevel@tonic-gate 	read(f, (char *)di_buf, sblock.fs_bsize);
49127c478bd9Sstevel@tonic-gate 	j = itoo(&sblock, inum);
49137c478bd9Sstevel@tonic-gate 	gen = di_buf[j].di_gen;
49147c478bd9Sstevel@tonic-gate 	(void) memset((caddr_t)&di_buf[j], 0, ISIZE);
49157c478bd9Sstevel@tonic-gate 	di_buf[j].di_gen = gen + 1;
49167c478bd9Sstevel@tonic-gate 	(void) llseek(f, off, 0);
49177c478bd9Sstevel@tonic-gate 	write(f, (char *)di_buf, sblock.fs_bsize);
49187c478bd9Sstevel@tonic-gate 	exit(31+status);
49197c478bd9Sstevel@tonic-gate }
49207c478bd9Sstevel@tonic-gate 
49217c478bd9Sstevel@tonic-gate static int
isnumber(char * s)4922d1a180b0Smaheshvs isnumber(char *s)
49237c478bd9Sstevel@tonic-gate {
49247c478bd9Sstevel@tonic-gate 	register int	c;
49257c478bd9Sstevel@tonic-gate 
49267c478bd9Sstevel@tonic-gate 	if (s == NULL)
49277c478bd9Sstevel@tonic-gate 		return (0);
49287c478bd9Sstevel@tonic-gate 	while ((c = *s++) != NULL)
49297c478bd9Sstevel@tonic-gate 		if (c < '0' || c > '9')
49307c478bd9Sstevel@tonic-gate 			return (0);
49317c478bd9Sstevel@tonic-gate 	return (1);
49327c478bd9Sstevel@tonic-gate }
49337c478bd9Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
49347c478bd9Sstevel@tonic-gate 
49357c478bd9Sstevel@tonic-gate enum boolean { True, False };
49367c478bd9Sstevel@tonic-gate extent_block_t	*log_eb;
49377c478bd9Sstevel@tonic-gate ml_odunit_t	*log_odi;
49387c478bd9Sstevel@tonic-gate int		lufs_tid;	/* last valid TID seen */
49397c478bd9Sstevel@tonic-gate 
49407c478bd9Sstevel@tonic-gate /*
49417c478bd9Sstevel@tonic-gate  * no single value is safe to use to indicate
49427c478bd9Sstevel@tonic-gate  * lufs_tid being invalid so we need a
49437c478bd9Sstevel@tonic-gate  * seperate variable.
49447c478bd9Sstevel@tonic-gate  */
49457c478bd9Sstevel@tonic-gate enum boolean	lufs_tid_valid;
49467c478bd9Sstevel@tonic-gate 
49477c478bd9Sstevel@tonic-gate /*
49487c478bd9Sstevel@tonic-gate  * log_get_header_info - get the basic info of the logging filesystem
49497c478bd9Sstevel@tonic-gate  */
49507c478bd9Sstevel@tonic-gate int
log_get_header_info(void)49517c478bd9Sstevel@tonic-gate log_get_header_info(void)
49527c478bd9Sstevel@tonic-gate {
49537c478bd9Sstevel@tonic-gate 	char		*b;
49547c478bd9Sstevel@tonic-gate 	int		nb;
49557c478bd9Sstevel@tonic-gate 
49567c478bd9Sstevel@tonic-gate 	/*
49577c478bd9Sstevel@tonic-gate 	 * Mark the global tid as invalid everytime we're called to
49587c478bd9Sstevel@tonic-gate 	 * prevent any false positive responses.
49597c478bd9Sstevel@tonic-gate 	 */
49607c478bd9Sstevel@tonic-gate 	lufs_tid_valid = False;
49617c478bd9Sstevel@tonic-gate 
49627c478bd9Sstevel@tonic-gate 	/*
49637c478bd9Sstevel@tonic-gate 	 * See if we've already set up the header areas. The only problem
49647c478bd9Sstevel@tonic-gate 	 * with this approach is we don't reread the on disk data though
49657c478bd9Sstevel@tonic-gate 	 * it shouldn't matter since we don't operate on a live disk.
49667c478bd9Sstevel@tonic-gate 	 */
49677c478bd9Sstevel@tonic-gate 	if ((log_eb != NULL) && (log_odi != NULL))
49687c478bd9Sstevel@tonic-gate 		return (1);
49697c478bd9Sstevel@tonic-gate 
49707c478bd9Sstevel@tonic-gate 	/*
49717c478bd9Sstevel@tonic-gate 	 * Either logging is disabled or we've not running 2.7.
49727c478bd9Sstevel@tonic-gate 	 */
49737c478bd9Sstevel@tonic-gate 	if (fs->fs_logbno == 0) {
49747c478bd9Sstevel@tonic-gate 		printf("Logging doesn't appear to be enabled on this disk\n");
49757c478bd9Sstevel@tonic-gate 		return (0);
49767c478bd9Sstevel@tonic-gate 	}
49777c478bd9Sstevel@tonic-gate 
49787c478bd9Sstevel@tonic-gate 	/*
49797c478bd9Sstevel@tonic-gate 	 * To find the log we need to first pick up the block allocation
49807c478bd9Sstevel@tonic-gate 	 * data. The block number for that data is fs_logbno in the
49817c478bd9Sstevel@tonic-gate 	 * super block.
49827c478bd9Sstevel@tonic-gate 	 */
49837c478bd9Sstevel@tonic-gate 	if ((b = getblk((u_offset_t)ldbtob(logbtodb(fs, fs->fs_logbno))))
49847c478bd9Sstevel@tonic-gate 	    == 0) {
49857c478bd9Sstevel@tonic-gate 		printf("getblk() indicates an error with logging block\n");
49867c478bd9Sstevel@tonic-gate 		return (0);
49877c478bd9Sstevel@tonic-gate 	}
49887c478bd9Sstevel@tonic-gate 
49897c478bd9Sstevel@tonic-gate 	/*
49907c478bd9Sstevel@tonic-gate 	 * Next we need to figure out how big the extent data structure
49917c478bd9Sstevel@tonic-gate 	 * really is. It can't be more then fs_bsize and you could just
49927c478bd9Sstevel@tonic-gate 	 * allocate that but, why get sloppy.
49937c478bd9Sstevel@tonic-gate 	 * 1 is subtracted from nextents because extent_block_t contains
49947c478bd9Sstevel@tonic-gate 	 * a single extent_t itself.
49957c478bd9Sstevel@tonic-gate 	 */
49967c478bd9Sstevel@tonic-gate 	log_eb = (extent_block_t *)b;
49977c478bd9Sstevel@tonic-gate 	if (log_eb->type != LUFS_EXTENTS) {
49987c478bd9Sstevel@tonic-gate 		printf("Extents block has invalid type (0x%x)\n",
49997c478bd9Sstevel@tonic-gate 		    log_eb->type);
50007c478bd9Sstevel@tonic-gate 		return (0);
50017c478bd9Sstevel@tonic-gate 	}
50027c478bd9Sstevel@tonic-gate 	nb = sizeof (extent_block_t) +
50037c478bd9Sstevel@tonic-gate 	    (sizeof (extent_t) * (log_eb->nextents - 1));
50047c478bd9Sstevel@tonic-gate 
50057c478bd9Sstevel@tonic-gate 	log_eb = (extent_block_t *)malloc(nb);
50067c478bd9Sstevel@tonic-gate 	if (log_eb == NULL) {
50077c478bd9Sstevel@tonic-gate 		printf("Failed to allocate memory for extent block log\n");
50087c478bd9Sstevel@tonic-gate 		return (0);
50097c478bd9Sstevel@tonic-gate 	}
50107c478bd9Sstevel@tonic-gate 	memcpy(log_eb, b, nb);
50117c478bd9Sstevel@tonic-gate 
50127c478bd9Sstevel@tonic-gate 	if (log_eb->nextbno != 0)
50137c478bd9Sstevel@tonic-gate 		/*
50147c478bd9Sstevel@tonic-gate 		 * Currently, as of 11-Dec-1997 the field nextbno isn't
50157c478bd9Sstevel@tonic-gate 		 * implemented. If someone starts using this sucker we'd
50167c478bd9Sstevel@tonic-gate 		 * better warn somebody.
50177c478bd9Sstevel@tonic-gate 		 */
50187c478bd9Sstevel@tonic-gate 		printf("WARNING: extent block field nextbno is non-zero!\n");
50197c478bd9Sstevel@tonic-gate 
50207c478bd9Sstevel@tonic-gate 	/*
50217c478bd9Sstevel@tonic-gate 	 * Now read in the on disk log structure. This is always in the
50227c478bd9Sstevel@tonic-gate 	 * first block of the first extent.
50237c478bd9Sstevel@tonic-gate 	 */
50247c478bd9Sstevel@tonic-gate 	b = getblk((u_offset_t)ldbtob(logbtodb(fs, log_eb->extents[0].pbno)));
50257c478bd9Sstevel@tonic-gate 	log_odi = (ml_odunit_t *)malloc(sizeof (ml_odunit_t));
50267c478bd9Sstevel@tonic-gate 	if (log_odi == NULL) {
50277c478bd9Sstevel@tonic-gate 		free(log_eb);
50287c478bd9Sstevel@tonic-gate 		log_eb = NULL;
50297c478bd9Sstevel@tonic-gate 		printf("Failed to allocate memory for ondisk structure\n");
50307c478bd9Sstevel@tonic-gate 		return (0);
50317c478bd9Sstevel@tonic-gate 	}
50327c478bd9Sstevel@tonic-gate 	memcpy(log_odi, b, sizeof (ml_odunit_t));
50337c478bd9Sstevel@tonic-gate 
50347c478bd9Sstevel@tonic-gate 	/*
50357c478bd9Sstevel@tonic-gate 	 * Consistency checks.
50367c478bd9Sstevel@tonic-gate 	 */
50377c478bd9Sstevel@tonic-gate 	if (log_odi->od_version != LUFS_VERSION_LATEST) {
50387c478bd9Sstevel@tonic-gate 		free(log_eb);
50397c478bd9Sstevel@tonic-gate 		log_eb = NULL;
50407c478bd9Sstevel@tonic-gate 		free(log_odi);
50417c478bd9Sstevel@tonic-gate 		log_odi = NULL;
50427c478bd9Sstevel@tonic-gate 		printf("Version mismatch in on-disk version of log data\n");
50437c478bd9Sstevel@tonic-gate 		return (0);
50447c478bd9Sstevel@tonic-gate 	} else if (log_odi->od_badlog) {
50457c478bd9Sstevel@tonic-gate 		printf("WARNING: Log was marked as bad\n");
50467c478bd9Sstevel@tonic-gate 	}
50477c478bd9Sstevel@tonic-gate 
50487c478bd9Sstevel@tonic-gate 	return (1);
50497c478bd9Sstevel@tonic-gate }
50507c478bd9Sstevel@tonic-gate 
5051d1a180b0Smaheshvs static void
log_display_header(void)50527c478bd9Sstevel@tonic-gate log_display_header(void)
50537c478bd9Sstevel@tonic-gate {
50547c478bd9Sstevel@tonic-gate 	int x;
50557c478bd9Sstevel@tonic-gate 	if (!log_get_header_info())
50567c478bd9Sstevel@tonic-gate 		/*
50577c478bd9Sstevel@tonic-gate 		 * No need to display anything here. The previous routine
50587c478bd9Sstevel@tonic-gate 		 * has already done so.
50597c478bd9Sstevel@tonic-gate 		 */
50607c478bd9Sstevel@tonic-gate 		return;
50617c478bd9Sstevel@tonic-gate 
50627c478bd9Sstevel@tonic-gate 	if (fs->fs_magic == FS_MAGIC)
50637c478bd9Sstevel@tonic-gate 		printf("Log block number: 0x%x\n------------------\n",
50647c478bd9Sstevel@tonic-gate 		    fs->fs_logbno);
50657c478bd9Sstevel@tonic-gate 	else
50667c478bd9Sstevel@tonic-gate 		printf("Log frag number: 0x%x\n------------------\n",
50677c478bd9Sstevel@tonic-gate 		    fs->fs_logbno);
50687c478bd9Sstevel@tonic-gate 	printf("Extent Info\n\t# Extents  : %d\n\t# Bytes    : 0x%x\n",
50697c478bd9Sstevel@tonic-gate 	    log_eb->nextents, log_eb->nbytes);
50707c478bd9Sstevel@tonic-gate 	printf("\tNext Block : 0x%x\n\tExtent List\n\t--------\n",
50717c478bd9Sstevel@tonic-gate 	    log_eb->nextbno);
50727c478bd9Sstevel@tonic-gate 	for (x = 0; x < log_eb->nextents; x++)
50737c478bd9Sstevel@tonic-gate 		printf("\t  [%d] lbno 0x%08x pbno 0x%08x nbno 0x%08x\n",
50747c478bd9Sstevel@tonic-gate 		    x, log_eb->extents[x].lbno, log_eb->extents[x].pbno,
50757c478bd9Sstevel@tonic-gate 		    log_eb->extents[x].nbno);
50767c478bd9Sstevel@tonic-gate 	printf("\nOn Disk Info\n\tbol_lof    : 0x%08x\n\teol_lof    : 0x%08x\n",
50777c478bd9Sstevel@tonic-gate 	    log_odi->od_bol_lof, log_odi->od_eol_lof);
50787c478bd9Sstevel@tonic-gate 	printf("\tlog_size   : 0x%08x\n",
50797c478bd9Sstevel@tonic-gate 	    log_odi->od_logsize);
50807c478bd9Sstevel@tonic-gate 	printf("\thead_lof   : 0x%08x\tident : 0x%x\n",
50817c478bd9Sstevel@tonic-gate 	    log_odi->od_head_lof, log_odi->od_head_ident);
50827c478bd9Sstevel@tonic-gate 	printf("\ttail_lof   : 0x%08x\tident : 0x%x\n\thead_tid   : 0x%08x\n",
50837c478bd9Sstevel@tonic-gate 	    log_odi->od_tail_lof, log_odi->od_tail_ident, log_odi->od_head_tid);
50847c478bd9Sstevel@tonic-gate 	printf("\tcheck sum  : 0x%08x\n", log_odi->od_chksum);
50857c478bd9Sstevel@tonic-gate 	if (log_odi->od_chksum !=
50867c478bd9Sstevel@tonic-gate 	    (log_odi->od_head_ident + log_odi->od_tail_ident))
50877c478bd9Sstevel@tonic-gate 		printf("bad checksum: found 0x%08x, should be 0x%08x\n",
50887c478bd9Sstevel@tonic-gate 		    log_odi->od_chksum,
50897c478bd9Sstevel@tonic-gate 		    log_odi->od_head_ident + log_odi->od_tail_ident);
50907c478bd9Sstevel@tonic-gate 	if (log_odi->od_head_lof == log_odi->od_tail_lof)
50917c478bd9Sstevel@tonic-gate 		printf("\t --- Log is empty ---\n");
50927c478bd9Sstevel@tonic-gate }
50937c478bd9Sstevel@tonic-gate 
50947c478bd9Sstevel@tonic-gate /*
50957c478bd9Sstevel@tonic-gate  * log_lodb -- logical log offset to disk block number
50967c478bd9Sstevel@tonic-gate  */
5097d1a180b0Smaheshvs int
log_lodb(u_offset_t off,diskaddr_t * pblk)50987c478bd9Sstevel@tonic-gate log_lodb(u_offset_t off, diskaddr_t *pblk)
50997c478bd9Sstevel@tonic-gate {
51007c478bd9Sstevel@tonic-gate 	uint32_t	lblk = (uint32_t)btodb(off);
51017c478bd9Sstevel@tonic-gate 	int	x;
51027c478bd9Sstevel@tonic-gate 
5103594e4f22Sdmick 	if (!log_get_header_info())
5104594e4f22Sdmick 		/*
5105594e4f22Sdmick 		 * No need to display anything here. The previous routine
5106594e4f22Sdmick 		 * has already done so.
5107594e4f22Sdmick 		 */
510882d3d86bSdmick 		return (0);
5109594e4f22Sdmick 
51107c478bd9Sstevel@tonic-gate 	for (x = 0; x < log_eb->nextents; x++)
51117c478bd9Sstevel@tonic-gate 		if ((lblk >= log_eb->extents[x].lbno) &&
51127c478bd9Sstevel@tonic-gate 		    (lblk < (log_eb->extents[x].lbno +
51137c478bd9Sstevel@tonic-gate 			log_eb->extents[x].nbno))) {
51147c478bd9Sstevel@tonic-gate 			*pblk = (diskaddr_t)lblk - log_eb->extents[x].lbno +
51157c478bd9Sstevel@tonic-gate 				logbtodb(fs, log_eb->extents[x].pbno);
51167c478bd9Sstevel@tonic-gate 			return (1);
51177c478bd9Sstevel@tonic-gate 		}
51187c478bd9Sstevel@tonic-gate 	return (0);
51197c478bd9Sstevel@tonic-gate }
51207c478bd9Sstevel@tonic-gate 
51217c478bd9Sstevel@tonic-gate /*
51227c478bd9Sstevel@tonic-gate  * String names for the enumerated types. These are only used
51237c478bd9Sstevel@tonic-gate  * for display purposes.
51247c478bd9Sstevel@tonic-gate  */
51257c478bd9Sstevel@tonic-gate char *dt_str[] = {
51267c478bd9Sstevel@tonic-gate 	"DT_NONE", "DT_SB", "DT_CG", "DT_SI", "DT_AB",
51277c478bd9Sstevel@tonic-gate 	"DT_ABZERO", "DT_DIR", "DT_INODE", "DT_FBI",
51287c478bd9Sstevel@tonic-gate 	"DT_QR", "DT_COMMIT", "DT_CANCEL", "DT_BOT",
51297c478bd9Sstevel@tonic-gate 	"DT_EOT", "DT_UD", "DT_SUD", "DT_SHAD", "DT_MAX"
51307c478bd9Sstevel@tonic-gate };
51317c478bd9Sstevel@tonic-gate 
51327c478bd9Sstevel@tonic-gate /*
51337c478bd9Sstevel@tonic-gate  * log_read_log -- transfer information from the log and adjust offset
51347c478bd9Sstevel@tonic-gate  */
5135d1a180b0Smaheshvs int
log_read_log(u_offset_t * addr,caddr_t va,int nb,uint32_t * chk)51367c478bd9Sstevel@tonic-gate log_read_log(u_offset_t *addr, caddr_t va, int nb, uint32_t *chk)
51377c478bd9Sstevel@tonic-gate {
51387c478bd9Sstevel@tonic-gate 	int		xfer;
51397c478bd9Sstevel@tonic-gate 	caddr_t		bp;
51407c478bd9Sstevel@tonic-gate 	diskaddr_t	pblk;
51417c478bd9Sstevel@tonic-gate 	sect_trailer_t	*st;
51427c478bd9Sstevel@tonic-gate 
51437c478bd9Sstevel@tonic-gate 	while (nb) {
51447c478bd9Sstevel@tonic-gate 		if (!log_lodb(*addr, &pblk)) {
51457c478bd9Sstevel@tonic-gate 			printf("Invalid log offset\n");
51467c478bd9Sstevel@tonic-gate 			return (0);
51477c478bd9Sstevel@tonic-gate 		}
51487c478bd9Sstevel@tonic-gate 
51497c478bd9Sstevel@tonic-gate 		/*
51507c478bd9Sstevel@tonic-gate 		 * fsdb getblk() expects offsets not block number.
51517c478bd9Sstevel@tonic-gate 		 */
51527c478bd9Sstevel@tonic-gate 		if ((bp = getblk((u_offset_t)dbtob(pblk))) == NULL)
51537c478bd9Sstevel@tonic-gate 			return (0);
51547c478bd9Sstevel@tonic-gate 
51557c478bd9Sstevel@tonic-gate 		xfer = MIN(NB_LEFT_IN_SECTOR(*addr), nb);
51567c478bd9Sstevel@tonic-gate 		if (va != NULL) {
51577c478bd9Sstevel@tonic-gate 			memcpy(va, bp + blkoff(fs, *addr), xfer);
51587c478bd9Sstevel@tonic-gate 			va += xfer;
51597c478bd9Sstevel@tonic-gate 		}
51607c478bd9Sstevel@tonic-gate 		nb -= xfer;
51617c478bd9Sstevel@tonic-gate 		*addr += xfer;
51627c478bd9Sstevel@tonic-gate 
51637c478bd9Sstevel@tonic-gate 		/*
51647c478bd9Sstevel@tonic-gate 		 * If the log offset is now at a sector trailer
51657c478bd9Sstevel@tonic-gate 		 * run the checks if requested.
51667c478bd9Sstevel@tonic-gate 		 */
51677c478bd9Sstevel@tonic-gate 		if (NB_LEFT_IN_SECTOR(*addr) == 0) {
51687c478bd9Sstevel@tonic-gate 			if (chk != NULL) {
51697c478bd9Sstevel@tonic-gate 				st = (sect_trailer_t *)
51707c478bd9Sstevel@tonic-gate 				    (bp + blkoff(fs, *addr));
51717c478bd9Sstevel@tonic-gate 				if (*chk != st->st_ident) {
51727c478bd9Sstevel@tonic-gate 					printf(
51737c478bd9Sstevel@tonic-gate 			"Expected sector trailer id 0x%08x, but saw 0x%08x\n",
51747c478bd9Sstevel@tonic-gate 						*chk, st->st_ident);
51757c478bd9Sstevel@tonic-gate 					return (0);
51767c478bd9Sstevel@tonic-gate 				} else {
51777c478bd9Sstevel@tonic-gate 					*chk = st->st_ident + 1;
51787c478bd9Sstevel@tonic-gate 					/*
51797c478bd9Sstevel@tonic-gate 					 * We update the on disk structure
51807c478bd9Sstevel@tonic-gate 					 * transaction ID each time we see
51817c478bd9Sstevel@tonic-gate 					 * one. By comparing this value
51827c478bd9Sstevel@tonic-gate 					 * to the last valid DT_COMMIT record
51837c478bd9Sstevel@tonic-gate 					 * we can determine if our log is
51847c478bd9Sstevel@tonic-gate 					 * completely valid.
51857c478bd9Sstevel@tonic-gate 					 */
51867c478bd9Sstevel@tonic-gate 					log_odi->od_head_tid = st->st_tid;
51877c478bd9Sstevel@tonic-gate 				}
51887c478bd9Sstevel@tonic-gate 			}
51897c478bd9Sstevel@tonic-gate 			*addr += sizeof (sect_trailer_t);
51907c478bd9Sstevel@tonic-gate 		}
51917c478bd9Sstevel@tonic-gate 		if ((int32_t)*addr == log_odi->od_eol_lof)
51927c478bd9Sstevel@tonic-gate 			*addr = log_odi->od_bol_lof;
51937c478bd9Sstevel@tonic-gate 	}
51947c478bd9Sstevel@tonic-gate 	return (1);
51957c478bd9Sstevel@tonic-gate }
51967c478bd9Sstevel@tonic-gate 
51977c478bd9Sstevel@tonic-gate u_offset_t
log_nbcommit(u_offset_t a)51987c478bd9Sstevel@tonic-gate log_nbcommit(u_offset_t a)
51997c478bd9Sstevel@tonic-gate {
52007c478bd9Sstevel@tonic-gate 	/*
52017c478bd9Sstevel@tonic-gate 	 * Comments are straight from ufs_log.c
52027c478bd9Sstevel@tonic-gate 	 *
52037c478bd9Sstevel@tonic-gate 	 * log is the offset following the commit header. However,
52047c478bd9Sstevel@tonic-gate 	 * if the commit header fell on the end-of-sector, then lof
52057c478bd9Sstevel@tonic-gate 	 * has already been advanced to the beginning of the next
52067c478bd9Sstevel@tonic-gate 	 * sector. So do nothgin. Otherwise, return the remaining
52077c478bd9Sstevel@tonic-gate 	 * bytes in the sector.
52087c478bd9Sstevel@tonic-gate 	 */
52097c478bd9Sstevel@tonic-gate 	if ((a & (DEV_BSIZE - 1)) == 0)
52107c478bd9Sstevel@tonic-gate 		return (0);
52117c478bd9Sstevel@tonic-gate 	else
52127c478bd9Sstevel@tonic-gate 		return (NB_LEFT_IN_SECTOR(a));
52137c478bd9Sstevel@tonic-gate }
52147c478bd9Sstevel@tonic-gate 
52157c478bd9Sstevel@tonic-gate /*
52167c478bd9Sstevel@tonic-gate  * log_show --  pretty print the deltas. The number of which is determined
52177c478bd9Sstevel@tonic-gate  *		by the log_enum arg. If LOG_ALLDELTAS the routine, as the
52187c478bd9Sstevel@tonic-gate  *		name implies dumps everything. If LOG_NDELTAS, the routine
52197c478bd9Sstevel@tonic-gate  *		will print out "count" deltas starting at "addr". If
52207c478bd9Sstevel@tonic-gate  *		LOG_CHECKSCAN then run through the log checking the st_ident
52217c478bd9Sstevel@tonic-gate  *		for valid data.
52227c478bd9Sstevel@tonic-gate  */
5223d1a180b0Smaheshvs static void
log_show(enum log_enum l)52247c478bd9Sstevel@tonic-gate log_show(enum log_enum l)
52257c478bd9Sstevel@tonic-gate {
52267c478bd9Sstevel@tonic-gate 	struct delta	d;
52277c478bd9Sstevel@tonic-gate 	int32_t		bol, eol;
52287c478bd9Sstevel@tonic-gate 	int		x = 0;
52297c478bd9Sstevel@tonic-gate 	uint32_t	chk;
52307c478bd9Sstevel@tonic-gate 
52317c478bd9Sstevel@tonic-gate 	if (!log_get_header_info())
52327c478bd9Sstevel@tonic-gate 		/*
52337c478bd9Sstevel@tonic-gate 		 * No need to display any error messages here. The previous
52347c478bd9Sstevel@tonic-gate 		 * routine has already done so.
52357c478bd9Sstevel@tonic-gate 		 */
52367c478bd9Sstevel@tonic-gate 		return;
52377c478bd9Sstevel@tonic-gate 
52387c478bd9Sstevel@tonic-gate 	bol = log_odi->od_head_lof;
52397c478bd9Sstevel@tonic-gate 	eol = log_odi->od_tail_lof;
52407c478bd9Sstevel@tonic-gate 	chk = log_odi->od_head_ident;
52417c478bd9Sstevel@tonic-gate 
52427c478bd9Sstevel@tonic-gate 	if (bol == eol) {
52437c478bd9Sstevel@tonic-gate 		if ((l == LOG_ALLDELTAS) || (l == LOG_CHECKSCAN)) {
52447c478bd9Sstevel@tonic-gate 			printf("Empty log.\n");
52457c478bd9Sstevel@tonic-gate 			return;
52467c478bd9Sstevel@tonic-gate 		} else
52477c478bd9Sstevel@tonic-gate 			printf("WARNING: empty log. addr may generate bogus"
52487c478bd9Sstevel@tonic-gate 			    " information");
52497c478bd9Sstevel@tonic-gate 	}
52507c478bd9Sstevel@tonic-gate 
52517c478bd9Sstevel@tonic-gate 	/*
52527c478bd9Sstevel@tonic-gate 	 * Only reset the "addr" if we've been requested to show all
52537c478bd9Sstevel@tonic-gate 	 * deltas in the log.
52547c478bd9Sstevel@tonic-gate 	 */
52557c478bd9Sstevel@tonic-gate 	if ((l == LOG_ALLDELTAS) || (l == LOG_CHECKSCAN))
52567c478bd9Sstevel@tonic-gate 		addr = (u_offset_t)bol;
52577c478bd9Sstevel@tonic-gate 
52587c478bd9Sstevel@tonic-gate 	if (l != LOG_CHECKSCAN) {
52597c478bd9Sstevel@tonic-gate 		printf("       Log Offset       Delta       Count     Type\n");
52607c478bd9Sstevel@tonic-gate 		printf("-----------------------------------------"
52617c478bd9Sstevel@tonic-gate 			"-----------------\n");
52627c478bd9Sstevel@tonic-gate 	}
52637c478bd9Sstevel@tonic-gate 
52647c478bd9Sstevel@tonic-gate 	while ((bol != eol) && ((l == LOG_ALLDELTAS) ||
52657c478bd9Sstevel@tonic-gate 	    (l == LOG_CHECKSCAN) || count--)) {
52667c478bd9Sstevel@tonic-gate 		if (!log_read_log(&addr, (caddr_t)&d, sizeof (d),
52677c478bd9Sstevel@tonic-gate 		    ((l == LOG_ALLDELTAS) || (l == LOG_CHECKSCAN)) ?
52687c478bd9Sstevel@tonic-gate 		    &chk : NULL))
52697c478bd9Sstevel@tonic-gate 			/*
52707c478bd9Sstevel@tonic-gate 			 * Two failures are possible. One from getblk()
52717c478bd9Sstevel@tonic-gate 			 * which prints out a message or when we've hit
52727c478bd9Sstevel@tonic-gate 			 * an invalid block which may or may not indicate
52737c478bd9Sstevel@tonic-gate 			 * an error
52747c478bd9Sstevel@tonic-gate 			 */
52757c478bd9Sstevel@tonic-gate 			goto end_scan;
52767c478bd9Sstevel@tonic-gate 
52777c478bd9Sstevel@tonic-gate 		if ((uint32_t)d.d_nb > log_odi->od_logsize) {
52787c478bd9Sstevel@tonic-gate 			printf("Bad delta entry. size out of bounds\n");
52797c478bd9Sstevel@tonic-gate 			return;
52807c478bd9Sstevel@tonic-gate 		}
52817c478bd9Sstevel@tonic-gate 		if (l != LOG_CHECKSCAN)
52827c478bd9Sstevel@tonic-gate 			printf("[%04d]  %08x  %08x.%08x %08x  %s\n", x++, bol,
52837c478bd9Sstevel@tonic-gate 			    d.d_mof, d.d_nb,
52847c478bd9Sstevel@tonic-gate 			    dt_str[d.d_typ >= DT_MAX ? DT_MAX : d.d_typ]);
52857c478bd9Sstevel@tonic-gate 
52867c478bd9Sstevel@tonic-gate 		switch (d.d_typ) {
52877c478bd9Sstevel@tonic-gate 		case DT_CANCEL:
52887c478bd9Sstevel@tonic-gate 		case DT_ABZERO:
52897c478bd9Sstevel@tonic-gate 			/*
52907c478bd9Sstevel@tonic-gate 			 * These two deltas don't have log space
52917c478bd9Sstevel@tonic-gate 			 * associated with the entry even though
52927c478bd9Sstevel@tonic-gate 			 * d_nb is non-zero.
52937c478bd9Sstevel@tonic-gate 			 */
52947c478bd9Sstevel@tonic-gate 			break;
52957c478bd9Sstevel@tonic-gate 
52967c478bd9Sstevel@tonic-gate 		case DT_COMMIT:
52977c478bd9Sstevel@tonic-gate 			/*
52987c478bd9Sstevel@tonic-gate 			 * Commit records have zero size yet, the
52997c478bd9Sstevel@tonic-gate 			 * rest of the current disk block is avoided.
53007c478bd9Sstevel@tonic-gate 			 */
53017c478bd9Sstevel@tonic-gate 			addr += log_nbcommit(addr);
53027c478bd9Sstevel@tonic-gate 			lufs_tid = log_odi->od_head_tid;
53037c478bd9Sstevel@tonic-gate 			lufs_tid_valid = True;
53047c478bd9Sstevel@tonic-gate 			break;
53057c478bd9Sstevel@tonic-gate 
53067c478bd9Sstevel@tonic-gate 		default:
53077c478bd9Sstevel@tonic-gate 			if (!log_read_log(&addr, NULL, d.d_nb,
53087c478bd9Sstevel@tonic-gate 			    ((l == LOG_ALLDELTAS) ||
53097c478bd9Sstevel@tonic-gate 			    (l == LOG_CHECKSCAN)) ? &chk : NULL))
53107c478bd9Sstevel@tonic-gate 				goto end_scan;
53117c478bd9Sstevel@tonic-gate 			break;
53127c478bd9Sstevel@tonic-gate 		}
53137c478bd9Sstevel@tonic-gate 		bol = (int32_t)addr;
53147c478bd9Sstevel@tonic-gate 	}
53157c478bd9Sstevel@tonic-gate 
53167c478bd9Sstevel@tonic-gate end_scan:
53177c478bd9Sstevel@tonic-gate 	if (lufs_tid_valid == True) {
53187c478bd9Sstevel@tonic-gate 		if (lufs_tid == log_odi->od_head_tid)
53197c478bd9Sstevel@tonic-gate 			printf("scan -- okay\n");
53207c478bd9Sstevel@tonic-gate 		else
53217c478bd9Sstevel@tonic-gate 			printf("scan -- some transactions have been lost\n");
53227c478bd9Sstevel@tonic-gate 	} else {
53237c478bd9Sstevel@tonic-gate 		printf("scan -- failed to find a single valid transaction\n");
53247c478bd9Sstevel@tonic-gate 		printf("        (possibly due to an empty log)\n");
53257c478bd9Sstevel@tonic-gate 	}
53267c478bd9Sstevel@tonic-gate }
5327