ncheck.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 528 行

C
528
字号
#ifndef lintstatic	char	*sccsid = "@(#)ncheck.c	4.2	(ULTRIX)	10/15/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1986,87 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * ncheck -- obtain file names from reading filesystem *//*									* *		Modification History					* *									* * 5) - 15 Oct 90 -- dws						* *	Sych'd up with 4.4 BSD and added code to dynamically allocate	* *	internal tables.						* *									* * 4) - 19 Sep 89 -- lebel                                              * *      Added a check for NULL pointer in -i processing.                * *									* * 3) - 15 Jan 87 -- prs						* *	Increased HSIZE and added code to default to all mounted	* *	ULTRIX file systems if none are passed.				* *									* * 2) - 16 Dec 86 -- prs						* *	Changed error message.						* *									* * 1) - 15 Mar 85 -- funding						* *	Added named pipe support (re. System V named pipes)		* */#define	NB		5000#define	MAXNINDIR	(MAXBSIZE / sizeof (daddr_t))#define NPIPES							/* 1 */#include <sys/param.h>#include <sys/inode.h>#include <sys/fs.h>#include <sys/dir.h>#include <sys/mount.h>#include <sys/fs_types.h>#include <stdio.h>struct	fs	sblock;struct	dinode	itab[MAXIPG];struct 	dinode	*gip;struct ilist {	ino_t	ino;	u_short	mode;	short	uid;	short	gid;} *ilist;long isize = NB;	/* ilist table size */struct	htab{	ino_t	h_ino;	ino_t	h_pino;	char	*h_name;} *htab;long hsize;		/* hash table size */char *strngtab;int strngloc;struct dirstuff {	int loc;	struct dinode *ip;	char dbuf[MAXBSIZE];};int	aflg;int	sflg;int	iflg; /* number of inodes being searched for */int	mflg;int	fi;ino_t	ino;int	nhent;int	nxfile;long	dev_bsize =  DEV_BSIZE;int	nerror;daddr_t	bmap();long	atol();struct htab *lookup();main(argc, argv)	int argc;	char *argv[];{	register i;	long n;	int loc, ret;	struct fs_data *mountbuffer;	struct fs_data *fd;#define MSIZE (NMOUNT * sizeof(struct fs_data))	ilist = (struct ilist *)malloc(isize * sizeof(struct ilist));	if (ilist == NULL) {		printf("not enough memory to allocate ilist table\n");		exit(1);	}		while (--argc) {		argv++;		if (**argv=='-')		switch ((*argv)[1]) {		case 'a':			aflg++;			continue;		case 'i':			for(iflg=0; iflg<isize; iflg++) {				if (argv[1] == NULL)					break;				n = atol(argv[1]);				if(n == 0)					break;				ilist[iflg].ino = n;				nxfile = iflg;				argv++;				argc--;			}			continue;		case 'm':			mflg++;			continue;		case 's':			sflg++;			continue;		default:			fprintf(stderr, "ncheck: bad flag %c\n", (*argv)[1]);			nerror++;		}		else break;	}	if (argc) {		/* arg list has file names */		while(argc-- > 0)			check(*argv++);	}	else {		/* 3 - read in mounted file systems for default */		/*		 * 3 - malloc enough space for mountbuffer to hold all		 * the fs_data structures for all mounted file		 * systems.		 */		if((mountbuffer = (struct fs_data *) malloc(MSIZE)) == NULL) {			perror("malloc");			exit(1);		}		/*		 * 3 - Get all mounted file systems		 */	/* use this so that we don't hang if server's down with nfs file sys */		ret = getmountent(&loc, mountbuffer, NMOUNT);		if (ret == 0) {			fprintf(stderr, "ncheck: unable to read default file sytems\n");			return(1);		}		/*		 * 3 - For all the mounted file systems, call check only is		 * it is a local file system		 */		for (fd = mountbuffer; fd < &mountbuffer[ret]; fd++)			if (fd->fd_fstype == GT_ULTRIX)				check((char *)fd->fd_devname);	}	return(nerror);}check(file)	char *file;{	register int i, j, c;	int nfiles;	fi = open(file, 0);	if(fi < 0) {		fprintf(stderr, "ncheck: cannot open %s\n", file);		nerror++;		return;	}	nhent = 0;	printf("%s:\n", file);	sync();	bread(SBLOCK, (char *)&sblock, SBSIZE);	if (sblock.fs_magic != FS_MAGIC) {		printf("%s: not a file system\n", file);		nerror++;		return;	}	dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);	hsize = sblock.fs_ipg * sblock.fs_ncg - sblock.fs_cstotal.cs_nifree + 1;	htab = (struct htab *)malloc(hsize * sizeof(struct htab));	strngtab = (char *)malloc(30 * hsize);	if (htab == 0 || strngtab == 0) {		printf("not enough memory to allocate tables\n");		nerror++;		return;	}	ino = 0;	for (c = 0; c < sblock.fs_ncg; c++) {		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,		    sblock.fs_ipg * sizeof (struct dinode));		for(j = 0; j < sblock.fs_ipg; j++) {			if (itab[j].di_mode != 0)				pass1(&itab[j]);			ino++;		}	}	ilist[nxfile+1].ino = 0;	ino = 0;	for (c = 0; c < sblock.fs_ncg; c++) {		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,		    sblock.fs_ipg * sizeof (struct dinode));		for(j = 0; j < sblock.fs_ipg; j++) {			if (itab[j].di_mode != 0)				pass2(&itab[j]);			ino++;		}	}	ino = 0;	for (c = 0; c < sblock.fs_ncg; c++) {		bread(fsbtodb(&sblock, cgimin(&sblock, c)), (char *)itab,		    sblock.fs_ipg * sizeof (struct dinode));		for(j = 0; j < sblock.fs_ipg; j++) {			if (itab[j].di_mode != 0)				pass3(&itab[j]);			ino++;		}	}	close(fi);	for (i = 0; i < hsize; i++)		htab[i].h_ino = 0;	for (i = iflg; i < isize; i++)		ilist[i].ino = 0;	nxfile = iflg;}pass1(ip)	register struct dinode *ip;{	int i;	if (mflg)		for (i = 0; i < iflg; i++)			if (ino == ilist[i].ino) {				ilist[i].mode = ip->di_mode;				ilist[i].uid = ip->di_uid;				ilist[i].gid = ip->di_gid;			}	if ((ip->di_mode & IFMT) != IFDIR) {		if (sflg==0)			return;		if ((ip->di_mode&IFMT)==IFBLK || (ip->di_mode&IFMT)==IFCHR ||								/* 1 */		(ip->di_mode&IFMT)==IFPORT || ip->di_mode&(ISUID|ISGID)) {			if (nxfile>=isize) {				printf("ilist table overflow, %u not added\n", ino);                        } else {				ilist[nxfile].ino = ino;				ilist[nxfile].mode = ip->di_mode;				ilist[nxfile].uid = ip->di_uid;				ilist[nxfile++].gid = ip->di_gid;			}		}		return;	}	lookup(ino, 1);}pass2(ip)	register struct dinode *ip;{	register struct direct *dp;	struct dirstuff dirp;	struct htab *hp;	if((ip->di_mode&IFMT) != IFDIR)		return;	dirp.loc = 0;	dirp.ip = ip;	gip = ip;	for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {		if(dp->d_ino == 0)			continue;		hp = lookup(dp->d_ino, 0);		if(hp == 0)			continue;		if(dotname(dp))			continue;		hp->h_pino = ino;		hp->h_name = &strngtab[strngloc];		strngloc += strlen(dp->d_name) + 1;		strcpy(hp->h_name, dp->d_name);	}}pass3(ip)	register struct dinode *ip;{	register struct direct *dp;	struct dirstuff dirp;	int k;	if((ip->di_mode&IFMT) != IFDIR)		return;	dirp.loc = 0;	dirp.ip = ip;	gip = ip;	for(dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {		if(aflg==0 && dotname(dp))			continue;		if(sflg == 0 && iflg == 0)			goto pr;		for(k = 0; ilist[k].ino != 0; k++)			if(ilist[k].ino == dp->d_ino)				break;		if (ilist[k].ino == 0)			continue;		if (mflg)			printf("mode %-6o uid %-5d gid %-5d ino ",			    ilist[k].mode, ilist[k].uid, ilist[k].gid);	pr:		printf("%-5u\t", dp->d_ino);		pname(ino, 0);		printf("/%s", dp->d_name);		if (lookup(dp->d_ino, 0))			printf("/.");		printf("\n");	}}/* * get next entry in a directory. */struct direct *readdir(dirp)	register struct dirstuff *dirp;{	register struct direct *dp;	daddr_t lbn, d;	for(;;) {		if (dirp->loc >= dirp->ip->di_size)			return NULL;		if (blkoff(&sblock, dirp->loc) == 0) {			lbn = lblkno(&sblock, dirp->loc);			d = bmap(lbn);			if(d == 0)				return NULL;			bread(fsbtodb(&sblock, d), dirp->dbuf,			    dblksize(&sblock, dirp->ip, lbn));		}		dp = (struct direct *)		    (dirp->dbuf + blkoff(&sblock, dirp->loc));		dirp->loc += dp->d_reclen;		if (dp->d_ino == 0)			continue;		return (dp);	}}dotname(dp)	register struct direct *dp;{	if (dp->d_name[0]=='.')		if (dp->d_name[1]==0 ||		   (dp->d_name[1]=='.' && dp->d_name[2]==0))			return(1);	return(0);}pname(i, lev)	ino_t i;	int lev;{	register struct htab *hp;	if (i==ROOTINO)		return;	if ((hp = lookup(i, 0)) == 0) {		printf("???");		return;	}	if (lev > 10) {		printf("...");		return;	}	pname(hp->h_pino, ++lev);	printf("/%s", hp->h_name);}struct htab *lookup(i, ef)	ino_t i;	int ef;{	register struct htab *hp;	for (hp = &htab[i%hsize]; hp->h_ino;) {		if (hp->h_ino==i)			return(hp);		if (++hp >= &htab[hsize])			hp = htab;	}	if (ef==0)		return(0);	if (++nhent >= hsize) {                fprintf(stderr, "ncheck: hsize of %d is too small\n", hsize);		exit(1);	}	hp->h_ino = i;	return(hp);}bread(bno, buf, cnt)	daddr_t bno;	char *buf;	int cnt;{	register i;	lseek(fi, bno * dev_bsize, 0);	if (read(fi, buf, cnt) != cnt) {		fprintf(stderr, "ncheck: read error %d\n", bno);		for(i=0; i < cnt; i++)			buf[i] = 0;	}}/* * Swiped from standalone sys.c. */#define	NBUFS	4char	b[NBUFS][MAXBSIZE];daddr_t	blknos[NBUFS];daddr_tbmap(bn)	register daddr_t bn;{	register int j;	int i, sh;	daddr_t nb, *bap;	if (bn < 0) {		fprintf(stderr, "ncheck: bn %d negative\n", bn);		return ((daddr_t)0);	}	/*	 * blocks 0..NDADDR are direct blocks	 */	if(bn < NDADDR)		return(gip->di_db[bn]);	/*	 * addresses NIADDR have single and double indirect blocks.	 * the first step is to determine how many levels of indirection.	 */	sh = 1;	bn -= NDADDR;	for (j = NIADDR; j > 0; j--) {		sh *= NINDIR(&sblock);		if (bn < sh)			break;		bn -= sh;	}	if (j == 0) {		printf("ncheck: bn %ld ovf, ino %u\n", bn, ino);		return ((daddr_t)0);	}	/*	 * fetch the first indirect block address from the inode	 */	nb = gip->di_ib[NIADDR - j];	if (nb == 0) {		printf("ncheck: bn %ld void1, ino %u\n", bn, ino);		return ((daddr_t)0);	}	/*	 * fetch through the indirect blocks	 */	for (; j <= NIADDR; j++) {		if (blknos[j] != nb) {			bread(fsbtodb(&sblock, nb), b[j], sblock.fs_bsize);			blknos[j] = nb;		}		bap = (daddr_t *)b[j];		sh /= NINDIR(&sblock);		i = (bn / sh) % NINDIR(&sblock);		nb = bap[i];		if(nb == 0) {			printf("ncheck: bn %ld void2, ino %u\n", bn, ino);			return ((daddr_t)0);		}	}	return (nb);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?