quot.c revision 144841
117721Speter/*
217721Speter * Copyright (C) 1991, 1994 Wolfgang Solfrank.
317721Speter * Copyright (C) 1991, 1994 TooLs GmbH.
417721Speter * All rights reserved.
517721Speter *
617721Speter * Redistribution and use in source and binary forms, with or without
717721Speter * modification, are permitted provided that the following conditions
817721Speter * are met:
917721Speter * 1. Redistributions of source code must retain the above copyright
1017721Speter *    notice, this list of conditions and the following disclaimer.
1117721Speter * 2. Redistributions in binary form must reproduce the above copyright
1217721Speter *    notice, this list of conditions and the following disclaimer in the
1317721Speter *    documentation and/or other materials provided with the distribution.
1417721Speter * 3. All advertising materials mentioning features or use of this software
1525839Speter *    must display the following acknowledgement:
1617721Speter *	This product includes software developed by TooLs GmbH.
1725839Speter * 4. The name of TooLs GmbH may not be used to endorse or promote products
1825839Speter *    derived from this software without specific prior written permission.
1925839Speter *
2025839Speter * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2125839Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2225839Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2325839Speter * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2425839Speter * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2525839Speter * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2617721Speter * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2717721Speter * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2817721Speter * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2917721Speter * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3017721Speter */
3117721Speter
3217721Speter#include <sys/cdefs.h>
3325839Speter__FBSDID("$FreeBSD: head/usr.sbin/quot/quot.c 144841 2005-04-09 14:59:10Z stefanf $");
3425839Speter
3525839Speter#include <sys/param.h>
3625839Speter#include <sys/stdint.h>
3717721Speter#include <sys/mount.h>
3817721Speter#include <sys/disklabel.h>
3917721Speter#include <sys/time.h>
4017721Speter#include <ufs/ufs/dinode.h>
4117721Speter#include <ufs/ffs/fs.h>
4217721Speter
4317721Speter#include <err.h>
4417721Speter#include <fcntl.h>
4517721Speter#include <fstab.h>
4625839Speter#include <errno.h>
4717721Speter#include <paths.h>
4825839Speter#include <pwd.h>
4917721Speter#include <stdio.h>
5017721Speter#include <stdlib.h>
5117721Speter#include <string.h>
5217721Speter#include <unistd.h>
5325839Speter
5425839Speter/* some flags of what to do: */
5517721Speterstatic char estimate;
5617721Speterstatic char count;
5717721Speterstatic char unused;
5817721Speterstatic void (*func)(int, struct fs *, char *);
5917721Speterstatic long blocksize;
6017721Speterstatic char *header;
6117721Speterstatic int headerlen;
6217721Speter
6317721Speterstatic union dinode *get_inode(int, struct fs *, ino_t);
6425839Speterstatic int	virtualblocks(struct fs *, union dinode *);
6517721Speterstatic int	isfree(struct fs *, union dinode *);
6617721Speterstatic void	inituser(void);
6725839Speterstatic void	usrrehash(void);
6825839Speterstatic struct user *user(uid_t);
6917721Speterstatic int	cmpusers(const void *, const void *);
7017721Speterstatic void	uses(uid_t, daddr_t, time_t);
7117721Speterstatic void	initfsizes(void);
7217721Speterstatic void	dofsizes(int, struct fs *, char *);
7317721Speterstatic void	douser(int, struct fs *, char *);
7417721Speterstatic void	donames(int, struct fs *, char *);
7517721Speterstatic void	usage(void);
7617721Speterstatic void	quot(char *, char *);
7725839Speter
7817721Speter/*
7925839Speter * Original BSD quot doesn't round to number of frags/blocks,
8025839Speter * doesn't account for indirection blocks and gets it totally
8117721Speter * wrong if the	size is a multiple of the blocksize.
8217721Speter * The new code always counts the number of 512 byte blocks
8317721Speter * instead of the number of kilobytes and converts them	to
8425839Speter * kByte when done (on request).
8525839Speter *
8617721Speter * Due to the size of modern disks, we must cast intermediate
8717721Speter * values to 64 bits to prevent potential overflows.
8817721Speter */
8917721Speter#ifdef	COMPAT
9017721Speter#define	SIZE(n)	(n)
9117721Speter#else
9217721Speter#define	SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize))
9325839Speter#endif
9417721Speter
9517721Speter#define	INOCNT(fs)	((fs)->fs_ipg)
9625839Speter#define	INOSZ(fs) \
9717721Speter	(((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \
9825839Speter	sizeof(struct ufs2_dinode)) * INOCNT(fs))
9925839Speter
10025839Speterunion dinode {
10117721Speter	struct ufs1_dinode dp1;
10217721Speter	struct ufs2_dinode dp2;
10317721Speter};
10417721Speter#define	DIP(fs, dp, field) \
10517721Speter	(((fs)->fs_magic == FS_UFS1_MAGIC) ? \
10625839Speter	(dp)->dp1.field : (dp)->dp2.field)
10725839Speter
10817721Speterstatic union dinode *
10917721Speterget_inode(fd,super,ino)
11017721Speter	int fd;
11117721Speter	struct fs *super;
11217721Speter	ino_t ino;
11317721Speter{
11417721Speter	static caddr_t ipbuf;
11517721Speter	static ino_t last;
11617721Speter
11717721Speter	if (fd < 0) {		/* flush cache */
11817721Speter		if (ipbuf) {
11917721Speter			free(ipbuf);
12025839Speter			ipbuf = 0;
12125839Speter		}
12217721Speter		return 0;
12317721Speter	}
12417721Speter
12525839Speter	if (!ipbuf || ino < last || ino >= last + INOCNT(super)) {
12617721Speter		if (!ipbuf
12725839Speter		    && !(ipbuf = malloc(INOSZ(super))))
12825839Speter			errx(1, "allocate inodes");
12925839Speter		last = (ino / INOCNT(super)) * INOCNT(super);
13025839Speter		if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
13125839Speter		    || read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super))
13217721Speter			err(1, "read inodes");
13317721Speter	}
13417721Speter
13517721Speter	if (super->fs_magic == FS_UFS1_MAGIC)
13617721Speter		return ((union dinode *)
13717721Speter		    &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]);
13817721Speter	return ((union dinode *)
13917721Speter	    &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]);
14017721Speter}
14117721Speter
14217721Speter#ifdef	COMPAT
14317721Speter#define	actualblocks(fs, dp)	(DIP(fs, dp, di_blocks) / 2)
14417721Speter#else
14517721Speter#define	actualblocks(fs, dp)	DIP(fs, dp, di_blocks)
14617721Speter#endif
14717721Speter
14825839Speterstatic int virtualblocks(super, dp)
14917721Speter	struct fs *super;
15025839Speter	union dinode *dp;
15117721Speter{
15217721Speter	register off_t nblk, sz;
15317721Speter
15417721Speter	sz = DIP(super, dp, di_size);
15517721Speter#ifdef	COMPAT
15617721Speter	if (lblkno(super,sz) >= NDADDR) {
15717721Speter		nblk = blkroundup(super,sz);
15817721Speter		if (sz == nblk)
15917721Speter			nblk += super->fs_bsize;
16017721Speter	}
16117721Speter
16217721Speter	return sz / 1024;
16317721Speter
16417721Speter#else	/* COMPAT */
16517721Speter
16617721Speter	if (lblkno(super,sz) >= NDADDR) {
16717721Speter		nblk = blkroundup(super,sz);
16817721Speter		sz = lblkno(super,nblk);
16917721Speter		sz = (sz - NDADDR + NINDIR(super) - 1) / NINDIR(super);
17017721Speter		while (sz > 0) {
17117721Speter			nblk += sz * super->fs_bsize;
17217721Speter			/* sz - 1 rounded up */
17325839Speter			sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super);
17417721Speter		}
17517721Speter	} else
17617721Speter		nblk = fragroundup(super,sz);
17717721Speter
17817721Speter	return nblk / 512;
17917721Speter#endif	/* COMPAT */
18017721Speter}
18117721Speter
18217721Speterstatic int
18325839Speterisfree(super, dp)
18425839Speter	struct fs *super;
18517721Speter	union dinode *dp;
18625839Speter{
18717721Speter#ifdef	COMPAT
18825839Speter	return (DIP(super, dp, di_mode) & IFMT) == 0;
18925839Speter#else	/* COMPAT */
19017721Speter
19117721Speter	switch (DIP(super, dp, di_mode) & IFMT) {
19217721Speter	case IFIFO:
19317721Speter	case IFLNK:		/* should check FASTSYMLINK? */
19417721Speter	case IFDIR:
19525839Speter	case IFREG:
19617721Speter		return 0;
19717721Speter	default:
19825839Speter		return 1;
19925839Speter	}
20025839Speter#endif
20125839Speter}
20226801Speter
20326801Speterstatic struct user {
20426801Speter	uid_t uid;
20526801Speter	char *name;
20626801Speter	daddr_t space;
20726801Speter	long count;
20826801Speter	daddr_t spc30;
20926801Speter	daddr_t spc60;
21026801Speter	daddr_t spc90;
21126801Speter} *users;
21226801Speterstatic int nusers;
21326801Speter
21426801Speterstatic void
21526801Speterinituser()
21626801Speter{
21726801Speter	register int i;
21826801Speter	register struct user *usr;
21926801Speter
22026801Speter	if (!nusers) {
22126801Speter		nusers = 8;
22226801Speter		if (!(users =
22326801Speter		    (struct user *)calloc(nusers,sizeof(struct user))))
22426801Speter			errx(1, "allocate users");
22526801Speter	} else {
22626801Speter		for (usr = users, i = nusers; --i >= 0; usr++) {
22726801Speter			usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0;
22826801Speter			usr->count = 0;
22926801Speter		}
23026801Speter	}
23126801Speter}
23226801Speter
23326801Speterstatic void
23426801Speterusrrehash()
23526801Speter{
23626801Speter	register int i;
23726801Speter	register struct user *usr, *usrn;
23826801Speter	struct user *svusr;
23926801Speter
24026801Speter	svusr = users;
24126801Speter	nusers <<= 1;
24226801Speter	if (!(users = (struct user *)calloc(nusers,sizeof(struct user))))
24326801Speter		errx(1, "allocate users");
24426801Speter	for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) {
24526801Speter		for (usrn = users + (usr->uid&(nusers - 1)); usrn->name;
24626801Speter		    usrn--) {
24726801Speter			if (usrn <= users)
24826801Speter				usrn = users + nusers;
24926801Speter		}
25026801Speter		*usrn = *usr;
25126801Speter	}
25226801Speter}
25326801Speter
25426801Speterstatic struct user *
25526801Speteruser(uid)
25626801Speter	uid_t uid;
25726801Speter{
25826801Speter	register struct user *usr;
25926801Speter	register int i;
26026801Speter	struct passwd *pwd;
26126801Speter
26226801Speter	while (1) {
26326801Speter		for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0;
26426801Speter		    usr--) {
26526801Speter			if (!usr->name) {
26626801Speter				usr->uid = uid;
26726801Speter
26826801Speter				if (!(pwd = getpwuid(uid))) {
26926801Speter					if ((usr->name = (char *)malloc(7)))
27026801Speter						sprintf(usr->name,"#%d",uid);
27126801Speter				} else {
27226801Speter					if ((usr->name = (char *)
27326801Speter					    malloc(strlen(pwd->pw_name) + 1)))
27426801Speter						strcpy(usr->name,pwd->pw_name);
27526801Speter				}
27626801Speter				if (!usr->name)
27726801Speter					errx(1, "allocate users");
27826801Speter
27926801Speter				return usr;
28026801Speter
28126801Speter			} else if (usr->uid == uid)
28225839Speter				return usr;
28325839Speter
28425839Speter			if (usr <= users)
28525839Speter				usr = users + nusers;
28625839Speter		}
28725839Speter		usrrehash();
28825839Speter	}
28925839Speter}
29025839Speter
29125839Speterstatic int
29225839Spetercmpusers(v1,v2)
29325839Speter	const void *v1, *v2;
29425839Speter{
29525839Speter	const struct user *u1, *u2;
29625839Speter	u1 = (const struct user *)v1;
29725839Speter	u2 = (const struct user *)v2;
29825839Speter
29925839Speter	return u2->space - u1->space;
30025839Speter}
30125839Speter
30225839Speter#define	sortusers(users)	(qsort((users),nusers,sizeof(struct user), \
30325839Speter				    cmpusers))
30425839Speter
30525839Speterstatic void
30625839Speteruses(uid,blks,act)
30725839Speter	uid_t uid;
30825839Speter	daddr_t blks;
30925839Speter	time_t act;
31025839Speter{
31125839Speter	static time_t today;
31225839Speter	register struct user *usr;
31325839Speter
31425839Speter	if (!today)
31525839Speter		time(&today);
31625839Speter
31725839Speter	usr = user(uid);
31825839Speter	usr->count++;
31925839Speter	usr->space += blks;
32025839Speter
32125839Speter	if (today - act > 90L * 24L * 60L * 60L)
32225839Speter		usr->spc90 += blks;
32325839Speter	if (today - act > 60L * 24L * 60L * 60L)
32425839Speter		usr->spc60 += blks;
32525839Speter	if (today - act > 30L * 24L * 60L * 60L)
32625839Speter		usr->spc30 += blks;
32725839Speter}
32825839Speter
32925839Speter#ifdef	COMPAT
33025839Speter#define	FSZCNT	500
33125839Speter#else
33225839Speter#define	FSZCNT	512
33325839Speter#endif
33425839Speterstruct fsizes {
33525839Speter	struct fsizes *fsz_next;
33625839Speter	daddr_t fsz_first, fsz_last;
33725839Speter	ino_t fsz_count[FSZCNT];
33825839Speter	daddr_t fsz_sz[FSZCNT];
33925839Speter} *fsizes;
34025839Speter
34125839Speterstatic void
34225839Speterinitfsizes()
34325839Speter{
34425839Speter	register struct fsizes *fp;
34525839Speter	register int i;
34625839Speter
34725839Speter	for (fp = fsizes; fp; fp = fp->fsz_next) {
34825839Speter		for (i = FSZCNT; --i >= 0;) {
34925839Speter			fp->fsz_count[i] = 0;
35025839Speter			fp->fsz_sz[i] = 0;
35125839Speter		}
35225839Speter	}
35325839Speter}
35425839Speter
35525839Speterstatic void
35625839Speterdofsizes(fd, super, name)
35725839Speter	int fd;
35825839Speter	struct fs *super;
35925839Speter	char *name;
36025839Speter{
36125839Speter	ino_t inode, maxino;
36225839Speter	union dinode *dp;
36325839Speter	daddr_t sz, ksz;
36425839Speter	struct fsizes *fp, **fsp;
36525839Speter	register int i;
36625839Speter
36725839Speter	maxino = super->fs_ncg * super->fs_ipg - 1;
36825839Speter#ifdef	COMPAT
36925839Speter	if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes))))
37025839Speter		errx(1, "allocate fsize structure");
37125839Speter#endif	/* COMPAT */
37225839Speter	for (inode = 0; inode < maxino; inode++) {
37325839Speter		errno = 0;
37425839Speter		if ((dp = get_inode(fd,super,inode))
37525839Speter#ifdef	COMPAT
37625839Speter		    && ((DIP(super, dp, di_mode) & IFMT) == IFREG
37725839Speter			|| (DIP(super, dp, di_mode) & IFMT) == IFDIR)
37825839Speter#else	/* COMPAT */
37925839Speter		    && !isfree(super, dp)
38025839Speter#endif	/* COMPAT */
38125839Speter		    ) {
38225839Speter			sz = estimate ? virtualblocks(super, dp) :
38325839Speter			    actualblocks(super, dp);
38425839Speter#ifdef	COMPAT
38525839Speter			if (sz >= FSZCNT) {
38625839Speter				fsizes->fsz_count[FSZCNT-1]++;
38725839Speter				fsizes->fsz_sz[FSZCNT-1] += sz;
38825839Speter			} else {
38925839Speter				fsizes->fsz_count[sz]++;
39025839Speter				fsizes->fsz_sz[sz] += sz;
39125839Speter			}
39225839Speter#else	/* COMPAT */
39325839Speter			ksz = SIZE(sz);
39425839Speter			for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) {
39525839Speter				if (ksz < fp->fsz_last)
39625839Speter					break;
39725839Speter			}
39825839Speter			if (!fp || ksz < fp->fsz_first) {
39925839Speter				if (!(fp = (struct fsizes *)
40025839Speter				    malloc(sizeof(struct fsizes))))
40125839Speter					errx(1, "allocate fsize structure");
40225839Speter				fp->fsz_next = *fsp;
40325839Speter				*fsp = fp;
40425839Speter				fp->fsz_first = (ksz / FSZCNT) * FSZCNT;
40525839Speter				fp->fsz_last = fp->fsz_first + FSZCNT;
40625839Speter				for (i = FSZCNT; --i >= 0;) {
40725839Speter					fp->fsz_count[i] = 0;
40825839Speter					fp->fsz_sz[i] = 0;
40925839Speter				}
41025839Speter			}
41125839Speter			fp->fsz_count[ksz % FSZCNT]++;
41225839Speter			fp->fsz_sz[ksz % FSZCNT] += sz;
41325839Speter#endif	/* COMPAT */
41425839Speter		} else if (errno) {
41525839Speter			err(1, "%s", name);
41625839Speter		}
41725839Speter	}
41825839Speter	sz = 0;
41925839Speter	for (fp = fsizes; fp; fp = fp->fsz_next) {
42025839Speter		for (i = 0; i < FSZCNT; i++) {
42125839Speter			if (fp->fsz_count[i])
42225839Speter				printf("%jd\t%jd\t%d\n",
42325839Speter				    (intmax_t)(fp->fsz_first + i),
42425839Speter				    (intmax_t)fp->fsz_count[i],
42525839Speter				    SIZE(sz += fp->fsz_sz[i]));
42625839Speter		}
42725839Speter	}
42825839Speter}
42925839Speter
43025839Speterstatic void
43125839Speterdouser(fd, super, name)
43225839Speter	int fd;
43325839Speter	struct fs *super;
43425839Speter	char *name;
43525839Speter{
43625839Speter	ino_t inode, maxino;
43725839Speter	struct user *usr, *usrs;
43825839Speter	union dinode *dp;
43925839Speter	register int n;
44025839Speter
44125839Speter	maxino = super->fs_ncg * super->fs_ipg - 1;
44225839Speter	for (inode = 0; inode < maxino; inode++) {
44325839Speter		errno = 0;
44425839Speter		if ((dp = get_inode(fd,super,inode))
44525839Speter		    && !isfree(super, dp))
44625839Speter			uses(DIP(super, dp, di_uid),
44725839Speter			    estimate ? virtualblocks(super, dp) :
44825839Speter				actualblocks(super, dp),
44925839Speter			    DIP(super, dp, di_atime));
45025839Speter		else if (errno) {
45125839Speter			err(1, "%s", name);
45225839Speter		}
45325839Speter	}
45425839Speter	if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user))))
45525839Speter		errx(1, "allocate users");
45625839Speter	bcopy(users,usrs,nusers * sizeof(struct user));
45725839Speter	sortusers(usrs);
45825839Speter	for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) {
45925839Speter		printf("%5d",SIZE(usr->space));
46025839Speter		if (count)
46125839Speter			printf("\t%5ld",usr->count);
46225839Speter		printf("\t%-8s",usr->name);
46325839Speter		if (unused)
46425839Speter			printf("\t%5d\t%5d\t%5d",
46525839Speter			       SIZE(usr->spc30),
46625839Speter			       SIZE(usr->spc60),
46725839Speter			       SIZE(usr->spc90));
46825839Speter		printf("\n");
46925839Speter	}
47025839Speter	free(usrs);
47125839Speter}
47225839Speter
47325839Speterstatic void
47425839Speterdonames(fd, super, name)
47525839Speter	int fd;
47625839Speter	struct fs *super;
47725839Speter	char *name;
47825839Speter{
47925839Speter	int c;
48025839Speter	ino_t inode;
48125839Speter	ino_t maxino;
48225839Speter	union dinode *dp;
48325839Speter
48425839Speter	maxino = super->fs_ncg * super->fs_ipg - 1;
48525839Speter	/* first skip the name of the filesystem */
48625839Speter	while ((c = getchar()) != EOF && (c < '0' || c > '9'))
48725839Speter		while ((c = getchar()) != EOF && c != '\n');
48825839Speter	ungetc(c,stdin);
48925839Speter	while (scanf("%u",&inode) == 1) {
49025839Speter		if (inode > maxino) {
49125839Speter			warnx("illegal inode %d",inode);
49225839Speter			return;
49325839Speter		}
49425839Speter		errno = 0;
49525839Speter		if ((dp = get_inode(fd,super,inode))
49625839Speter		    && !isfree(super, dp)) {
49725839Speter			printf("%s\t",user(DIP(super, dp, di_uid))->name);
49825839Speter			/* now skip whitespace */
49925839Speter			while ((c = getchar()) == ' ' || c == '\t');
50025839Speter			/* and print out the remainder of the input line */
50125839Speter			while (c != EOF && c != '\n') {
50225839Speter				putchar(c);
50325839Speter				c = getchar();
50425839Speter			}
50525839Speter			putchar('\n');
50625839Speter		} else {
50725839Speter			if (errno) {
50825839Speter				err(1, "%s", name);
50925839Speter			}
51025839Speter			/* skip this line */
51125839Speter			while ((c = getchar()) != EOF && c != '\n');
51225839Speter		}
51325839Speter		if (c == EOF)
51425839Speter			break;
51525839Speter	}
51625839Speter}
51725839Speter
51825839Speterstatic void
51925839Speterusage()
52025839Speter{
52125839Speter#ifdef	COMPAT
52225839Speter	fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n");
52325839Speter#else	/* COMPAT */
52425839Speter	fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n");
52525839Speter#endif	/* COMPAT */
52625839Speter	exit(1);
52725839Speter}
52825839Speter
52925839Speter/*
53025839Speter * Possible superblock locations ordered from most to least likely.
53125839Speter */
53225839Speterstatic int sblock_try[] = SBLOCKSEARCH;
53325839Speterstatic char superblock[SBLOCKSIZE];
53425839Speter
53525839Spetervoid
53625839Speterquot(name,mp)
53725839Speter	char *name, *mp;
53825839Speter{
53925839Speter	int i, fd;
54025839Speter	struct fs *fs;
54125839Speter
54225839Speter	get_inode(-1, NULL, 0);		/* flush cache */
54325839Speter	inituser();
54425839Speter	initfsizes();
54525839Speter	if ((fd = open(name,0)) < 0) {
54625839Speter		warn("%s", name);
54725839Speter		close(fd);
54825839Speter		return;
54925839Speter	}
55025839Speter	for (i = 0; sblock_try[i] != -1; i++) {
55125839Speter		if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) {
55225839Speter			close(fd);
55325839Speter			return;
554		}
555		if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) {
556			close(fd);
557			return;
558		}
559		fs = (struct fs *)superblock;
560		if ((fs->fs_magic == FS_UFS1_MAGIC ||
561		     (fs->fs_magic == FS_UFS2_MAGIC &&
562		      fs->fs_sblockloc == sblock_try[i])) &&
563		    fs->fs_bsize <= MAXBSIZE &&
564		    fs->fs_bsize >= sizeof(struct fs))
565			break;
566	}
567	if (sblock_try[i] == -1) {
568		warnx("%s: not a BSD filesystem",name);
569		close(fd);
570		return;
571	}
572	printf("%s:",name);
573	if (mp)
574		printf(" (%s)",mp);
575	putchar('\n');
576	(*func)(fd, fs, name);
577	close(fd);
578}
579
580int
581main(argc,argv)
582	int argc;
583	char **argv;
584{
585	char all = 0;
586	struct statfs *mp;
587	struct fstab *fs;
588	char dev[MNAMELEN + 1];
589	char *nm;
590	int cnt;
591
592	func = douser;
593#ifndef	COMPAT
594	header = getbsize(&headerlen,&blocksize);
595#endif
596	while (--argc > 0 && **++argv == '-') {
597		while (*++*argv) {
598			switch (**argv) {
599			case 'n':
600				func = donames;
601				break;
602			case 'c':
603				func = dofsizes;
604				break;
605			case 'a':
606				all = 1;
607				break;
608			case 'f':
609				count = 1;
610				break;
611			case 'h':
612				estimate = 1;
613				break;
614#ifndef	COMPAT
615			case 'k':
616				blocksize = 1024;
617				break;
618#endif	/* COMPAT */
619			case 'v':
620				unused = 1;
621				break;
622			default:
623				usage();
624			}
625		}
626	}
627	if (all) {
628		cnt = getmntinfo(&mp,MNT_NOWAIT);
629		for (; --cnt >= 0; mp++) {
630			if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) {
631				if ((nm = strrchr(mp->f_mntfromname,'/'))) {
632					sprintf(dev,"%s%s",_PATH_DEV,nm + 1);
633					nm = dev;
634				} else
635					nm = mp->f_mntfromname;
636				quot(nm,mp->f_mntonname);
637			}
638		}
639	}
640	while (--argc >= 0) {
641		if ((fs = getfsfile(*argv)) != NULL)
642			quot(fs->fs_spec, 0);
643		else
644			quot(*argv,0);
645		argv++;
646	}
647	return 0;
648}
649