17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5d1a180bmaheshvs * Common Development and Distribution License (the "License").
6d1a180bmaheshvs * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
226451fdbvsakar * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
277c478bdstevel@tonic-gate/*	  All Rights Reserved  	*/
287c478bdstevel@tonic-gate
297c478bdstevel@tonic-gate/*
307c478bdstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
317c478bdstevel@tonic-gate * The Regents of the University of California
327c478bdstevel@tonic-gate * All Rights Reserved
337c478bdstevel@tonic-gate *
347c478bdstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
357c478bdstevel@tonic-gate * software developed by the University of California, Berkeley, and its
367c478bdstevel@tonic-gate * contributors.
377c478bdstevel@tonic-gate */
387c478bdstevel@tonic-gate
397c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
407c478bdstevel@tonic-gate
417c478bdstevel@tonic-gate/*
427c478bdstevel@tonic-gate * ncheck -- obtain file names from reading filesystem
437c478bdstevel@tonic-gate */
447c478bdstevel@tonic-gate
457c478bdstevel@tonic-gate#define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))
467c478bdstevel@tonic-gate
477c478bdstevel@tonic-gate#include <sys/param.h>
487c478bdstevel@tonic-gate#include <sys/types.h>
497c478bdstevel@tonic-gate#include <sys/vnode.h>
507c478bdstevel@tonic-gate#include <sys/fs/ufs_inode.h>
517c478bdstevel@tonic-gate#include <sys/fs/ufs_fs.h>
527c478bdstevel@tonic-gate#include <sys/fs/ufs_fsdir.h>
537c478bdstevel@tonic-gate#include <stdio.h>
547c478bdstevel@tonic-gate#include <stdlib.h>
557c478bdstevel@tonic-gate#include <string.h>
567c478bdstevel@tonic-gate#include <errno.h>
577c478bdstevel@tonic-gate#include <fcntl.h>
587c478bdstevel@tonic-gate#include <unistd.h>
597c478bdstevel@tonic-gate#include "roll_log.h"
607c478bdstevel@tonic-gate
617c478bdstevel@tonic-gateunion {
627c478bdstevel@tonic-gate	struct	fs	sblk;
637c478bdstevel@tonic-gate	char xxx[SBSIZE];	/* because fs is variable length */
647c478bdstevel@tonic-gate} real_fs;
657c478bdstevel@tonic-gate#define	sblock real_fs.sblk
667c478bdstevel@tonic-gate
677c478bdstevel@tonic-gatestruct	dinode	*itab;
687c478bdstevel@tonic-gateunsigned itab_size;
697c478bdstevel@tonic-gate
707c478bdstevel@tonic-gate
717c478bdstevel@tonic-gatestruct 	dinode	*gip;
727c478bdstevel@tonic-gate
737c478bdstevel@tonic-gate/* inode list */
747c478bdstevel@tonic-gatestruct ilist {
757c478bdstevel@tonic-gate	ino_t	ino;
767c478bdstevel@tonic-gate	ushort_t	mode;
777c478bdstevel@tonic-gate	uid_t	uid;
787c478bdstevel@tonic-gate	gid_t	gid;
797c478bdstevel@tonic-gate} *ilist;
807c478bdstevel@tonic-gateint ilist_size = 0;	/* size of ilist[] */
817c478bdstevel@tonic-gateint ilist_index = 0;	/* current index for storing into ilist; */
827c478bdstevel@tonic-gate#define	ILIST_SZ_INCR	1000	/* initial size, amount to incr sz of ilist */
837c478bdstevel@tonic-gate#define	MAX_ILIST_INDEX()	(ilist_size - 1)
847c478bdstevel@tonic-gate
857c478bdstevel@tonic-gatestruct	htab
867c478bdstevel@tonic-gate{
877c478bdstevel@tonic-gate	ino_t	h_ino;
887c478bdstevel@tonic-gate	ino_t	h_pino;
897c478bdstevel@tonic-gate	int	h_name_index;		/* index into string table */
907c478bdstevel@tonic-gate} *htab;
917c478bdstevel@tonic-gateunsigned htab_size;		/* how much malloc'd for htab */
927c478bdstevel@tonic-gate
937c478bdstevel@tonic-gate/*
947c478bdstevel@tonic-gate * string table: used to hold filenames.
957c478bdstevel@tonic-gate */
967c478bdstevel@tonic-gatechar *strngtab;
977c478bdstevel@tonic-gateint strngloc;
987c478bdstevel@tonic-gateint strngtab_size;
997c478bdstevel@tonic-gate#define	STRNGTAB_INCR	(1024*16)	/* amount to grow strngtab */
1007c478bdstevel@tonic-gate#define	MAX_STRNGTAB_INDEX()	(strngtab_size - 1)
1017c478bdstevel@tonic-gate#define	AVG_PATH_LEN	30		/* average (?) length of name */
1027c478bdstevel@tonic-gate
1037c478bdstevel@tonic-gatelong hsize;
1047c478bdstevel@tonic-gate
1057c478bdstevel@tonic-gatestruct dirstuff {
1067c478bdstevel@tonic-gate	int loc;
1077c478bdstevel@tonic-gate	struct dinode *ip;
1087c478bdstevel@tonic-gate	char dbuf[MAXBSIZE];
1097c478bdstevel@tonic-gate};
1107c478bdstevel@tonic-gate
1117c478bdstevel@tonic-gate
1127c478bdstevel@tonic-gateint	aflg = 0;
1137c478bdstevel@tonic-gateint	sflg = 0;
1147c478bdstevel@tonic-gateint	iflg = 0; /* number of inodes being searched for */
1157c478bdstevel@tonic-gateint	mflg = 0;
1167c478bdstevel@tonic-gateint	fi;
1177c478bdstevel@tonic-gateino_t	ino;
1187c478bdstevel@tonic-gateint	nhent;
1197c478bdstevel@tonic-gate
1207c478bdstevel@tonic-gateint	nerror;
1217c478bdstevel@tonic-gate
1227c478bdstevel@tonic-gatelong	atol();
123d1a180bmaheshvsdaddr_t	bmap(daddr_t);
1247c478bdstevel@tonic-gatevoid	bread(diskaddr_t bno, char *buf, int cnt);
1257c478bdstevel@tonic-gatevoid	check(char *file);
1267c478bdstevel@tonic-gateint	dotname(struct direct *dp);
1277c478bdstevel@tonic-gateoffset_t llseek();
1287c478bdstevel@tonic-gatestruct htab *lookup(ino_t i, int ef);
1297c478bdstevel@tonic-gatevoid	pass1(struct dinode *ip);
1307c478bdstevel@tonic-gatevoid	pass2(struct dinode *ip);
1317c478bdstevel@tonic-gatevoid	pass3(struct dinode *ip);
1327c478bdstevel@tonic-gatevoid	pname(ino_t i, int lev);
1337c478bdstevel@tonic-gatechar 	*strcpy();
1347c478bdstevel@tonic-gatevoid	usage();
1357c478bdstevel@tonic-gatestruct direct *dreaddir();
1367c478bdstevel@tonic-gatevoid extend_ilist();
1377c478bdstevel@tonic-gateint extend_strngtab(unsigned int size);
1387c478bdstevel@tonic-gateuchar_t *extend_tbl(uchar_t *tbl, unsigned int *current_size,
1397c478bdstevel@tonic-gate	unsigned int new_size);
1407c478bdstevel@tonic-gate
1417c478bdstevel@tonic-gateextern int	optind;
1427c478bdstevel@tonic-gateextern char	*optarg;
1437c478bdstevel@tonic-gate
1447c478bdstevel@tonic-gatechar *subopts [] = {
1457c478bdstevel@tonic-gate#define	M_FLAG		0
1467c478bdstevel@tonic-gate	"m",
1477c478bdstevel@tonic-gate	NULL
1487c478bdstevel@tonic-gate	};
1497c478bdstevel@tonic-gate
150d1a180bmaheshvsint
151d1a180bmaheshvsmain(int argc, char *argv[])
1527c478bdstevel@tonic-gate{
1537c478bdstevel@tonic-gate	long n;
1547c478bdstevel@tonic-gate	int	opt;
1557c478bdstevel@tonic-gate	char	*suboptions,	*value;
1567c478bdstevel@tonic-gate	int	suboption;
1577c478bdstevel@tonic-gate	char	*p;
1587c478bdstevel@tonic-gate	int	first = 0;
1597c478bdstevel@tonic-gate
1607c478bdstevel@tonic-gate	extend_ilist();
1617c478bdstevel@tonic-gate	while ((opt = getopt(argc, argv, "ao:i:s")) != EOF) {
1627c478bdstevel@tonic-gate		switch (opt) {
1637c478bdstevel@tonic-gate
1647c478bdstevel@tonic-gate		case 'a':
1657c478bdstevel@tonic-gate			aflg++;
1667c478bdstevel@tonic-gate			break;
1677c478bdstevel@tonic-gate
1687c478bdstevel@tonic-gate		case 'o':
1697c478bdstevel@tonic-gate			/*
1707c478bdstevel@tonic-gate			 * ufs specific options.
1717c478bdstevel@tonic-gate			 */
1727c478bdstevel@tonic-gate			suboptions = optarg;
1737c478bdstevel@tonic-gate			while (*suboptions != '\0') {
1747c478bdstevel@tonic-gate				suboption = getsubopt(&suboptions,
1757c478bdstevel@tonic-gate					subopts, &value);
1767c478bdstevel@tonic-gate				switch (suboption) {
1777c478bdstevel@tonic-gate
1787c478bdstevel@tonic-gate				case M_FLAG:
1797c478bdstevel@tonic-gate					mflg++;
1807c478bdstevel@tonic-gate					break;
1817c478bdstevel@tonic-gate
1827c478bdstevel@tonic-gate				default:
1837c478bdstevel@tonic-gate					usage();
1847c478bdstevel@tonic-gate				}
1857c478bdstevel@tonic-gate			}
1867c478bdstevel@tonic-gate			break;
1877c478bdstevel@tonic-gate
1887c478bdstevel@tonic-gate		case 'i':
1897c478bdstevel@tonic-gate			while ((p = (char *)strtok((first++ == 0 ? optarg : 0),
1907c478bdstevel@tonic-gate						    ", ")) != NULL) {
1917c478bdstevel@tonic-gate				if ((n = atoi(p)) == 0)
1927c478bdstevel@tonic-gate					break;
1937c478bdstevel@tonic-gate				ilist[iflg].ino = n;
1947c478bdstevel@tonic-gate				iflg++;
1957c478bdstevel@tonic-gate				ilist_index = iflg;
1967c478bdstevel@tonic-gate				if (iflg > MAX_ILIST_INDEX())
1977c478bdstevel@tonic-gate					extend_ilist();
1987c478bdstevel@tonic-gate			}
1997c478bdstevel@tonic-gate			break;
2007c478bdstevel@tonic-gate
2017c478bdstevel@tonic-gate		case 's':
2027c478bdstevel@tonic-gate			sflg++;
2037c478bdstevel@tonic-gate			break;
2047c478bdstevel@tonic-gate#if 0
2057c478bdstevel@tonic-gate		case 'V':
2067c478bdstevel@tonic-gate			{
2077c478bdstevel@tonic-gate				int	opt_count;
2087c478bdstevel@tonic-gate				char	*opt_text;
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gate				(void) fprintf(stdout, "ncheck -F ufs ");
2117c478bdstevel@tonic-gate				for (opt_count = 1; opt_count < argc;
2127c478bdstevel@tonic-gate						opt_count++) {
2137c478bdstevel@tonic-gate					opt_text = argv[opt_count];
2147c478bdstevel@tonic-gate					if (opt_text)
2157c478bdstevel@tonic-gate						(void) fprintf(stdout, " %s ",
2167c478bdstevel@tonic-gate							opt_text);
2177c478bdstevel@tonic-gate				}
2187c478bdstevel@tonic-gate				(void) fprintf(stdout, "\n");
2197c478bdstevel@tonic-gate			}
2207c478bdstevel@tonic-gate			break;
2217c478bdstevel@tonic-gate#endif
2227c478bdstevel@tonic-gate		case '?':
2237c478bdstevel@tonic-gate			usage();
2247c478bdstevel@tonic-gate		}
2257c478bdstevel@tonic-gate	}
2267c478bdstevel@tonic-gate	argc -= optind;
2277c478bdstevel@tonic-gate	argv = &argv[optind];
2287c478bdstevel@tonic-gate	while (argc--) {
2297c478bdstevel@tonic-gate		check(*argv);
2307c478bdstevel@tonic-gate		argv++;
2317c478bdstevel@tonic-gate	}
2327c478bdstevel@tonic-gate	return (nerror);
2337c478bdstevel@tonic-gate}
2347c478bdstevel@tonic-gate
2357c478bdstevel@tonic-gatevoid
236d1a180bmaheshvscheck(char *file)
2377c478bdstevel@tonic-gate{
238d1a180bmaheshvs	int i, j, c;
2397c478bdstevel@tonic-gate
2407c478bdstevel@tonic-gate	fi = open64(file, 0);
2417c478bdstevel@tonic-gate	if (fi < 0) {
2427c478bdstevel@tonic-gate		(void) fprintf(stderr, "ncheck: cannot open %s\n", file);
2437c478bdstevel@tonic-gate		nerror++;
2447c478bdstevel@tonic-gate		return;
2457c478bdstevel@tonic-gate	}
2467c478bdstevel@tonic-gate	nhent = 0;
2477c478bdstevel@tonic-gate	(void) printf("%s:\n", file);
2487c478bdstevel@tonic-gate	sync();
2497c478bdstevel@tonic-gate	bread((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE);
2507c478bdstevel@tonic-gate	if ((sblock.fs_magic != FS_MAGIC) &&
2517c478bdstevel@tonic-gate	    (sblock.fs_magic != MTB_UFS_MAGIC)) {
2527c478bdstevel@tonic-gate		(void) printf("%s: not a ufs file system\n", file);
2537c478bdstevel@tonic-gate		nerror++;
2547c478bdstevel@tonic-gate		return;
2557c478bdstevel@tonic-gate	}
2567c478bdstevel@tonic-gate
2576451fdbvsakar	if ((sblock.fs_magic == FS_MAGIC) &&
2586451fdbvsakar	    ((sblock.fs_version != UFS_EFISTYLE4NONEFI_VERSION_2) &&
2596451fdbvsakar	    (sblock.fs_version != UFS_VERSION_MIN))) {
2606451fdbvsakar		(void) printf("%s: unrecognized ufs version number %d\n",
2616451fdbvsakar		    file, sblock.fs_version);
2626451fdbvsakar		nerror++;
2636451fdbvsakar		return;
2646451fdbvsakar	}
2656451fdbvsakar
2667c478bdstevel@tonic-gate	if ((sblock.fs_magic == MTB_UFS_MAGIC) &&
2677c478bdstevel@tonic-gate	    ((sblock.fs_version > MTB_UFS_VERSION_1) ||
2687c478bdstevel@tonic-gate	    (sblock.fs_version < MTB_UFS_VERSION_MIN))) {
2697c478bdstevel@tonic-gate		(void) printf("%s: unrecognized ufs version number %d\n",
2707c478bdstevel@tonic-gate		    file, sblock.fs_version);
2717c478bdstevel@tonic-gate		nerror++;
2727c478bdstevel@tonic-gate		return;
2737c478bdstevel@tonic-gate	}
2747c478bdstevel@tonic-gate
2757c478bdstevel@tonic-gate	/* If fs is logged, roll the log. */
2767c478bdstevel@tonic-gate	if (sblock.fs_logbno) {
2777c478bdstevel@tonic-gate		switch (rl_roll_log(file)) {
2787c478bdstevel@tonic-gate		case RL_SUCCESS:
2797c478bdstevel@tonic-gate			/*
2807c478bdstevel@tonic-gate			 * Reread the superblock.  Rolling the log may have
2817c478bdstevel@tonic-gate			 * changed it.
2827c478bdstevel@tonic-gate			 */
2837c478bdstevel@tonic-gate			bread((diskaddr_t)SBLOCK, (char *)&sblock, SBSIZE);
2847c478bdstevel@tonic-gate			break;
2857c478bdstevel@tonic-gate		case RL_SYSERR:
2867c478bdstevel@tonic-gate			(void) printf("Warning: cannot roll log for %s.  %s\n",
2877c478bdstevel@tonic-gate				file, strerror(errno));
2887c478bdstevel@tonic-gate			break;
2897c478bdstevel@tonic-gate		default:
2907c478bdstevel@tonic-gate			(void) printf("Warning: cannot roll log for %s.\n",
2917c478bdstevel@tonic-gate				file);
2927c478bdstevel@tonic-gate			break;
2937c478bdstevel@tonic-gate		}
2947c478bdstevel@tonic-gate	}
2957c478bdstevel@tonic-gate
2967c478bdstevel@tonic-gate	itab = (struct dinode *)extend_tbl((uchar_t *)itab, &itab_size,
2977c478bdstevel@tonic-gate		(unsigned)(sblock.fs_ipg * sizeof (struct dinode)));
2987c478bdstevel@tonic-gate	if (itab == 0) {
2997c478bdstevel@tonic-gate		(void) fprintf(stderr,
3007c478bdstevel@tonic-gate			"ncheck: not enough memory for itab table\n");
3017c478bdstevel@tonic-gate		nerror++;
3027c478bdstevel@tonic-gate		return;
3037c478bdstevel@tonic-gate	}
3047c478bdstevel@tonic-gate
3057c478bdstevel@tonic-gate	hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1;
3067c478bdstevel@tonic-gate
3077c478bdstevel@tonic-gate	htab = (struct htab *)extend_tbl((uchar_t *)htab, &htab_size,
3087c478bdstevel@tonic-gate		(unsigned)(hsize * sizeof (struct htab)));
3097c478bdstevel@tonic-gate	if (htab == 0) {
3107c478bdstevel@tonic-gate		(void) fprintf(stderr,
3117c478bdstevel@tonic-gate			"ncheck: not enough memory for htab table\n");
3127c478bdstevel@tonic-gate		nerror++;
3137c478bdstevel@tonic-gate		return;
3147c478bdstevel@tonic-gate	}
3157c478bdstevel@tonic-gate
3167c478bdstevel@tonic-gate	if (!extend_strngtab(AVG_PATH_LEN * hsize)) {
3177c478bdstevel@tonic-gate		(void) printf("not enough memory to allocate tables\n");
3187c478bdstevel@tonic-gate		nerror++;
3197c478bdstevel@tonic-gate		return;
3207c478bdstevel@tonic-gate	}
3217c478bdstevel@tonic-gate	strngloc = 0;
3227c478bdstevel@tonic-gate
3237c478bdstevel@tonic-gate	ino = 0;
3247c478bdstevel@tonic-gate	for (c = 0; c < sblock.fs_ncg; c++) {
3257c478bdstevel@tonic-gate		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
3267c478bdstevel@tonic-gate		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
3277c478bdstevel@tonic-gate		for (j = 0; j < sblock.fs_ipg; j++) {
3287c478bdstevel@tonic-gate			if (itab[j].di_smode != 0) {
3297c478bdstevel@tonic-gate				itab[j].di_mode = itab[j].di_smode;
3307c478bdstevel@tonic-gate				if (itab[j].di_suid != UID_LONG)
3317c478bdstevel@tonic-gate					itab[j].di_uid = itab[j].di_suid;
3327c478bdstevel@tonic-gate				if (itab[j].di_sgid != GID_LONG)
3337c478bdstevel@tonic-gate					itab[j].di_gid = itab[j].di_sgid;
3347c478bdstevel@tonic-gate				pass1(&itab[j]);
3357c478bdstevel@tonic-gate			}
3367c478bdstevel@tonic-gate			ino++;
3377c478bdstevel@tonic-gate		}
3387c478bdstevel@tonic-gate	}
3397c478bdstevel@tonic-gate	ilist[ilist_index++].ino = 0;
3407c478bdstevel@tonic-gate	if (ilist_index > MAX_ILIST_INDEX())
3417c478bdstevel@tonic-gate		extend_ilist();
3427c478bdstevel@tonic-gate	ino = 0;
3437c478bdstevel@tonic-gate	for (c = 0; c < sblock.fs_ncg; c++) {
3447c478bdstevel@tonic-gate		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
3457c478bdstevel@tonic-gate		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
3467c478bdstevel@tonic-gate		for (j = 0; j < sblock.fs_ipg; j++) {
3477c478bdstevel@tonic-gate
3487c478bdstevel@tonic-gate			if (itab[j].di_smode != 0) {
3497c478bdstevel@tonic-gate				itab[j].di_mode = itab[j].di_smode;
3507c478bdstevel@tonic-gate				pass2(&itab[j]);
3517c478bdstevel@tonic-gate			}
3527c478bdstevel@tonic-gate			ino++;
3537c478bdstevel@tonic-gate		}
3547c478bdstevel@tonic-gate	}
3557c478bdstevel@tonic-gate	ino = 0;
3567c478bdstevel@tonic-gate	for (c = 0; c < sblock.fs_ncg; c++) {
3577c478bdstevel@tonic-gate		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,
3587c478bdstevel@tonic-gate		    (int)(sblock.fs_ipg * sizeof (struct dinode)));
3597c478bdstevel@tonic-gate		for (j = 0; j < sblock.fs_ipg; j++) {
3607c478bdstevel@tonic-gate			if (itab[j].di_smode != 0) {
3617c478bdstevel@tonic-gate				itab[j].di_mode = itab[j].di_smode;
3627c478bdstevel@tonic-gate				pass3(&itab[j]);
3637c478bdstevel@tonic-gate			}
3647c478bdstevel@tonic-gate			ino++;
3657c478bdstevel@tonic-gate		}
3667c478bdstevel@tonic-gate	}
3677c478bdstevel@tonic-gate	(void) close(fi);
3687c478bdstevel@tonic-gate
3697c478bdstevel@tonic-gate	/*
3707c478bdstevel@tonic-gate	 * Clear those elements after inodes specified by "-i" out of
3717c478bdstevel@tonic-gate	 * ilist.
3727c478bdstevel@tonic-gate	 */
3737c478bdstevel@tonic-gate	for (i = iflg; i < ilist_index; i++) {
3747c478bdstevel@tonic-gate		ilist[i].ino = 0;
3757c478bdstevel@tonic-gate	}
3767c478bdstevel@tonic-gate	ilist_index = iflg;
3777c478bdstevel@tonic-gate}
3787c478bdstevel@tonic-gate
3797c478bdstevel@tonic-gatevoid
380d1a180bmaheshvspass1(struct dinode *ip)
3817c478bdstevel@tonic-gate{
3827c478bdstevel@tonic-gate	int i;
3837c478bdstevel@tonic-gate
3847c478bdstevel@tonic-gate	if (mflg) {
3857c478bdstevel@tonic-gate		for (i = 0; i < iflg; i++)
3867c478bdstevel@tonic-gate			if (ino == ilist[i].ino) {
3877c478bdstevel@tonic-gate				ilist[i].mode = ip->di_mode;
3887c478bdstevel@tonic-gate				ilist[i].uid = ip->di_uid;
3897c478bdstevel@tonic-gate				ilist[i].gid = ip->di_gid;
3907c478bdstevel@tonic-gate			}
3917c478bdstevel@tonic-gate	}
3927c478bdstevel@tonic-gate	if ((ip->di_mode & IFMT) != IFDIR) {
3937c478bdstevel@tonic-gate		if (sflg == 0)
3947c478bdstevel@tonic-gate			return;
3957c478bdstevel@tonic-gate		if ((ip->di_mode & IFMT) == IFBLK ||
3967c478bdstevel@tonic-gate				(ip->di_mode & IFMT) == IFCHR ||
3977c478bdstevel@tonic-gate				ip->di_mode&(ISUID|ISGID)) {
3987c478bdstevel@tonic-gate			ilist[ilist_index].ino = ino;
3997c478bdstevel@tonic-gate			ilist[ilist_index].mode = ip->di_mode;
4007c478bdstevel@tonic-gate			ilist[ilist_index].uid = ip->di_uid;
4017c478bdstevel@tonic-gate			ilist[ilist_index].gid = ip->di_gid;
4027c478bdstevel@tonic-gate			if (++ilist_index > MAX_ILIST_INDEX())
4037c478bdstevel@tonic-gate				extend_ilist();
4047c478bdstevel@tonic-gate			return;
4057c478bdstevel@tonic-gate		}
4067c478bdstevel@tonic-gate	}
4077c478bdstevel@tonic-gate	(void) lookup(ino, 1);
4087c478bdstevel@tonic-gate}
4097c478bdstevel@tonic-gate
4107c478bdstevel@tonic-gatevoid
411d1a180bmaheshvspass2(struct dinode *ip)
4127c478bdstevel@tonic-gate{
413d1a180bmaheshvs	struct direct *dp;
4147c478bdstevel@tonic-gate	struct dirstuff dirp;
4157c478bdstevel@tonic-gate	struct htab *hp;
4167c478bdstevel@tonic-gate
4177c478bdstevel@tonic-gate
4187c478bdstevel@tonic-gate	if ((ip->di_mode&IFMT) != IFDIR)
4197c478bdstevel@tonic-gate		return;
4207c478bdstevel@tonic-gate	dirp.loc = 0;
4217c478bdstevel@tonic-gate	dirp.ip = ip;
4227c478bdstevel@tonic-gate	gip = ip;
4237c478bdstevel@tonic-gate	for (dp = dreaddir(&dirp); dp != NULL; dp = dreaddir(&dirp)) {
4247c478bdstevel@tonic-gate		int nmlen;
4257c478bdstevel@tonic-gate
4267c478bdstevel@tonic-gate		if (dp->d_ino == 0)
4277c478bdstevel@tonic-gate			continue;
4287c478bdstevel@tonic-gate
4297c478bdstevel@tonic-gate		hp = lookup(dp->d_ino, 0);
4307c478bdstevel@tonic-gate		if (hp == 0)
4317c478bdstevel@tonic-gate			continue;
4327c478bdstevel@tonic-gate
4337c478bdstevel@tonic-gate		if (dotname(dp))
4347c478bdstevel@tonic-gate			continue;
4357c478bdstevel@tonic-gate		hp->h_pino = ino;
4367c478bdstevel@tonic-gate		nmlen = strlen(dp->d_name);
4377c478bdstevel@tonic-gate
4387c478bdstevel@tonic-gate		if (strngloc + nmlen + 1 > MAX_STRNGTAB_INDEX()) {
4397c478bdstevel@tonic-gate			if (!extend_strngtab(STRNGTAB_INCR)) {
4407c478bdstevel@tonic-gate				perror("ncheck: can't grow string table\n");
4417c478bdstevel@tonic-gate				exit(32);
4427c478bdstevel@tonic-gate			}
4437c478bdstevel@tonic-gate		}
4447c478bdstevel@tonic-gate
4457c478bdstevel@tonic-gate		hp->h_name_index = strngloc;
4467c478bdstevel@tonic-gate		(void) strcpy(&strngtab[strngloc], dp->d_name);
4477c478bdstevel@tonic-gate		strngloc += nmlen + 1;
4487c478bdstevel@tonic-gate	}
4497c478bdstevel@tonic-gate}
4507c478bdstevel@tonic-gate
4517c478bdstevel@tonic-gatevoid
452d1a180bmaheshvspass3(struct dinode *ip)
4537c478bdstevel@tonic-gate{
454d1a180bmaheshvs	struct direct *dp;
4557c478bdstevel@tonic-gate	struct dirstuff dirp;
4567c478bdstevel@tonic-gate	int k;
4577c478bdstevel@tonic-gate
4587c478bdstevel@tonic-gate	if ((ip->di_mode&IFMT) != IFDIR)
4597c478bdstevel@tonic-gate		return;
4607c478bdstevel@tonic-gate	dirp.loc = 0;
4617c478bdstevel@tonic-gate	dirp.ip = ip;
4627c478bdstevel@tonic-gate	gip = ip;
4637c478bdstevel@tonic-gate	for (dp = dreaddir(&dirp); dp != NULL; dp = dreaddir(&dirp)) {
4647c478bdstevel@tonic-gate		if (aflg == 0 && dotname(dp))
4657c478bdstevel@tonic-gate			continue;
4667c478bdstevel@tonic-gate
4677c478bdstevel@tonic-gate		if (sflg == 0 && iflg == 0)
4687c478bdstevel@tonic-gate			goto pr;
4697c478bdstevel@tonic-gate		for (k = 0; k < ilist_index && ilist[k].ino != 0; k++) {
4707c478bdstevel@tonic-gate			if (ilist[k].ino == dp->d_ino) {
4717c478bdstevel@tonic-gate				break;
4727c478bdstevel@tonic-gate			}
4737c478bdstevel@tonic-gate		}
4747c478bdstevel@tonic-gate		if (ilist[k].ino == 0)
4757c478bdstevel@tonic-gate			continue;
4767c478bdstevel@tonic-gate		if (mflg)
4777c478bdstevel@tonic-gate			(void) printf("mode %-6o uid %-5ld gid %-5ld ino ",
4787c478bdstevel@tonic-gate			    ilist[k].mode, ilist[k].uid, ilist[k].gid);
4797c478bdstevel@tonic-gate	pr:
4807c478bdstevel@tonic-gate		(void) printf("%-5u\t", dp->d_ino);
4817c478bdstevel@tonic-gate		pname(ino, 0);
4827c478bdstevel@tonic-gate		(void) printf("/%s", dp->d_name);
4837c478bdstevel@tonic-gate		if (lookup(dp->d_ino, 0))
4847c478bdstevel@tonic-gate			(void) printf("/.");
4857c478bdstevel@tonic-gate		(void) printf("\n");
4867c478bdstevel@tonic-gate	}
4877c478bdstevel@tonic-gate}
4887c478bdstevel@tonic-gate
4897c478bdstevel@tonic-gate/*
4907c478bdstevel@tonic-gate * get next entry in a directory.
4917c478bdstevel@tonic-gate */
4927c478bdstevel@tonic-gatestruct direct *
493d1a180bmaheshvsdreaddir(struct dirstuff *dirp)
4947c478bdstevel@tonic-gate{
495d1a180bmaheshvs	struct direct *dp;
4967c478bdstevel@tonic-gate	daddr_t lbn, d;
4977c478bdstevel@tonic-gate
4987c478bdstevel@tonic-gate	for (;;) {
4997c478bdstevel@tonic-gate
5007c478bdstevel@tonic-gate		if (dirp->loc >= (int)dirp->ip->di_size)
5017c478bdstevel@tonic-gate			return (NULL);
5027c478bdstevel@tonic-gate		if (blkoff(&sblock, dirp->loc) == 0) {
5037c478bdstevel@tonic-gate
5047c478bdstevel@tonic-gate			lbn = lblkno(&sblock, dirp->loc);
5057c478bdstevel@tonic-gate
5067c478bdstevel@tonic-gate			d = bmap(lbn);
5077c478bdstevel@tonic-gate			if (d == 0)
5087c478bdstevel@tonic-gate				return (NULL);
5097c478bdstevel@tonic-gate
5107c478bdstevel@tonic-gate			bread(fsbtodb(&sblock, d), dirp->dbuf,
5117c478bdstevel@tonic-gate			    (int)dblksize(&sblock, dirp->ip, (int)lbn));
5127c478bdstevel@tonic-gate
5137c478bdstevel@tonic-gate		}
5147c478bdstevel@tonic-gate		dp = (struct direct *)
5157c478bdstevel@tonic-gate		    (dirp->dbuf + blkoff(&sblock, dirp->loc));
5167c478bdstevel@tonic-gate		dirp->loc += dp->d_reclen;
5177c478bdstevel@tonic-gate		if (dp->d_ino == 0) {
5187c478bdstevel@tonic-gate			continue;
5197c478bdstevel@tonic-gate		}
5207c478bdstevel@tonic-gate		return (dp);
5217c478bdstevel@tonic-gate	}
5227c478bdstevel@tonic-gate}
5237c478bdstevel@tonic-gate
524d1a180bmaheshvsint
525d1a180bmaheshvsdotname(struct direct *dp)
5267c478bdstevel@tonic-gate{
5277c478bdstevel@tonic-gate
5287c478bdstevel@tonic-gate	if (dp->d_name[0] == '.') {
5297c478bdstevel@tonic-gate		if (dp->d_name[1] == 0 ||
5307c478bdstevel@tonic-gate		    (dp->d_name[1] == '.' && dp->d_name[2] == 0))
5317c478bdstevel@tonic-gate			return (1);
5327c478bdstevel@tonic-gate	}
5337c478bdstevel@tonic-gate	return (0);
5347c478bdstevel@tonic-gate}
5357c478bdstevel@tonic-gate
5367c478bdstevel@tonic-gatevoid
537d1a180bmaheshvspname(ino_t i, int lev)
5387c478bdstevel@tonic-gate{
539d1a180bmaheshvs	struct htab *hp;
5407c478bdstevel@tonic-gate
5417c478bdstevel@tonic-gate	if (i == UFSROOTINO)
5427c478bdstevel@tonic-gate		return;
5437c478bdstevel@tonic-gate
5447c478bdstevel@tonic-gate	if ((hp = lookup(i, 0)) == 0) {
5457c478bdstevel@tonic-gate		(void) printf("???");
5467c478bdstevel@tonic-gate		return;
5477c478bdstevel@tonic-gate	}
5487c478bdstevel@tonic-gate	if (lev > 10) {
5497c478bdstevel@tonic-gate		(void) printf("...");
5507c478bdstevel@tonic-gate		return;
5517c478bdstevel@tonic-gate	}
5527c478bdstevel@tonic-gate	pname(hp->h_pino, ++lev);
5537c478bdstevel@tonic-gate	(void) printf("/%s", &(strngtab[hp->h_name_index]));
5547c478bdstevel@tonic-gate
5557c478bdstevel@tonic-gate}
5567c478bdstevel@tonic-gate
5577c478bdstevel@tonic-gatestruct htab *
558d1a180bmaheshvslookup(ino_t i, int ef)
5597c478bdstevel@tonic-gate{
560d1a180bmaheshvs	struct htab *hp;
5617c478bdstevel@tonic-gate
5627c478bdstevel@tonic-gate	for (hp = &htab[(int)i%hsize]; hp->h_ino; ) {
5637c478bdstevel@tonic-gate		if (hp->h_ino == i)
5647c478bdstevel@tonic-gate			return (hp);
5657c478bdstevel@tonic-gate		if (++hp >= &htab[hsize])
5667c478bdstevel@tonic-gate			hp = htab;
5677c478bdstevel@tonic-gate	}
5687c478bdstevel@tonic-gate
5697c478bdstevel@tonic-gate	if (ef == 0)
5707c478bdstevel@tonic-gate		return (0);
5717c478bdstevel@tonic-gate	if (++nhent >= hsize) {
5727c478bdstevel@tonic-gate		(void) fprintf(stderr, "ncheck: hsize of %ld is too small\n",
5737c478bdstevel@tonic-gate									hsize);
5747c478bdstevel@tonic-gate		exit(32);
5757c478bdstevel@tonic-gate	}
5767c478bdstevel@tonic-gate	hp->h_ino = i;
5777c478bdstevel@tonic-gate	return (hp);
5787c478bdstevel@tonic-gate}
5797c478bdstevel@tonic-gate
5807c478bdstevel@tonic-gatevoid
581d1a180bmaheshvsbread(diskaddr_t bno, char *buf, int cnt)
5827c478bdstevel@tonic-gate{
583d1a180bmaheshvs	int i;
5847c478bdstevel@tonic-gate	int got;
5857c478bdstevel@tonic-gate
5867c478bdstevel@tonic-gate	if (llseek(fi, (offset_t)bno * DEV_BSIZE, 0) == -1) {
5877c478bdstevel@tonic-gate		(void) fprintf(stderr, "ncheck: lseek error %lld\n",
5887c478bdstevel@tonic-gate		    (offset_t)bno * DEV_BSIZE);
5897c478bdstevel@tonic-gate
5907c478bdstevel@tonic-gate		for (i = 0; i < cnt; i++) {
5917c478bdstevel@tonic-gate			buf[i] = 0;
5927c478bdstevel@tonic-gate		}
5937c478bdstevel@tonic-gate
5947c478bdstevel@tonic-gate		return;
5957c478bdstevel@tonic-gate	}
5967c478bdstevel@tonic-gate
5977c478bdstevel@tonic-gate	got = read((int)fi, buf, cnt);
5987c478bdstevel@tonic-gate
5997c478bdstevel@tonic-gate	if (got != cnt) {
6007c478bdstevel@tonic-gate		(void) fprintf(stderr,
6017c478bdstevel@tonic-gate		    "ncheck: read error at block %lld (wanted %d got %d)\n",
6027c478bdstevel@tonic-gate		    bno, cnt, got);
6037c478bdstevel@tonic-gate
6047c478bdstevel@tonic-gate		for (i = 0; i < cnt; i++)
6057c478bdstevel@tonic-gate			buf[i] = 0;
6067c478bdstevel@tonic-gate	}
6077c478bdstevel@tonic-gate}
6087c478bdstevel@tonic-gate
6097c478bdstevel@tonic-gatedaddr_t
610d1a180bmaheshvsbmap(daddr_t i)
6117c478bdstevel@tonic-gate{
6127c478bdstevel@tonic-gate	daddr_t ibuf[MAXNINDIR];
6137c478bdstevel@tonic-gate
6147c478bdstevel@tonic-gate	if (i < NDADDR)
6157c478bdstevel@tonic-gate		return (gip->di_db[i]);
6167c478bdstevel@tonic-gate	i -= NDADDR;
6177c478bdstevel@tonic-gate	if (i > NINDIR(&sblock)) {
6187c478bdstevel@tonic-gate		(void) fprintf(stderr, "ncheck: %lu - huge directory\n", ino);
6197c478bdstevel@tonic-gate		return ((daddr_t)0);
6207c478bdstevel@tonic-gate	}
6217c478bdstevel@tonic-gate
6227c478bdstevel@tonic-gate	bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof (ibuf));
6237c478bdstevel@tonic-gate
6247c478bdstevel@tonic-gate	return (ibuf[i]);
6257c478bdstevel@tonic-gate}
6267c478bdstevel@tonic-gate
6277c478bdstevel@tonic-gatevoid
6287c478bdstevel@tonic-gateusage()
6297c478bdstevel@tonic-gate{
6307c478bdstevel@tonic-gate	(void) fprintf(stderr,
6317c478bdstevel@tonic-gate		/*CSTYLED*/
6327c478bdstevel@tonic-gate		"ufs usage: ncheck [-F ufs] [generic options] [-a -i #list -s] [-o m] special\n");
6337c478bdstevel@tonic-gate	exit(32);
6347c478bdstevel@tonic-gate}
6357c478bdstevel@tonic-gate
6367c478bdstevel@tonic-gate
6377c478bdstevel@tonic-gate/*
6387c478bdstevel@tonic-gate * Extend or create the inode list;
6397c478bdstevel@tonic-gate * this is used to contains the list of inodes we've been
6407c478bdstevel@tonic-gate * asked to check using the "-i" flag and to hold the
6417c478bdstevel@tonic-gate * inode numbers of files which we detect as being
6427c478bdstevel@tonic-gate * blk|char|setuid|setgid ("-s" flag support).
6437c478bdstevel@tonic-gate * Preserves contents.
6447c478bdstevel@tonic-gate */
6457c478bdstevel@tonic-gatevoid
6467c478bdstevel@tonic-gateextend_ilist()
6477c478bdstevel@tonic-gate{
6487c478bdstevel@tonic-gate	ilist_size += ILIST_SZ_INCR;
6497c478bdstevel@tonic-gate	ilist = (struct ilist *)realloc(ilist,
6507c478bdstevel@tonic-gate		(ilist_size * sizeof (struct ilist)));
6517c478bdstevel@tonic-gate
6527c478bdstevel@tonic-gate	if (ilist == NULL) {
6537c478bdstevel@tonic-gate		perror("ncheck: not enough memory to grow ilist\n");
6547c478bdstevel@tonic-gate		exit(32);
6557c478bdstevel@tonic-gate	}
6567c478bdstevel@tonic-gate}
6577c478bdstevel@tonic-gate
6587c478bdstevel@tonic-gate/*
6597c478bdstevel@tonic-gate * Extend or create the string table.
6607c478bdstevel@tonic-gate * Preserves contents.
6617c478bdstevel@tonic-gate * Return non-zero for success.
6627c478bdstevel@tonic-gate */
6637c478bdstevel@tonic-gateint
664d1a180bmaheshvsextend_strngtab(unsigned int size)
6657c478bdstevel@tonic-gate{
6667c478bdstevel@tonic-gate	strngtab_size += size;
6677c478bdstevel@tonic-gate	strngtab = (char *)realloc(strngtab, strngtab_size);
6687c478bdstevel@tonic-gate
6697c478bdstevel@tonic-gate	return ((int)strngtab);
6707c478bdstevel@tonic-gate}
6717c478bdstevel@tonic-gate
6727c478bdstevel@tonic-gate/*
6737c478bdstevel@tonic-gate * Extend or create a table, throwing away previous
6747c478bdstevel@tonic-gate * contents.
6757c478bdstevel@tonic-gate * Return null on failure.
6767c478bdstevel@tonic-gate */
6777c478bdstevel@tonic-gateuchar_t *
678d1a180bmaheshvsextend_tbl(uchar_t *tbl, unsigned int *current_size, unsigned int new_size)
6797c478bdstevel@tonic-gate{
6807c478bdstevel@tonic-gate	/*
6817c478bdstevel@tonic-gate	 * if we've already allocated tbl,
6827c478bdstevel@tonic-gate	 * but it is too small, free it.
6837c478bdstevel@tonic-gate	 * we don't realloc because we are throwing
6847c478bdstevel@tonic-gate	 * away its contents.
6857c478bdstevel@tonic-gate	 */
6867c478bdstevel@tonic-gate
6877c478bdstevel@tonic-gate	if (tbl && (*current_size < new_size)) {
6887c478bdstevel@tonic-gate		free(tbl);
6897c478bdstevel@tonic-gate		tbl = NULL;
6907c478bdstevel@tonic-gate	}
6917c478bdstevel@tonic-gate
6927c478bdstevel@tonic-gate	if (tbl == NULL) {
6937c478bdstevel@tonic-gate		tbl = (uchar_t *)malloc(new_size);
6947c478bdstevel@tonic-gate		if (tbl == 0)
6957c478bdstevel@tonic-gate			return ((uchar_t *)0);
6967c478bdstevel@tonic-gate
6977c478bdstevel@tonic-gate		*current_size = new_size;
6987c478bdstevel@tonic-gate	}
6997c478bdstevel@tonic-gate	(void) memset(tbl, 0, new_size);
7007c478bdstevel@tonic-gate
7017c478bdstevel@tonic-gate	return (tbl);
7027c478bdstevel@tonic-gate}
703