quot.c revision 96638
112032Speter/*
212032Speter * Copyright (C) 1991, 1994 Wolfgang Solfrank.
312032Speter * Copyright (C) 1991, 1994 TooLs GmbH.
412032Speter * All rights reserved.
512032Speter *
612032Speter * Redistribution and use in source and binary forms, with or without
712032Speter * modification, are permitted provided that the following conditions
812032Speter * are met:
912032Speter * 1. Redistributions of source code must retain the above copyright
1012032Speter *    notice, this list of conditions and the following disclaimer.
1112032Speter * 2. Redistributions in binary form must reproduce the above copyright
1212032Speter *    notice, this list of conditions and the following disclaimer in the
1312032Speter *    documentation and/or other materials provided with the distribution.
1412032Speter * 3. All advertising materials mentioning features or use of this software
1512032Speter *    must display the following acknowledgement:
1612032Speter *	This product includes software developed by TooLs GmbH.
1712032Speter * 4. The name of TooLs GmbH may not be used to endorse or promote products
1812032Speter *    derived from this software without specific prior written permission.
1912032Speter *
2012032Speter * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2112032Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2212032Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2312032Speter * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2412032Speter * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2512032Speter * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2612032Speter * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2712032Speter * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2812032Speter * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2912032Speter * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3012032Speter */
3112032Speter
3212032Speter#ifndef lint
3330262Scharnierstatic const char rcsid[] =
3450479Speter  "$FreeBSD: head/usr.sbin/quot/quot.c 96638 2002-05-15 08:01:31Z des $";
3512032Speter#endif /* not lint */
3612032Speter
3712032Speter#include <sys/param.h>
3896638Sdes#include <sys/stdint.h>
3912032Speter#include <sys/mount.h>
4096479Sphk#include <sys/disklabel.h>
4112032Speter#include <sys/time.h>
4212032Speter#include <ufs/ffs/fs.h>
4312032Speter#include <ufs/ufs/quota.h>
4412032Speter#include <ufs/ufs/inode.h>
4512032Speter
4630262Scharnier#include <err.h>
4730262Scharnier#include <fcntl.h>
4874071Sps#include <fstab.h>
4930262Scharnier#include <errno.h>
5069793Sobrien#include <paths.h>
5130262Scharnier#include <pwd.h>
5212032Speter#include <stdio.h>
5312032Speter#include <stdlib.h>
5412032Speter#include <string.h>
5530262Scharnier#include <unistd.h>
5612032Speter
5712032Speter/* some flags of what to do: */
5812032Speterstatic char estimate;
5912032Speterstatic char count;
6012032Speterstatic char unused;
6187554Smikehstatic void (*func)(int, struct fs *, char *);
6212032Speterstatic long blocksize;
6312032Speterstatic char *header;
6412032Speterstatic int headerlen;
6512032Speter
6687554Smikehstatic struct dinode *get_inode(int, struct fs *, ino_t);
6787554Smikehstatic int	virtualblocks(struct fs *, struct dinode *);
6887554Smikehstatic int	isfree(struct dinode *);
6987554Smikehstatic void	inituser(void);
7087554Smikehstatic void	usrrehash(void);
7187554Smikehstatic struct user *user(uid_t);
7287554Smikehstatic int	cmpusers(const void *, const void *);
7387554Smikehstatic void	uses(uid_t, daddr_t, time_t);
7487554Smikehstatic void	initfsizes(void);
7587554Smikehstatic void	dofsizes(int, struct fs *, char *);
7687554Smikehstatic void	douser(int, struct fs *, char *);
7787554Smikehstatic void	donames(int, struct fs *, char *);
7887554Smikehstatic void	usage(void);
7987554Smikehstatic void	quot(char *, char *);
8087554Smikeh
8112032Speter/*
8212032Speter * Original BSD quot doesn't round to number of frags/blocks,
8312032Speter * doesn't account for indirection blocks and gets it totally
8412032Speter * wrong if the	size is a multiple of the blocksize.
8512032Speter * The new code always counts the number of 512 byte blocks
8612032Speter * instead of the number of kilobytes and converts them	to
8712032Speter * kByte when done (on request).
8841727Sdillon *
8941727Sdillon * Due to the size of modern disks, we must cast intermediate
9041727Sdillon * values to 64 bits to prevent potential overflows.
9112032Speter */
9212032Speter#ifdef	COMPAT
9312032Speter#define	SIZE(n)	(n)
9412032Speter#else
9541727Sdillon#define	SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize))
9612032Speter#endif
9712032Speter
9812032Speter#define	INOCNT(fs)	((fs)->fs_ipg)
9912032Speter#define	INOSZ(fs)	(sizeof(struct dinode) * INOCNT(fs))
10012032Speter
10130262Scharnierstatic struct dinode *
10230262Scharnierget_inode(fd,super,ino)
10387554Smikeh	int fd;
10412032Speter	struct fs *super;
10512032Speter	ino_t ino;
10612032Speter{
10712032Speter	static struct dinode *ip;
10812032Speter	static ino_t last;
10912032Speter
11012032Speter	if (fd < 0) {		/* flush cache */
11112032Speter		if (ip) {
11212032Speter			free(ip);
11312032Speter			ip = 0;
11412032Speter		}
11512032Speter		return 0;
11612032Speter	}
11712032Speter
11812032Speter	if (!ip || ino < last || ino >= last + INOCNT(super)) {
11912032Speter		if (!ip
12030262Scharnier		    && !(ip = (struct dinode *)malloc(INOSZ(super))))
12130262Scharnier			errx(1, "allocate inodes");
12212032Speter		last = (ino / INOCNT(super)) * INOCNT(super);
12328160Sjkh		if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
12487554Smikeh		    || read(fd,ip,INOSZ(super)) != (ssize_t)INOSZ(super))
12530262Scharnier			err(1, "read inodes");
12612032Speter	}
12712032Speter
12812032Speter	return ip + ino % INOCNT(super);
12912032Speter}
13012032Speter
13112032Speter#ifdef	COMPAT
13212032Speter#define	actualblocks(super,ip)	((ip)->di_blocks/2)
13312032Speter#else
13412032Speter#define	actualblocks(super,ip)	((ip)->di_blocks)
13512032Speter#endif
13612032Speter
13730262Scharnierstatic int virtualblocks(super,ip)
13812032Speter	struct fs *super;
13912032Speter	struct dinode *ip;
14012032Speter{
14112032Speter	register off_t nblk, sz;
14212032Speter
14312032Speter	sz = ip->di_size;
14412032Speter#ifdef	COMPAT
14512032Speter	if (lblkno(super,sz) >= NDADDR) {
14612032Speter		nblk = blkroundup(super,sz);
14712032Speter		if (sz == nblk)
14812032Speter			nblk += super->fs_bsize;
14912032Speter	}
15012032Speter
15112032Speter	return sz / 1024;
15212032Speter
15312032Speter#else	/* COMPAT */
15412032Speter
15512032Speter	if (lblkno(super,sz) >= NDADDR) {
15612032Speter		nblk = blkroundup(super,sz);
15712032Speter		sz = lblkno(super,nblk);
15812032Speter		sz = (sz - NDADDR + NINDIR(super) - 1) / NINDIR(super);
15912032Speter		while (sz > 0) {
16012032Speter			nblk += sz * super->fs_bsize;
16112032Speter			/* sz - 1 rounded up */
16212032Speter			sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super);
16312032Speter		}
16412032Speter	} else
16512032Speter		nblk = fragroundup(super,sz);
16612032Speter
16712032Speter	return nblk / 512;
16812032Speter#endif	/* COMPAT */
16912032Speter}
17012032Speter
17130262Scharnierstatic int
17230262Scharnierisfree(ip)
17312032Speter	struct dinode *ip;
17412032Speter{
17512032Speter#ifdef	COMPAT
17612032Speter	return (ip->di_mode&IFMT) == 0;
17712032Speter#else	/* COMPAT */
17812032Speter
17912032Speter	switch (ip->di_mode&IFMT) {
18012032Speter	case IFIFO:
18112032Speter	case IFLNK:		/* should check FASTSYMLINK? */
18212032Speter	case IFDIR:
18312032Speter	case IFREG:
18412032Speter		return 0;
18512032Speter	default:
18612032Speter		return 1;
18712032Speter	}
18812032Speter#endif
18912032Speter}
19012032Speter
19112032Speterstatic struct user {
19212032Speter	uid_t uid;
19312032Speter	char *name;
19412032Speter	daddr_t space;
19512032Speter	long count;
19612032Speter	daddr_t spc30;
19712032Speter	daddr_t spc60;
19812032Speter	daddr_t spc90;
19912032Speter} *users;
20012032Speterstatic int nusers;
20112032Speter
20230262Scharnierstatic void
20330262Scharnierinituser()
20412032Speter{
20587554Smikeh	register int i;
20612032Speter	register struct user *usr;
20712032Speter
20812032Speter	if (!nusers) {
20912032Speter		nusers = 8;
21012032Speter		if (!(users =
21130262Scharnier		    (struct user *)calloc(nusers,sizeof(struct user))))
21230262Scharnier			errx(1, "allocate users");
21312032Speter	} else {
21412032Speter		for (usr = users, i = nusers; --i >= 0; usr++) {
21512032Speter			usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0;
21612032Speter			usr->count = 0;
21712032Speter		}
21812032Speter	}
21912032Speter}
22012032Speter
22130262Scharnierstatic void
22230262Scharnierusrrehash()
22312032Speter{
22487554Smikeh	register int i;
22512032Speter	register struct user *usr, *usrn;
22612032Speter	struct user *svusr;
22712032Speter
22812032Speter	svusr = users;
22912032Speter	nusers <<= 1;
23030262Scharnier	if (!(users = (struct user *)calloc(nusers,sizeof(struct user))))
23130262Scharnier		errx(1, "allocate users");
23212032Speter	for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) {
23312032Speter		for (usrn = users + (usr->uid&(nusers - 1)); usrn->name;
23412032Speter		    usrn--) {
23512032Speter			if (usrn <= users)
23612032Speter				usrn = users + nusers;
23712032Speter		}
23812032Speter		*usrn = *usr;
23912032Speter	}
24012032Speter}
24112032Speter
24230262Scharnierstatic struct user *
24330262Scharnieruser(uid)
24412032Speter	uid_t uid;
24512032Speter{
24612032Speter	register struct user *usr;
24787554Smikeh	register int i;
24812032Speter	struct passwd *pwd;
24912032Speter
25012032Speter	while (1) {
25112032Speter		for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0;
25212032Speter		    usr--) {
25312032Speter			if (!usr->name) {
25412032Speter				usr->uid = uid;
25512032Speter
25612032Speter				if (!(pwd = getpwuid(uid))) {
25730262Scharnier					if ((usr->name = (char *)malloc(7)))
25812032Speter						sprintf(usr->name,"#%d",uid);
25912032Speter				} else {
26030262Scharnier					if ((usr->name = (char *)
26130262Scharnier					    malloc(strlen(pwd->pw_name) + 1)))
26212032Speter						strcpy(usr->name,pwd->pw_name);
26312032Speter				}
26430262Scharnier				if (!usr->name)
26530262Scharnier					errx(1, "allocate users");
26612032Speter
26712032Speter				return usr;
26812032Speter
26912032Speter			} else if (usr->uid == uid)
27012032Speter				return usr;
27112032Speter
27212032Speter			if (usr <= users)
27312032Speter				usr = users + nusers;
27412032Speter		}
27512032Speter		usrrehash();
27612032Speter	}
27712032Speter}
27812032Speter
27930262Scharnierstatic int
28087554Smikehcmpusers(v1,v2)
28187554Smikeh	const void *v1, *v2;
28212032Speter{
28387554Smikeh	const struct user *u1, *u2;
28487554Smikeh	u1 = (const struct user *)v1;
28587554Smikeh	u2 = (const struct user *)v2;
28687554Smikeh
28712032Speter	return u2->space - u1->space;
28812032Speter}
28912032Speter
29012032Speter#define	sortusers(users)	(qsort((users),nusers,sizeof(struct user), \
29112032Speter				    cmpusers))
29212032Speter
29330262Scharnierstatic void
29430262Scharnieruses(uid,blks,act)
29512032Speter	uid_t uid;
29612032Speter	daddr_t blks;
29712032Speter	time_t act;
29812032Speter{
29912032Speter	static time_t today;
30012032Speter	register struct user *usr;
30112032Speter
30212032Speter	if (!today)
30312032Speter		time(&today);
30412032Speter
30512032Speter	usr = user(uid);
30612032Speter	usr->count++;
30712032Speter	usr->space += blks;
30812032Speter
30912032Speter	if (today - act > 90L * 24L * 60L * 60L)
31012032Speter		usr->spc90 += blks;
31112032Speter	if (today - act > 60L * 24L * 60L * 60L)
31212032Speter		usr->spc60 += blks;
31312032Speter	if (today - act > 30L * 24L * 60L * 60L)
31412032Speter		usr->spc30 += blks;
31512032Speter}
31612032Speter
31712032Speter#ifdef	COMPAT
31812032Speter#define	FSZCNT	500
31912032Speter#else
32012032Speter#define	FSZCNT	512
32112032Speter#endif
32212032Speterstruct fsizes {
32312032Speter	struct fsizes *fsz_next;
32412032Speter	daddr_t fsz_first, fsz_last;
32512032Speter	ino_t fsz_count[FSZCNT];
32612032Speter	daddr_t fsz_sz[FSZCNT];
32712032Speter} *fsizes;
32812032Speter
32930262Scharnierstatic void
33030262Scharnierinitfsizes()
33112032Speter{
33212032Speter	register struct fsizes *fp;
33387554Smikeh	register int i;
33412032Speter
33512032Speter	for (fp = fsizes; fp; fp = fp->fsz_next) {
33612032Speter		for (i = FSZCNT; --i >= 0;) {
33712032Speter			fp->fsz_count[i] = 0;
33812032Speter			fp->fsz_sz[i] = 0;
33912032Speter		}
34012032Speter	}
34112032Speter}
34212032Speter
34330262Scharnierstatic void
34430262Scharnierdofsizes(fd,super,name)
34587554Smikeh	int fd;
34612032Speter	struct fs *super;
34712032Speter	char *name;
34812032Speter{
34912032Speter	ino_t inode, maxino;
35012032Speter	struct dinode *ip;
35112032Speter	daddr_t sz, ksz;
35212032Speter	struct fsizes *fp, **fsp;
35387554Smikeh	register int i;
35412032Speter
35512032Speter	maxino = super->fs_ncg * super->fs_ipg - 1;
35612032Speter#ifdef	COMPAT
35730262Scharnier	if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes))))
35853764Scharnier		errx(1, "allocate fsize structure");
35912032Speter#endif	/* COMPAT */
36012032Speter	for (inode = 0; inode < maxino; inode++) {
36112032Speter		errno = 0;
36212032Speter		if ((ip = get_inode(fd,super,inode))
36312032Speter#ifdef	COMPAT
36412032Speter		    && ((ip->di_mode&IFMT) == IFREG
36512032Speter			|| (ip->di_mode&IFMT) == IFDIR)
36612032Speter#else	/* COMPAT */
36712032Speter		    && !isfree(ip)
36812032Speter#endif	/* COMPAT */
36912032Speter		    ) {
37012032Speter			sz = estimate ? virtualblocks(super,ip) :
37112032Speter			    actualblocks(super,ip);
37212032Speter#ifdef	COMPAT
37312032Speter			if (sz >= FSZCNT) {
37412032Speter				fsizes->fsz_count[FSZCNT-1]++;
37512032Speter				fsizes->fsz_sz[FSZCNT-1] += sz;
37612032Speter			} else {
37712032Speter				fsizes->fsz_count[sz]++;
37812032Speter				fsizes->fsz_sz[sz] += sz;
37912032Speter			}
38012032Speter#else	/* COMPAT */
38112032Speter			ksz = SIZE(sz);
38230262Scharnier			for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) {
38312032Speter				if (ksz < fp->fsz_last)
38412032Speter					break;
38512032Speter			}
38612032Speter			if (!fp || ksz < fp->fsz_first) {
38712032Speter				if (!(fp = (struct fsizes *)
38830262Scharnier				    malloc(sizeof(struct fsizes))))
38953764Scharnier					errx(1, "allocate fsize structure");
39012032Speter				fp->fsz_next = *fsp;
39112032Speter				*fsp = fp;
39212032Speter				fp->fsz_first = (ksz / FSZCNT) * FSZCNT;
39312032Speter				fp->fsz_last = fp->fsz_first + FSZCNT;
39412032Speter				for (i = FSZCNT; --i >= 0;) {
39512032Speter					fp->fsz_count[i] = 0;
39612032Speter					fp->fsz_sz[i] = 0;
39712032Speter				}
39812032Speter			}
39912032Speter			fp->fsz_count[ksz % FSZCNT]++;
40012032Speter			fp->fsz_sz[ksz % FSZCNT] += sz;
40112032Speter#endif	/* COMPAT */
40212032Speter		} else if (errno) {
40330262Scharnier			err(1, "%s", name);
40412032Speter		}
40512032Speter	}
40612032Speter	sz = 0;
40712032Speter	for (fp = fsizes; fp; fp = fp->fsz_next) {
40812032Speter		for (i = 0; i < FSZCNT; i++) {
40912032Speter			if (fp->fsz_count[i])
41096638Sdes				printf("%jd\t%jd\t%d\n",
41196638Sdes				    (intmax_t)(fp->fsz_first + i),
41296638Sdes				    (intmax_t)fp->fsz_count[i],
41312032Speter				    SIZE(sz += fp->fsz_sz[i]));
41412032Speter		}
41512032Speter	}
41612032Speter}
41712032Speter
41830262Scharnierstatic void
41930262Scharnierdouser(fd,super,name)
42087554Smikeh	int fd;
42112032Speter	struct fs *super;
42212032Speter	char *name;
42312032Speter{
42412032Speter	ino_t inode, maxino;
42512032Speter	struct user *usr, *usrs;
42612032Speter	struct dinode *ip;
42787554Smikeh	register int n;
42812032Speter
42912032Speter	maxino = super->fs_ncg * super->fs_ipg - 1;
43012032Speter	for (inode = 0; inode < maxino; inode++) {
43112032Speter		errno = 0;
43212032Speter		if ((ip = get_inode(fd,super,inode))
43312032Speter		    && !isfree(ip))
43412032Speter			uses(ip->di_uid,
43512032Speter			    estimate ? virtualblocks(super,ip) :
43612032Speter				actualblocks(super,ip),
43712032Speter			    ip->di_atime);
43812032Speter		else if (errno) {
43930262Scharnier			err(1, "%s", name);
44012032Speter		}
44112032Speter	}
44230262Scharnier	if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user))))
44330262Scharnier		errx(1, "allocate users");
44412032Speter	bcopy(users,usrs,nusers * sizeof(struct user));
44512032Speter	sortusers(usrs);
44612032Speter	for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) {
44712032Speter		printf("%5d",SIZE(usr->space));
44812032Speter		if (count)
44987554Smikeh			printf("\t%5ld",usr->count);
45012032Speter		printf("\t%-8s",usr->name);
45112032Speter		if (unused)
45212032Speter			printf("\t%5d\t%5d\t%5d",
45312032Speter			       SIZE(usr->spc30),
45412032Speter			       SIZE(usr->spc60),
45512032Speter			       SIZE(usr->spc90));
45612032Speter		printf("\n");
45712032Speter	}
45812032Speter	free(usrs);
45912032Speter}
46012032Speter
46130262Scharnierstatic void
46230262Scharnierdonames(fd,super,name)
46387554Smikeh	int fd;
46412032Speter	struct fs *super;
46512032Speter	char *name;
46612032Speter{
46712032Speter	int c;
46812032Speter	ino_t inode, inode1;
46912032Speter	ino_t maxino;
47012032Speter	struct dinode *ip;
47112032Speter
47212032Speter	maxino = super->fs_ncg * super->fs_ipg - 1;
47312032Speter	/* first skip the name of the filesystem */
47412032Speter	while ((c = getchar()) != EOF && (c < '0' || c > '9'))
47512032Speter		while ((c = getchar()) != EOF && c != '\n');
47612032Speter	ungetc(c,stdin);
47712032Speter	inode1 = -1;
47887554Smikeh	while (scanf("%u",&inode) == 1) {
47987554Smikeh		if (inode > maxino) {
48030262Scharnier			warnx("illegal inode %d",inode);
48112032Speter			return;
48212032Speter		}
48312032Speter		errno = 0;
48412032Speter		if ((ip = get_inode(fd,super,inode))
48512032Speter		    && !isfree(ip)) {
48612032Speter			printf("%s\t",user(ip->di_uid)->name);
48712032Speter			/* now skip whitespace */
48812032Speter			while ((c = getchar()) == ' ' || c == '\t');
48912032Speter			/* and print out the remainder of the input line */
49012032Speter			while (c != EOF && c != '\n') {
49112032Speter				putchar(c);
49212032Speter				c = getchar();
49312032Speter			}
49412032Speter			putchar('\n');
49512032Speter			inode1 = inode;
49612032Speter		} else {
49712032Speter			if (errno) {
49830262Scharnier				err(1, "%s", name);
49912032Speter			}
50012032Speter			/* skip this line */
50112032Speter			while ((c = getchar()) != EOF && c != '\n');
50212032Speter		}
50312032Speter		if (c == EOF)
50412032Speter			break;
50512032Speter	}
50612032Speter}
50712032Speter
50830262Scharnierstatic void
50930262Scharnierusage()
51012032Speter{
51112032Speter#ifdef	COMPAT
51230262Scharnier	fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n");
51312032Speter#else	/* COMPAT */
51453764Scharnier	fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n");
51512032Speter#endif	/* COMPAT */
51612032Speter	exit(1);
51712032Speter}
51812032Speter
51912032Speterstatic char superblock[SBSIZE];
52012032Speter
52130262Scharniervoid
52212032Speterquot(name,mp)
52312032Speter	char *name, *mp;
52412032Speter{
52512032Speter	int fd;
52612032Speter
52787554Smikeh	get_inode(-1, NULL, 0);		/* flush cache */
52812032Speter	inituser();
52912032Speter	initfsizes();
53012032Speter	if ((fd = open(name,0)) < 0
53112032Speter	    || lseek(fd,SBOFF,0) != SBOFF
53212032Speter	    || read(fd,superblock,SBSIZE) != SBSIZE) {
53330262Scharnier		warn("%s", name);
53412032Speter		close(fd);
53512032Speter		return;
53612032Speter	}
53712032Speter	if (((struct fs *)superblock)->fs_magic != FS_MAGIC) {
53830262Scharnier		warnx("%s: not a BSD filesystem",name);
53912032Speter		close(fd);
54012032Speter		return;
54112032Speter	}
54212032Speter	printf("%s:",name);
54312032Speter	if (mp)
54412032Speter		printf(" (%s)",mp);
54512032Speter	putchar('\n');
54687554Smikeh	(*func)(fd,(struct fs *)superblock,name);
54712032Speter	close(fd);
54812032Speter}
54912032Speter
55030262Scharnierint
55130262Scharniermain(argc,argv)
55287554Smikeh	int argc;
55312032Speter	char **argv;
55412032Speter{
55512032Speter	char all = 0;
55612032Speter	struct statfs *mp;
55774071Sps	struct fstab *fs;
55812032Speter	char dev[MNAMELEN + 1];
55912032Speter	char *nm;
56012032Speter	int cnt;
56112032Speter
56212032Speter	func = douser;
56312032Speter#ifndef	COMPAT
56412032Speter	header = getbsize(&headerlen,&blocksize);
56512032Speter#endif
56612032Speter	while (--argc > 0 && **++argv == '-') {
56712032Speter		while (*++*argv) {
56812032Speter			switch (**argv) {
56912032Speter			case 'n':
57012032Speter				func = donames;
57112032Speter				break;
57212032Speter			case 'c':
57312032Speter				func = dofsizes;
57412032Speter				break;
57512032Speter			case 'a':
57612032Speter				all = 1;
57712032Speter				break;
57812032Speter			case 'f':
57912032Speter				count = 1;
58012032Speter				break;
58112032Speter			case 'h':
58212032Speter				estimate = 1;
58312032Speter				break;
58412032Speter#ifndef	COMPAT
58512032Speter			case 'k':
58612032Speter				blocksize = 1024;
58712032Speter				break;
58812032Speter#endif	/* COMPAT */
58912032Speter			case 'v':
59012032Speter				unused = 1;
59112032Speter				break;
59212032Speter			default:
59312032Speter				usage();
59412032Speter			}
59512032Speter		}
59612032Speter	}
59712032Speter	if (all) {
59812032Speter		cnt = getmntinfo(&mp,MNT_NOWAIT);
59912032Speter		for (; --cnt >= 0; mp++) {
60032595Sbde			if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) {
60130262Scharnier				if ((nm = strrchr(mp->f_mntfromname,'/'))) {
60269793Sobrien					sprintf(dev,"%s%s",_PATH_DEV,nm + 1);
60312032Speter					nm = dev;
60412032Speter				} else
60512032Speter					nm = mp->f_mntfromname;
60612032Speter				quot(nm,mp->f_mntonname);
60712032Speter			}
60812032Speter		}
60912032Speter	}
61074071Sps	while (--argc >= 0) {
61174071Sps		if ((fs = getfsfile(*argv)) != NULL)
61274071Sps			quot(fs->fs_spec, 0);
61374071Sps		else
61474071Sps			quot(*argv,0);
61574071Sps		argv++;
61674071Sps	}
61712032Speter	return 0;
61812032Speter}
619