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