11de7b4b8SPedro F. Giffuni /*-
21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause
31de7b4b8SPedro F. Giffuni *
416c2ba93SPeter Wemm * Copyright (C) 1991, 1994 Wolfgang Solfrank.
516c2ba93SPeter Wemm * Copyright (C) 1991, 1994 TooLs GmbH.
616c2ba93SPeter Wemm * All rights reserved.
716c2ba93SPeter Wemm *
816c2ba93SPeter Wemm * Redistribution and use in source and binary forms, with or without
916c2ba93SPeter Wemm * modification, are permitted provided that the following conditions
1016c2ba93SPeter Wemm * are met:
1116c2ba93SPeter Wemm * 1. Redistributions of source code must retain the above copyright
1216c2ba93SPeter Wemm * notice, this list of conditions and the following disclaimer.
1316c2ba93SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright
1416c2ba93SPeter Wemm * notice, this list of conditions and the following disclaimer in the
1516c2ba93SPeter Wemm * documentation and/or other materials provided with the distribution.
1616c2ba93SPeter Wemm * 3. All advertising materials mentioning features or use of this software
1716c2ba93SPeter Wemm * must display the following acknowledgement:
1816c2ba93SPeter Wemm * This product includes software developed by TooLs GmbH.
1916c2ba93SPeter Wemm * 4. The name of TooLs GmbH may not be used to endorse or promote products
2016c2ba93SPeter Wemm * derived from this software without specific prior written permission.
2116c2ba93SPeter Wemm *
2216c2ba93SPeter Wemm * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2316c2ba93SPeter Wemm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2416c2ba93SPeter Wemm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2516c2ba93SPeter Wemm * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2616c2ba93SPeter Wemm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2716c2ba93SPeter Wemm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2816c2ba93SPeter Wemm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2916c2ba93SPeter Wemm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3016c2ba93SPeter Wemm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3116c2ba93SPeter Wemm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3216c2ba93SPeter Wemm */
3316c2ba93SPeter Wemm
3416c2ba93SPeter Wemm #include <sys/param.h>
359f60cc9eSDag-Erling Smørgrav #include <sys/stdint.h>
3616c2ba93SPeter Wemm #include <sys/mount.h>
37386f1d1bSPoul-Henning Kamp #include <sys/disklabel.h>
381c85e6a3SKirk McKusick #include <ufs/ufs/dinode.h>
3916c2ba93SPeter Wemm #include <ufs/ffs/fs.h>
4016c2ba93SPeter Wemm
416980f0ebSPhilippe Charnier #include <err.h>
426980f0ebSPhilippe Charnier #include <fcntl.h>
4381f1ec27SPaul Saab #include <fstab.h>
446980f0ebSPhilippe Charnier #include <errno.h>
45dffce215SKirk McKusick #include <libufs.h>
461a37aa56SDavid E. O'Brien #include <paths.h>
476980f0ebSPhilippe Charnier #include <pwd.h>
4816c2ba93SPeter Wemm #include <stdio.h>
4916c2ba93SPeter Wemm #include <stdlib.h>
5016c2ba93SPeter Wemm #include <string.h>
517649cb00SKirk McKusick #include <time.h>
526980f0ebSPhilippe Charnier #include <unistd.h>
5316c2ba93SPeter Wemm
5416c2ba93SPeter Wemm /* some flags of what to do: */
5516c2ba93SPeter Wemm static char estimate;
5616c2ba93SPeter Wemm static char count;
5716c2ba93SPeter Wemm static char unused;
5857cdc152SMike Heffner static void (*func)(int, struct fs *, char *);
5916c2ba93SPeter Wemm static long blocksize;
6016c2ba93SPeter Wemm static char *header;
61bc6ba9aeSMike Barcroft static int headerlen;
6216c2ba93SPeter Wemm
631c85e6a3SKirk McKusick static union dinode *get_inode(int, struct fs *, ino_t);
641c85e6a3SKirk McKusick static int virtualblocks(struct fs *, union dinode *);
651c85e6a3SKirk McKusick static int isfree(struct fs *, union dinode *);
6657cdc152SMike Heffner static void inituser(void);
6757cdc152SMike Heffner static void usrrehash(void);
6857cdc152SMike Heffner static struct user *user(uid_t);
6957cdc152SMike Heffner static int cmpusers(const void *, const void *);
7057cdc152SMike Heffner static void uses(uid_t, daddr_t, time_t);
7157cdc152SMike Heffner static void initfsizes(void);
7257cdc152SMike Heffner static void dofsizes(int, struct fs *, char *);
7357cdc152SMike Heffner static void douser(int, struct fs *, char *);
7457cdc152SMike Heffner static void donames(int, struct fs *, char *);
7557cdc152SMike Heffner static void usage(void);
7657cdc152SMike Heffner static void quot(char *, char *);
7757cdc152SMike Heffner
7816c2ba93SPeter Wemm /*
7916c2ba93SPeter Wemm * Original BSD quot doesn't round to number of frags/blocks,
8016c2ba93SPeter Wemm * doesn't account for indirection blocks and gets it totally
8116c2ba93SPeter Wemm * wrong if the size is a multiple of the blocksize.
8216c2ba93SPeter Wemm * The new code always counts the number of 512 byte blocks
8316c2ba93SPeter Wemm * instead of the number of kilobytes and converts them to
8416c2ba93SPeter Wemm * kByte when done (on request).
859983067eSMatthew Dillon *
869983067eSMatthew Dillon * Due to the size of modern disks, we must cast intermediate
879983067eSMatthew Dillon * values to 64 bits to prevent potential overflows.
8816c2ba93SPeter Wemm */
8916c2ba93SPeter Wemm #ifdef COMPAT
9016c2ba93SPeter Wemm #define SIZE(n) (n)
9116c2ba93SPeter Wemm #else
929983067eSMatthew Dillon #define SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize))
9316c2ba93SPeter Wemm #endif
9416c2ba93SPeter Wemm
9516c2ba93SPeter Wemm #define INOCNT(fs) ((fs)->fs_ipg)
961c85e6a3SKirk McKusick #define INOSZ(fs) \
971c85e6a3SKirk McKusick (((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \
981c85e6a3SKirk McKusick sizeof(struct ufs2_dinode)) * INOCNT(fs))
9916c2ba93SPeter Wemm
1001c85e6a3SKirk McKusick union dinode {
1011c85e6a3SKirk McKusick struct ufs1_dinode dp1;
1021c85e6a3SKirk McKusick struct ufs2_dinode dp2;
1031c85e6a3SKirk McKusick };
1041c85e6a3SKirk McKusick #define DIP(fs, dp, field) \
1051c85e6a3SKirk McKusick (((fs)->fs_magic == FS_UFS1_MAGIC) ? \
1061c85e6a3SKirk McKusick (dp)->dp1.field : (dp)->dp2.field)
1071c85e6a3SKirk McKusick
1081c85e6a3SKirk McKusick static union dinode *
get_inode(int fd,struct fs * super,ino_t ino)1098f518424SDag-Erling Smørgrav get_inode(int fd, struct fs *super, ino_t ino)
11016c2ba93SPeter Wemm {
1111c85e6a3SKirk McKusick static caddr_t ipbuf;
112bee3d34fSDavid Malone static struct cg *cgp;
11316c2ba93SPeter Wemm static ino_t last;
114bee3d34fSDavid Malone static int cg;
115bee3d34fSDavid Malone struct ufs2_dinode *di2;
11616c2ba93SPeter Wemm
11716c2ba93SPeter Wemm if (fd < 0) { /* flush cache */
1181c85e6a3SKirk McKusick if (ipbuf) {
1191c85e6a3SKirk McKusick free(ipbuf);
1201c85e6a3SKirk McKusick ipbuf = 0;
121c433b438SMaxim Konovalov if (super != NULL && super->fs_magic == FS_UFS2_MAGIC) {
122bee3d34fSDavid Malone free(cgp);
123bee3d34fSDavid Malone cgp = 0;
124bee3d34fSDavid Malone }
12516c2ba93SPeter Wemm }
12616c2ba93SPeter Wemm return 0;
12716c2ba93SPeter Wemm }
12816c2ba93SPeter Wemm
1291c85e6a3SKirk McKusick if (!ipbuf || ino < last || ino >= last + INOCNT(super)) {
130bee3d34fSDavid Malone if (super->fs_magic == FS_UFS2_MAGIC &&
131bee3d34fSDavid Malone (!cgp || cg != ino_to_cg(super, ino))) {
132bee3d34fSDavid Malone cg = ino_to_cg(super, ino);
133bee3d34fSDavid Malone if (!cgp && !(cgp = malloc(super->fs_cgsize)))
134bee3d34fSDavid Malone errx(1, "allocate cg");
135bee3d34fSDavid Malone if (lseek(fd, (off_t)cgtod(super, cg) << super->fs_fshift, 0) < 0)
136bee3d34fSDavid Malone err(1, "lseek cg");
137bee3d34fSDavid Malone if (read(fd, cgp, super->fs_cgsize) != super->fs_cgsize)
138bee3d34fSDavid Malone err(1, "read cg");
139bee3d34fSDavid Malone if (!cg_chkmagic(cgp))
140bee3d34fSDavid Malone errx(1, "cg has bad magic");
141bee3d34fSDavid Malone }
1421c85e6a3SKirk McKusick if (!ipbuf
1431c85e6a3SKirk McKusick && !(ipbuf = malloc(INOSZ(super))))
1446980f0ebSPhilippe Charnier errx(1, "allocate inodes");
1456e560addSPedro F. Giffuni last = rounddown(ino, INOCNT(super));
146c9d12677SJordan K. Hubbard if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0
1471c85e6a3SKirk McKusick || read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super))
1486980f0ebSPhilippe Charnier err(1, "read inodes");
14916c2ba93SPeter Wemm }
15016c2ba93SPeter Wemm
1511c85e6a3SKirk McKusick if (super->fs_magic == FS_UFS1_MAGIC)
1521c85e6a3SKirk McKusick return ((union dinode *)
1531c85e6a3SKirk McKusick &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]);
154bee3d34fSDavid Malone di2 = &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)];
155bee3d34fSDavid Malone /* If the inode is unused, it might be unallocated too, so zero it. */
156bee3d34fSDavid Malone if (isclr(cg_inosused(cgp), ino % super->fs_ipg))
157bee3d34fSDavid Malone bzero(di2, sizeof (*di2));
158bee3d34fSDavid Malone return ((union dinode *)di2);
15916c2ba93SPeter Wemm }
16016c2ba93SPeter Wemm
16116c2ba93SPeter Wemm #ifdef COMPAT
1621c85e6a3SKirk McKusick #define actualblocks(fs, dp) (DIP(fs, dp, di_blocks) / 2)
16316c2ba93SPeter Wemm #else
1641c85e6a3SKirk McKusick #define actualblocks(fs, dp) DIP(fs, dp, di_blocks)
16516c2ba93SPeter Wemm #endif
16616c2ba93SPeter Wemm
virtualblocks(struct fs * super,union dinode * dp)1678f518424SDag-Erling Smørgrav static int virtualblocks(struct fs *super, union dinode *dp)
16816c2ba93SPeter Wemm {
1698f518424SDag-Erling Smørgrav off_t nblk, sz;
17016c2ba93SPeter Wemm
1711c85e6a3SKirk McKusick sz = DIP(super, dp, di_size);
17216c2ba93SPeter Wemm #ifdef COMPAT
1731dc349abSEd Maste if (lblkno(super,sz) >= UFS_NDADDR) {
17416c2ba93SPeter Wemm nblk = blkroundup(super,sz);
17516c2ba93SPeter Wemm if (sz == nblk)
17616c2ba93SPeter Wemm nblk += super->fs_bsize;
17716c2ba93SPeter Wemm }
17816c2ba93SPeter Wemm
17916c2ba93SPeter Wemm return sz / 1024;
18016c2ba93SPeter Wemm
18116c2ba93SPeter Wemm #else /* COMPAT */
18216c2ba93SPeter Wemm
1831dc349abSEd Maste if (lblkno(super,sz) >= UFS_NDADDR) {
18416c2ba93SPeter Wemm nblk = blkroundup(super,sz);
18516c2ba93SPeter Wemm sz = lblkno(super,nblk);
1861dc349abSEd Maste sz = (sz - UFS_NDADDR + NINDIR(super) - 1) / NINDIR(super);
18716c2ba93SPeter Wemm while (sz > 0) {
18816c2ba93SPeter Wemm nblk += sz * super->fs_bsize;
18916c2ba93SPeter Wemm /* sz - 1 rounded up */
19016c2ba93SPeter Wemm sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super);
19116c2ba93SPeter Wemm }
19216c2ba93SPeter Wemm } else
19316c2ba93SPeter Wemm nblk = fragroundup(super,sz);
19416c2ba93SPeter Wemm
19516c2ba93SPeter Wemm return nblk / 512;
19616c2ba93SPeter Wemm #endif /* COMPAT */
19716c2ba93SPeter Wemm }
19816c2ba93SPeter Wemm
1996980f0ebSPhilippe Charnier static int
isfree(struct fs * super,union dinode * dp)2008f518424SDag-Erling Smørgrav isfree(struct fs *super, union dinode *dp)
20116c2ba93SPeter Wemm {
20216c2ba93SPeter Wemm #ifdef COMPAT
203d8ba45e2SEd Maste return (DIP(super, dp, di_mode) & IFMT) == 0;
20416c2ba93SPeter Wemm #else /* COMPAT */
20516c2ba93SPeter Wemm
206d8ba45e2SEd Maste switch (DIP(super, dp, di_mode) & IFMT) {
207d8ba45e2SEd Maste case IFIFO:
208d8ba45e2SEd Maste case IFLNK: /* should check FASTSYMLINK? */
209d8ba45e2SEd Maste case IFDIR:
210d8ba45e2SEd Maste case IFREG:
21116c2ba93SPeter Wemm return 0;
212d8ba45e2SEd Maste case IFCHR:
213d8ba45e2SEd Maste case IFBLK:
214d8ba45e2SEd Maste case IFSOCK:
215d8ba45e2SEd Maste case IFWHT:
216bee3d34fSDavid Malone case 0:
21716c2ba93SPeter Wemm return 1;
218bee3d34fSDavid Malone default:
219d8ba45e2SEd Maste errx(1, "unknown IFMT 0%o", DIP(super, dp, di_mode) & IFMT);
22016c2ba93SPeter Wemm }
22116c2ba93SPeter Wemm #endif
22216c2ba93SPeter Wemm }
22316c2ba93SPeter Wemm
22416c2ba93SPeter Wemm static struct user {
22516c2ba93SPeter Wemm uid_t uid;
22616c2ba93SPeter Wemm char *name;
22716c2ba93SPeter Wemm daddr_t space;
22816c2ba93SPeter Wemm long count;
22916c2ba93SPeter Wemm daddr_t spc30;
23016c2ba93SPeter Wemm daddr_t spc60;
23116c2ba93SPeter Wemm daddr_t spc90;
23216c2ba93SPeter Wemm } *users;
23316c2ba93SPeter Wemm static int nusers;
23416c2ba93SPeter Wemm
2356980f0ebSPhilippe Charnier static void
inituser(void)2368f518424SDag-Erling Smørgrav inituser(void)
23716c2ba93SPeter Wemm {
2388f518424SDag-Erling Smørgrav int i;
2398f518424SDag-Erling Smørgrav struct user *usr;
24016c2ba93SPeter Wemm
24116c2ba93SPeter Wemm if (!nusers) {
24216c2ba93SPeter Wemm nusers = 8;
24316c2ba93SPeter Wemm if (!(users =
2446980f0ebSPhilippe Charnier (struct user *)calloc(nusers,sizeof(struct user))))
2456980f0ebSPhilippe Charnier errx(1, "allocate users");
24616c2ba93SPeter Wemm } else {
24716c2ba93SPeter Wemm for (usr = users, i = nusers; --i >= 0; usr++) {
24816c2ba93SPeter Wemm usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0;
24916c2ba93SPeter Wemm usr->count = 0;
25016c2ba93SPeter Wemm }
25116c2ba93SPeter Wemm }
25216c2ba93SPeter Wemm }
25316c2ba93SPeter Wemm
2546980f0ebSPhilippe Charnier static void
usrrehash(void)2558f518424SDag-Erling Smørgrav usrrehash(void)
25616c2ba93SPeter Wemm {
2578f518424SDag-Erling Smørgrav int i;
2588f518424SDag-Erling Smørgrav struct user *usr, *usrn;
25916c2ba93SPeter Wemm struct user *svusr;
26016c2ba93SPeter Wemm
26116c2ba93SPeter Wemm svusr = users;
26216c2ba93SPeter Wemm nusers <<= 1;
2636980f0ebSPhilippe Charnier if (!(users = (struct user *)calloc(nusers,sizeof(struct user))))
2646980f0ebSPhilippe Charnier errx(1, "allocate users");
26516c2ba93SPeter Wemm for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) {
26616c2ba93SPeter Wemm for (usrn = users + (usr->uid&(nusers - 1)); usrn->name;
26716c2ba93SPeter Wemm usrn--) {
26816c2ba93SPeter Wemm if (usrn <= users)
26916c2ba93SPeter Wemm usrn = users + nusers;
27016c2ba93SPeter Wemm }
27116c2ba93SPeter Wemm *usrn = *usr;
27216c2ba93SPeter Wemm }
27316c2ba93SPeter Wemm }
27416c2ba93SPeter Wemm
2756980f0ebSPhilippe Charnier static struct user *
user(uid_t uid)2768f518424SDag-Erling Smørgrav user(uid_t uid)
27716c2ba93SPeter Wemm {
2788f518424SDag-Erling Smørgrav struct user *usr;
2798f518424SDag-Erling Smørgrav int i;
28016c2ba93SPeter Wemm struct passwd *pwd;
28116c2ba93SPeter Wemm
28216c2ba93SPeter Wemm while (1) {
28316c2ba93SPeter Wemm for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0;
28416c2ba93SPeter Wemm usr--) {
28516c2ba93SPeter Wemm if (!usr->name) {
28616c2ba93SPeter Wemm usr->uid = uid;
28716c2ba93SPeter Wemm
28816c2ba93SPeter Wemm if (!(pwd = getpwuid(uid))) {
2896980f0ebSPhilippe Charnier if ((usr->name = (char *)malloc(7)))
29016c2ba93SPeter Wemm sprintf(usr->name,"#%d",uid);
29116c2ba93SPeter Wemm } else {
2926980f0ebSPhilippe Charnier if ((usr->name = (char *)
2936980f0ebSPhilippe Charnier malloc(strlen(pwd->pw_name) + 1)))
29416c2ba93SPeter Wemm strcpy(usr->name,pwd->pw_name);
29516c2ba93SPeter Wemm }
2966980f0ebSPhilippe Charnier if (!usr->name)
2976980f0ebSPhilippe Charnier errx(1, "allocate users");
29816c2ba93SPeter Wemm
29916c2ba93SPeter Wemm return usr;
30016c2ba93SPeter Wemm
30116c2ba93SPeter Wemm } else if (usr->uid == uid)
30216c2ba93SPeter Wemm return usr;
30316c2ba93SPeter Wemm
30416c2ba93SPeter Wemm if (usr <= users)
30516c2ba93SPeter Wemm usr = users + nusers;
30616c2ba93SPeter Wemm }
30716c2ba93SPeter Wemm usrrehash();
30816c2ba93SPeter Wemm }
30916c2ba93SPeter Wemm }
31016c2ba93SPeter Wemm
3116980f0ebSPhilippe Charnier static int
cmpusers(const void * v1,const void * v2)3128f518424SDag-Erling Smørgrav cmpusers(const void *v1, const void *v2)
31316c2ba93SPeter Wemm {
31457cdc152SMike Heffner const struct user *u1, *u2;
31557cdc152SMike Heffner u1 = (const struct user *)v1;
31657cdc152SMike Heffner u2 = (const struct user *)v2;
31757cdc152SMike Heffner
31816c2ba93SPeter Wemm return u2->space - u1->space;
31916c2ba93SPeter Wemm }
32016c2ba93SPeter Wemm
32116c2ba93SPeter Wemm #define sortusers(users) (qsort((users),nusers,sizeof(struct user), \
32216c2ba93SPeter Wemm cmpusers))
32316c2ba93SPeter Wemm
3246980f0ebSPhilippe Charnier static void
uses(uid_t uid,daddr_t blks,time_t act)3258f518424SDag-Erling Smørgrav uses(uid_t uid, daddr_t blks, time_t act)
32616c2ba93SPeter Wemm {
32716c2ba93SPeter Wemm static time_t today;
3288f518424SDag-Erling Smørgrav struct user *usr;
32916c2ba93SPeter Wemm
33016c2ba93SPeter Wemm if (!today)
33116c2ba93SPeter Wemm time(&today);
33216c2ba93SPeter Wemm
33316c2ba93SPeter Wemm usr = user(uid);
33416c2ba93SPeter Wemm usr->count++;
33516c2ba93SPeter Wemm usr->space += blks;
33616c2ba93SPeter Wemm
33716c2ba93SPeter Wemm if (today - act > 90L * 24L * 60L * 60L)
33816c2ba93SPeter Wemm usr->spc90 += blks;
33916c2ba93SPeter Wemm if (today - act > 60L * 24L * 60L * 60L)
34016c2ba93SPeter Wemm usr->spc60 += blks;
34116c2ba93SPeter Wemm if (today - act > 30L * 24L * 60L * 60L)
34216c2ba93SPeter Wemm usr->spc30 += blks;
34316c2ba93SPeter Wemm }
34416c2ba93SPeter Wemm
34516c2ba93SPeter Wemm #ifdef COMPAT
34616c2ba93SPeter Wemm #define FSZCNT 500
34716c2ba93SPeter Wemm #else
34816c2ba93SPeter Wemm #define FSZCNT 512
34916c2ba93SPeter Wemm #endif
35016c2ba93SPeter Wemm struct fsizes {
35116c2ba93SPeter Wemm struct fsizes *fsz_next;
35216c2ba93SPeter Wemm daddr_t fsz_first, fsz_last;
35316c2ba93SPeter Wemm ino_t fsz_count[FSZCNT];
35416c2ba93SPeter Wemm daddr_t fsz_sz[FSZCNT];
35516c2ba93SPeter Wemm } *fsizes;
35616c2ba93SPeter Wemm
3576980f0ebSPhilippe Charnier static void
initfsizes(void)3588f518424SDag-Erling Smørgrav initfsizes(void)
35916c2ba93SPeter Wemm {
3608f518424SDag-Erling Smørgrav struct fsizes *fp;
3618f518424SDag-Erling Smørgrav int i;
36216c2ba93SPeter Wemm
36316c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) {
36416c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) {
36516c2ba93SPeter Wemm fp->fsz_count[i] = 0;
36616c2ba93SPeter Wemm fp->fsz_sz[i] = 0;
36716c2ba93SPeter Wemm }
36816c2ba93SPeter Wemm }
36916c2ba93SPeter Wemm }
37016c2ba93SPeter Wemm
3716980f0ebSPhilippe Charnier static void
dofsizes(int fd,struct fs * super,char * name)3728f518424SDag-Erling Smørgrav dofsizes(int fd, struct fs *super, char *name)
37316c2ba93SPeter Wemm {
37416c2ba93SPeter Wemm ino_t inode, maxino;
3751c85e6a3SKirk McKusick union dinode *dp;
37616c2ba93SPeter Wemm daddr_t sz, ksz;
37716c2ba93SPeter Wemm struct fsizes *fp, **fsp;
3788f518424SDag-Erling Smørgrav int i;
37916c2ba93SPeter Wemm
38016c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1;
38116c2ba93SPeter Wemm #ifdef COMPAT
3826980f0ebSPhilippe Charnier if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes))))
383652b7200SPhilippe Charnier errx(1, "allocate fsize structure");
38416c2ba93SPeter Wemm #endif /* COMPAT */
38516c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) {
38616c2ba93SPeter Wemm errno = 0;
3871c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode))
38816c2ba93SPeter Wemm #ifdef COMPAT
389d8ba45e2SEd Maste && ((DIP(super, dp, di_mode) & IFMT) == IFREG
390d8ba45e2SEd Maste || (DIP(super, dp, di_mode) & IFMT) == IFDIR)
39116c2ba93SPeter Wemm #else /* COMPAT */
3921c85e6a3SKirk McKusick && !isfree(super, dp)
39316c2ba93SPeter Wemm #endif /* COMPAT */
39416c2ba93SPeter Wemm ) {
3951c85e6a3SKirk McKusick sz = estimate ? virtualblocks(super, dp) :
3961c85e6a3SKirk McKusick actualblocks(super, dp);
39716c2ba93SPeter Wemm #ifdef COMPAT
39816c2ba93SPeter Wemm if (sz >= FSZCNT) {
39916c2ba93SPeter Wemm fsizes->fsz_count[FSZCNT-1]++;
40016c2ba93SPeter Wemm fsizes->fsz_sz[FSZCNT-1] += sz;
40116c2ba93SPeter Wemm } else {
40216c2ba93SPeter Wemm fsizes->fsz_count[sz]++;
40316c2ba93SPeter Wemm fsizes->fsz_sz[sz] += sz;
40416c2ba93SPeter Wemm }
40516c2ba93SPeter Wemm #else /* COMPAT */
40616c2ba93SPeter Wemm ksz = SIZE(sz);
4076980f0ebSPhilippe Charnier for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) {
40816c2ba93SPeter Wemm if (ksz < fp->fsz_last)
40916c2ba93SPeter Wemm break;
41016c2ba93SPeter Wemm }
41116c2ba93SPeter Wemm if (!fp || ksz < fp->fsz_first) {
41216c2ba93SPeter Wemm if (!(fp = (struct fsizes *)
4136980f0ebSPhilippe Charnier malloc(sizeof(struct fsizes))))
414652b7200SPhilippe Charnier errx(1, "allocate fsize structure");
41516c2ba93SPeter Wemm fp->fsz_next = *fsp;
41616c2ba93SPeter Wemm *fsp = fp;
4176e560addSPedro F. Giffuni fp->fsz_first = rounddown(ksz, FSZCNT);
41816c2ba93SPeter Wemm fp->fsz_last = fp->fsz_first + FSZCNT;
41916c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) {
42016c2ba93SPeter Wemm fp->fsz_count[i] = 0;
42116c2ba93SPeter Wemm fp->fsz_sz[i] = 0;
42216c2ba93SPeter Wemm }
42316c2ba93SPeter Wemm }
42416c2ba93SPeter Wemm fp->fsz_count[ksz % FSZCNT]++;
42516c2ba93SPeter Wemm fp->fsz_sz[ksz % FSZCNT] += sz;
42616c2ba93SPeter Wemm #endif /* COMPAT */
42716c2ba93SPeter Wemm } else if (errno) {
4286980f0ebSPhilippe Charnier err(1, "%s", name);
42916c2ba93SPeter Wemm }
43016c2ba93SPeter Wemm }
43116c2ba93SPeter Wemm sz = 0;
43216c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) {
43316c2ba93SPeter Wemm for (i = 0; i < FSZCNT; i++) {
43416c2ba93SPeter Wemm if (fp->fsz_count[i])
4359f60cc9eSDag-Erling Smørgrav printf("%jd\t%jd\t%d\n",
4369f60cc9eSDag-Erling Smørgrav (intmax_t)(fp->fsz_first + i),
4379f60cc9eSDag-Erling Smørgrav (intmax_t)fp->fsz_count[i],
43816c2ba93SPeter Wemm SIZE(sz += fp->fsz_sz[i]));
43916c2ba93SPeter Wemm }
44016c2ba93SPeter Wemm }
44116c2ba93SPeter Wemm }
44216c2ba93SPeter Wemm
4436980f0ebSPhilippe Charnier static void
douser(int fd,struct fs * super,char * name)4448f518424SDag-Erling Smørgrav douser(int fd, struct fs *super, char *name)
44516c2ba93SPeter Wemm {
44616c2ba93SPeter Wemm ino_t inode, maxino;
44716c2ba93SPeter Wemm struct user *usr, *usrs;
4481c85e6a3SKirk McKusick union dinode *dp;
4498f518424SDag-Erling Smørgrav int n;
45016c2ba93SPeter Wemm
45116c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1;
45216c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) {
45316c2ba93SPeter Wemm errno = 0;
4541c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode))
4551c85e6a3SKirk McKusick && !isfree(super, dp))
4561c85e6a3SKirk McKusick uses(DIP(super, dp, di_uid),
4571c85e6a3SKirk McKusick estimate ? virtualblocks(super, dp) :
4581c85e6a3SKirk McKusick actualblocks(super, dp),
4591c85e6a3SKirk McKusick DIP(super, dp, di_atime));
46016c2ba93SPeter Wemm else if (errno) {
4616980f0ebSPhilippe Charnier err(1, "%s", name);
46216c2ba93SPeter Wemm }
46316c2ba93SPeter Wemm }
4646980f0ebSPhilippe Charnier if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user))))
4656980f0ebSPhilippe Charnier errx(1, "allocate users");
46616c2ba93SPeter Wemm bcopy(users,usrs,nusers * sizeof(struct user));
46716c2ba93SPeter Wemm sortusers(usrs);
46816c2ba93SPeter Wemm for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) {
46916c2ba93SPeter Wemm printf("%5d",SIZE(usr->space));
47016c2ba93SPeter Wemm if (count)
47157cdc152SMike Heffner printf("\t%5ld",usr->count);
47216c2ba93SPeter Wemm printf("\t%-8s",usr->name);
47316c2ba93SPeter Wemm if (unused)
47416c2ba93SPeter Wemm printf("\t%5d\t%5d\t%5d",
47516c2ba93SPeter Wemm SIZE(usr->spc30),
47616c2ba93SPeter Wemm SIZE(usr->spc60),
47716c2ba93SPeter Wemm SIZE(usr->spc90));
47816c2ba93SPeter Wemm printf("\n");
47916c2ba93SPeter Wemm }
48016c2ba93SPeter Wemm free(usrs);
48116c2ba93SPeter Wemm }
48216c2ba93SPeter Wemm
4836980f0ebSPhilippe Charnier static void
donames(int fd,struct fs * super,char * name)4848f518424SDag-Erling Smørgrav donames(int fd, struct fs *super, char *name)
48516c2ba93SPeter Wemm {
48616c2ba93SPeter Wemm int c;
48716c2ba93SPeter Wemm ino_t maxino;
488b424efd5SMatthew D Fleming uintmax_t inode;
4891c85e6a3SKirk McKusick union dinode *dp;
49016c2ba93SPeter Wemm
49116c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1;
49216c2ba93SPeter Wemm /* first skip the name of the filesystem */
49316c2ba93SPeter Wemm while ((c = getchar()) != EOF && (c < '0' || c > '9'))
49416c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n');
49516c2ba93SPeter Wemm ungetc(c,stdin);
496b424efd5SMatthew D Fleming while (scanf("%ju", &inode) == 1) {
49757cdc152SMike Heffner if (inode > maxino) {
498b424efd5SMatthew D Fleming warnx("illegal inode %ju", inode);
49916c2ba93SPeter Wemm return;
50016c2ba93SPeter Wemm }
50116c2ba93SPeter Wemm errno = 0;
5021c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode))
5031c85e6a3SKirk McKusick && !isfree(super, dp)) {
5041c85e6a3SKirk McKusick printf("%s\t",user(DIP(super, dp, di_uid))->name);
50516c2ba93SPeter Wemm /* now skip whitespace */
50616c2ba93SPeter Wemm while ((c = getchar()) == ' ' || c == '\t');
50716c2ba93SPeter Wemm /* and print out the remainder of the input line */
50816c2ba93SPeter Wemm while (c != EOF && c != '\n') {
50916c2ba93SPeter Wemm putchar(c);
51016c2ba93SPeter Wemm c = getchar();
51116c2ba93SPeter Wemm }
51216c2ba93SPeter Wemm putchar('\n');
51316c2ba93SPeter Wemm } else {
51416c2ba93SPeter Wemm if (errno) {
5156980f0ebSPhilippe Charnier err(1, "%s", name);
51616c2ba93SPeter Wemm }
51716c2ba93SPeter Wemm /* skip this line */
51816c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n');
51916c2ba93SPeter Wemm }
52016c2ba93SPeter Wemm if (c == EOF)
52116c2ba93SPeter Wemm break;
52216c2ba93SPeter Wemm }
52316c2ba93SPeter Wemm }
52416c2ba93SPeter Wemm
5256980f0ebSPhilippe Charnier static void
usage(void)5268f518424SDag-Erling Smørgrav usage(void)
52716c2ba93SPeter Wemm {
52816c2ba93SPeter Wemm #ifdef COMPAT
529752a3404SRicardo Branco fprintf(stderr, "usage: quot [-cfhnv] [-a | filesystem ...]\n");
53016c2ba93SPeter Wemm #else /* COMPAT */
531752a3404SRicardo Branco fprintf(stderr, "usage: quot [-cfhknv] [-a | filesystem ...]\n");
53216c2ba93SPeter Wemm #endif /* COMPAT */
53316c2ba93SPeter Wemm exit(1);
53416c2ba93SPeter Wemm }
53516c2ba93SPeter Wemm
5366980f0ebSPhilippe Charnier void
quot(char * name,char * mp)5378f518424SDag-Erling Smørgrav quot(char *name, char *mp)
53816c2ba93SPeter Wemm {
539dffce215SKirk McKusick int fd;
5401c85e6a3SKirk McKusick struct fs *fs;
54116c2ba93SPeter Wemm
54257cdc152SMike Heffner get_inode(-1, NULL, 0); /* flush cache */
54316c2ba93SPeter Wemm inituser();
54416c2ba93SPeter Wemm initfsizes();
5451c85e6a3SKirk McKusick if ((fd = open(name,0)) < 0) {
5466980f0ebSPhilippe Charnier warn("%s", name);
54716c2ba93SPeter Wemm close(fd);
54816c2ba93SPeter Wemm return;
54916c2ba93SPeter Wemm }
550b21582eeSKirk McKusick switch (errno = sbget(fd, &fs, UFS_STDSB, UFS_NOCSUM)) {
551dffce215SKirk McKusick case 0:
5521c85e6a3SKirk McKusick break;
553dffce215SKirk McKusick case ENOENT:
554dffce215SKirk McKusick warn("Cannot find file system superblock");
555dffce215SKirk McKusick close(fd);
556dffce215SKirk McKusick return;
557dffce215SKirk McKusick default:
558dffce215SKirk McKusick warn("Unable to read file system superblock");
55916c2ba93SPeter Wemm close(fd);
56016c2ba93SPeter Wemm return;
56116c2ba93SPeter Wemm }
56216c2ba93SPeter Wemm printf("%s:",name);
56316c2ba93SPeter Wemm if (mp)
56416c2ba93SPeter Wemm printf(" (%s)",mp);
56516c2ba93SPeter Wemm putchar('\n');
5661c85e6a3SKirk McKusick (*func)(fd, fs, name);
56734816cb9SKirk McKusick free(fs);
56816c2ba93SPeter Wemm close(fd);
56916c2ba93SPeter Wemm }
57016c2ba93SPeter Wemm
5716980f0ebSPhilippe Charnier int
main(int argc,char * argv[])5728f518424SDag-Erling Smørgrav main(int argc, char *argv[])
57316c2ba93SPeter Wemm {
57416c2ba93SPeter Wemm char all = 0;
57516c2ba93SPeter Wemm struct statfs *mp;
57681f1ec27SPaul Saab struct fstab *fs;
57716c2ba93SPeter Wemm int cnt;
578752a3404SRicardo Branco int ch;
57916c2ba93SPeter Wemm
58016c2ba93SPeter Wemm func = douser;
58116c2ba93SPeter Wemm #ifndef COMPAT
58216c2ba93SPeter Wemm header = getbsize(&headerlen,&blocksize);
58316c2ba93SPeter Wemm #endif
584752a3404SRicardo Branco while ((ch = getopt(argc, argv, "acfhknv")) != -1) {
585752a3404SRicardo Branco switch (ch) {
586752a3404SRicardo Branco case 'a':
587752a3404SRicardo Branco all = 1;
58816c2ba93SPeter Wemm break;
58916c2ba93SPeter Wemm case 'c':
59016c2ba93SPeter Wemm func = dofsizes;
59116c2ba93SPeter Wemm break;
59216c2ba93SPeter Wemm case 'f':
59316c2ba93SPeter Wemm count = 1;
59416c2ba93SPeter Wemm break;
59516c2ba93SPeter Wemm case 'h':
59616c2ba93SPeter Wemm estimate = 1;
59716c2ba93SPeter Wemm break;
59816c2ba93SPeter Wemm #ifndef COMPAT
59916c2ba93SPeter Wemm case 'k':
60016c2ba93SPeter Wemm blocksize = 1024;
60116c2ba93SPeter Wemm break;
60216c2ba93SPeter Wemm #endif /* COMPAT */
603752a3404SRicardo Branco case 'n':
604752a3404SRicardo Branco func = donames;
605752a3404SRicardo Branco break;
60616c2ba93SPeter Wemm case 'v':
60716c2ba93SPeter Wemm unused = 1;
60816c2ba93SPeter Wemm break;
60916c2ba93SPeter Wemm default:
61016c2ba93SPeter Wemm usage();
61116c2ba93SPeter Wemm }
61216c2ba93SPeter Wemm }
613752a3404SRicardo Branco argc -= optind;
614752a3404SRicardo Branco argv += optind;
615752a3404SRicardo Branco
616752a3404SRicardo Branco if ((argc == 0 && !all) || (all && argc))
617752a3404SRicardo Branco usage();
618752a3404SRicardo Branco
61916c2ba93SPeter Wemm if (all) {
62016c2ba93SPeter Wemm cnt = getmntinfo(&mp,MNT_NOWAIT);
62116c2ba93SPeter Wemm for (; --cnt >= 0; mp++) {
622b4eca767SEd Schouten if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN))
623b4eca767SEd Schouten quot(mp->f_mntfromname, mp->f_mntonname);
62416c2ba93SPeter Wemm }
62516c2ba93SPeter Wemm }
62681f1ec27SPaul Saab while (--argc >= 0) {
62781f1ec27SPaul Saab if ((fs = getfsfile(*argv)) != NULL)
62881f1ec27SPaul Saab quot(fs->fs_spec, 0);
62981f1ec27SPaul Saab else
63081f1ec27SPaul Saab quot(*argv,0);
63181f1ec27SPaul Saab argv++;
63281f1ec27SPaul Saab }
63316c2ba93SPeter Wemm return 0;
63416c2ba93SPeter Wemm }
635