116c2ba93SPeter Wemm /* 216c2ba93SPeter Wemm * Copyright (C) 1991, 1994 Wolfgang Solfrank. 316c2ba93SPeter Wemm * Copyright (C) 1991, 1994 TooLs GmbH. 416c2ba93SPeter Wemm * All rights reserved. 516c2ba93SPeter Wemm * 616c2ba93SPeter Wemm * Redistribution and use in source and binary forms, with or without 716c2ba93SPeter Wemm * modification, are permitted provided that the following conditions 816c2ba93SPeter Wemm * are met: 916c2ba93SPeter Wemm * 1. Redistributions of source code must retain the above copyright 1016c2ba93SPeter Wemm * notice, this list of conditions and the following disclaimer. 1116c2ba93SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 1216c2ba93SPeter Wemm * notice, this list of conditions and the following disclaimer in the 1316c2ba93SPeter Wemm * documentation and/or other materials provided with the distribution. 1416c2ba93SPeter Wemm * 3. All advertising materials mentioning features or use of this software 1516c2ba93SPeter Wemm * must display the following acknowledgement: 1616c2ba93SPeter Wemm * This product includes software developed by TooLs GmbH. 1716c2ba93SPeter Wemm * 4. The name of TooLs GmbH may not be used to endorse or promote products 1816c2ba93SPeter Wemm * derived from this software without specific prior written permission. 1916c2ba93SPeter Wemm * 2016c2ba93SPeter Wemm * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 2116c2ba93SPeter Wemm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2216c2ba93SPeter Wemm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2316c2ba93SPeter Wemm * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2416c2ba93SPeter Wemm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2516c2ba93SPeter Wemm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2616c2ba93SPeter Wemm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2716c2ba93SPeter Wemm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2816c2ba93SPeter Wemm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2916c2ba93SPeter Wemm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3016c2ba93SPeter Wemm */ 3116c2ba93SPeter Wemm 32b728350eSDavid E. O'Brien #include <sys/cdefs.h> 33b728350eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 3416c2ba93SPeter Wemm 3516c2ba93SPeter Wemm #include <sys/param.h> 369f60cc9eSDag-Erling Smørgrav #include <sys/stdint.h> 3716c2ba93SPeter Wemm #include <sys/mount.h> 38386f1d1bSPoul-Henning Kamp #include <sys/disklabel.h> 3916c2ba93SPeter Wemm #include <sys/time.h> 401c85e6a3SKirk McKusick #include <ufs/ufs/dinode.h> 4116c2ba93SPeter Wemm #include <ufs/ffs/fs.h> 4216c2ba93SPeter Wemm 436980f0ebSPhilippe Charnier #include <err.h> 446980f0ebSPhilippe Charnier #include <fcntl.h> 4581f1ec27SPaul Saab #include <fstab.h> 466980f0ebSPhilippe Charnier #include <errno.h> 471a37aa56SDavid E. O'Brien #include <paths.h> 486980f0ebSPhilippe Charnier #include <pwd.h> 4916c2ba93SPeter Wemm #include <stdio.h> 5016c2ba93SPeter Wemm #include <stdlib.h> 5116c2ba93SPeter Wemm #include <string.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 * 1096980f0ebSPhilippe Charnier get_inode(fd,super,ino) 11057cdc152SMike Heffner int fd; 11116c2ba93SPeter Wemm struct fs *super; 11216c2ba93SPeter Wemm ino_t ino; 11316c2ba93SPeter Wemm { 1141c85e6a3SKirk McKusick static caddr_t ipbuf; 115bee3d34fSDavid Malone static struct cg *cgp; 11616c2ba93SPeter Wemm static ino_t last; 117bee3d34fSDavid Malone static int cg; 118bee3d34fSDavid Malone struct ufs2_dinode *di2; 11916c2ba93SPeter Wemm 12016c2ba93SPeter Wemm if (fd < 0) { /* flush cache */ 1211c85e6a3SKirk McKusick if (ipbuf) { 1221c85e6a3SKirk McKusick free(ipbuf); 1231c85e6a3SKirk McKusick ipbuf = 0; 124c433b438SMaxim Konovalov if (super != NULL && super->fs_magic == FS_UFS2_MAGIC) { 125bee3d34fSDavid Malone free(cgp); 126bee3d34fSDavid Malone cgp = 0; 127bee3d34fSDavid Malone } 12816c2ba93SPeter Wemm } 12916c2ba93SPeter Wemm return 0; 13016c2ba93SPeter Wemm } 13116c2ba93SPeter Wemm 1321c85e6a3SKirk McKusick if (!ipbuf || ino < last || ino >= last + INOCNT(super)) { 133bee3d34fSDavid Malone if (super->fs_magic == FS_UFS2_MAGIC && 134bee3d34fSDavid Malone (!cgp || cg != ino_to_cg(super, ino))) { 135bee3d34fSDavid Malone cg = ino_to_cg(super, ino); 136bee3d34fSDavid Malone if (!cgp && !(cgp = malloc(super->fs_cgsize))) 137bee3d34fSDavid Malone errx(1, "allocate cg"); 138bee3d34fSDavid Malone if (lseek(fd, (off_t)cgtod(super, cg) << super->fs_fshift, 0) < 0) 139bee3d34fSDavid Malone err(1, "lseek cg"); 140bee3d34fSDavid Malone if (read(fd, cgp, super->fs_cgsize) != super->fs_cgsize) 141bee3d34fSDavid Malone err(1, "read cg"); 142bee3d34fSDavid Malone if (!cg_chkmagic(cgp)) 143bee3d34fSDavid Malone errx(1, "cg has bad magic"); 144bee3d34fSDavid Malone } 1451c85e6a3SKirk McKusick if (!ipbuf 1461c85e6a3SKirk McKusick && !(ipbuf = malloc(INOSZ(super)))) 1476980f0ebSPhilippe Charnier errx(1, "allocate inodes"); 14816c2ba93SPeter Wemm last = (ino / INOCNT(super)) * INOCNT(super); 149c9d12677SJordan K. Hubbard if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0 1501c85e6a3SKirk McKusick || read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super)) 1516980f0ebSPhilippe Charnier err(1, "read inodes"); 15216c2ba93SPeter Wemm } 15316c2ba93SPeter Wemm 1541c85e6a3SKirk McKusick if (super->fs_magic == FS_UFS1_MAGIC) 1551c85e6a3SKirk McKusick return ((union dinode *) 1561c85e6a3SKirk McKusick &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]); 157bee3d34fSDavid Malone di2 = &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]; 158bee3d34fSDavid Malone /* If the inode is unused, it might be unallocated too, so zero it. */ 159bee3d34fSDavid Malone if (isclr(cg_inosused(cgp), ino % super->fs_ipg)) 160bee3d34fSDavid Malone bzero(di2, sizeof (*di2)); 161bee3d34fSDavid Malone return ((union dinode *)di2); 16216c2ba93SPeter Wemm } 16316c2ba93SPeter Wemm 16416c2ba93SPeter Wemm #ifdef COMPAT 1651c85e6a3SKirk McKusick #define actualblocks(fs, dp) (DIP(fs, dp, di_blocks) / 2) 16616c2ba93SPeter Wemm #else 1671c85e6a3SKirk McKusick #define actualblocks(fs, dp) DIP(fs, dp, di_blocks) 16816c2ba93SPeter Wemm #endif 16916c2ba93SPeter Wemm 1701c85e6a3SKirk McKusick static int virtualblocks(super, dp) 17116c2ba93SPeter Wemm struct fs *super; 1721c85e6a3SKirk McKusick union dinode *dp; 17316c2ba93SPeter Wemm { 17416c2ba93SPeter Wemm register off_t nblk, sz; 17516c2ba93SPeter Wemm 1761c85e6a3SKirk McKusick sz = DIP(super, dp, di_size); 17716c2ba93SPeter Wemm #ifdef COMPAT 17816c2ba93SPeter Wemm if (lblkno(super,sz) >= NDADDR) { 17916c2ba93SPeter Wemm nblk = blkroundup(super,sz); 18016c2ba93SPeter Wemm if (sz == nblk) 18116c2ba93SPeter Wemm nblk += super->fs_bsize; 18216c2ba93SPeter Wemm } 18316c2ba93SPeter Wemm 18416c2ba93SPeter Wemm return sz / 1024; 18516c2ba93SPeter Wemm 18616c2ba93SPeter Wemm #else /* COMPAT */ 18716c2ba93SPeter Wemm 18816c2ba93SPeter Wemm if (lblkno(super,sz) >= NDADDR) { 18916c2ba93SPeter Wemm nblk = blkroundup(super,sz); 19016c2ba93SPeter Wemm sz = lblkno(super,nblk); 19116c2ba93SPeter Wemm sz = (sz - NDADDR + NINDIR(super) - 1) / NINDIR(super); 19216c2ba93SPeter Wemm while (sz > 0) { 19316c2ba93SPeter Wemm nblk += sz * super->fs_bsize; 19416c2ba93SPeter Wemm /* sz - 1 rounded up */ 19516c2ba93SPeter Wemm sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super); 19616c2ba93SPeter Wemm } 19716c2ba93SPeter Wemm } else 19816c2ba93SPeter Wemm nblk = fragroundup(super,sz); 19916c2ba93SPeter Wemm 20016c2ba93SPeter Wemm return nblk / 512; 20116c2ba93SPeter Wemm #endif /* COMPAT */ 20216c2ba93SPeter Wemm } 20316c2ba93SPeter Wemm 2046980f0ebSPhilippe Charnier static int 2051c85e6a3SKirk McKusick isfree(super, dp) 2061c85e6a3SKirk McKusick struct fs *super; 2071c85e6a3SKirk McKusick union dinode *dp; 20816c2ba93SPeter Wemm { 20916c2ba93SPeter Wemm #ifdef COMPAT 2101c85e6a3SKirk McKusick return (DIP(super, dp, di_mode) & IFMT) == 0; 21116c2ba93SPeter Wemm #else /* COMPAT */ 21216c2ba93SPeter Wemm 2131c85e6a3SKirk McKusick switch (DIP(super, dp, di_mode) & IFMT) { 21416c2ba93SPeter Wemm case IFIFO: 21516c2ba93SPeter Wemm case IFLNK: /* should check FASTSYMLINK? */ 21616c2ba93SPeter Wemm case IFDIR: 21716c2ba93SPeter Wemm case IFREG: 21816c2ba93SPeter Wemm return 0; 219bee3d34fSDavid Malone case IFCHR: 220bee3d34fSDavid Malone case IFBLK: 221bee3d34fSDavid Malone case IFSOCK: 222bee3d34fSDavid Malone case IFWHT: 223bee3d34fSDavid Malone case 0: 22416c2ba93SPeter Wemm return 1; 225bee3d34fSDavid Malone default: 226bee3d34fSDavid Malone errx(1, "unknown IFMT 0%o", DIP(super, dp, di_mode) & IFMT); 22716c2ba93SPeter Wemm } 22816c2ba93SPeter Wemm #endif 22916c2ba93SPeter Wemm } 23016c2ba93SPeter Wemm 23116c2ba93SPeter Wemm static struct user { 23216c2ba93SPeter Wemm uid_t uid; 23316c2ba93SPeter Wemm char *name; 23416c2ba93SPeter Wemm daddr_t space; 23516c2ba93SPeter Wemm long count; 23616c2ba93SPeter Wemm daddr_t spc30; 23716c2ba93SPeter Wemm daddr_t spc60; 23816c2ba93SPeter Wemm daddr_t spc90; 23916c2ba93SPeter Wemm } *users; 24016c2ba93SPeter Wemm static int nusers; 24116c2ba93SPeter Wemm 2426980f0ebSPhilippe Charnier static void 2436980f0ebSPhilippe Charnier inituser() 24416c2ba93SPeter Wemm { 24557cdc152SMike Heffner register int i; 24616c2ba93SPeter Wemm register struct user *usr; 24716c2ba93SPeter Wemm 24816c2ba93SPeter Wemm if (!nusers) { 24916c2ba93SPeter Wemm nusers = 8; 25016c2ba93SPeter Wemm if (!(users = 2516980f0ebSPhilippe Charnier (struct user *)calloc(nusers,sizeof(struct user)))) 2526980f0ebSPhilippe Charnier errx(1, "allocate users"); 25316c2ba93SPeter Wemm } else { 25416c2ba93SPeter Wemm for (usr = users, i = nusers; --i >= 0; usr++) { 25516c2ba93SPeter Wemm usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0; 25616c2ba93SPeter Wemm usr->count = 0; 25716c2ba93SPeter Wemm } 25816c2ba93SPeter Wemm } 25916c2ba93SPeter Wemm } 26016c2ba93SPeter Wemm 2616980f0ebSPhilippe Charnier static void 2626980f0ebSPhilippe Charnier usrrehash() 26316c2ba93SPeter Wemm { 26457cdc152SMike Heffner register int i; 26516c2ba93SPeter Wemm register struct user *usr, *usrn; 26616c2ba93SPeter Wemm struct user *svusr; 26716c2ba93SPeter Wemm 26816c2ba93SPeter Wemm svusr = users; 26916c2ba93SPeter Wemm nusers <<= 1; 2706980f0ebSPhilippe Charnier if (!(users = (struct user *)calloc(nusers,sizeof(struct user)))) 2716980f0ebSPhilippe Charnier errx(1, "allocate users"); 27216c2ba93SPeter Wemm for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) { 27316c2ba93SPeter Wemm for (usrn = users + (usr->uid&(nusers - 1)); usrn->name; 27416c2ba93SPeter Wemm usrn--) { 27516c2ba93SPeter Wemm if (usrn <= users) 27616c2ba93SPeter Wemm usrn = users + nusers; 27716c2ba93SPeter Wemm } 27816c2ba93SPeter Wemm *usrn = *usr; 27916c2ba93SPeter Wemm } 28016c2ba93SPeter Wemm } 28116c2ba93SPeter Wemm 2826980f0ebSPhilippe Charnier static struct user * 2836980f0ebSPhilippe Charnier user(uid) 28416c2ba93SPeter Wemm uid_t uid; 28516c2ba93SPeter Wemm { 28616c2ba93SPeter Wemm register struct user *usr; 28757cdc152SMike Heffner register int i; 28816c2ba93SPeter Wemm struct passwd *pwd; 28916c2ba93SPeter Wemm 29016c2ba93SPeter Wemm while (1) { 29116c2ba93SPeter Wemm for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0; 29216c2ba93SPeter Wemm usr--) { 29316c2ba93SPeter Wemm if (!usr->name) { 29416c2ba93SPeter Wemm usr->uid = uid; 29516c2ba93SPeter Wemm 29616c2ba93SPeter Wemm if (!(pwd = getpwuid(uid))) { 2976980f0ebSPhilippe Charnier if ((usr->name = (char *)malloc(7))) 29816c2ba93SPeter Wemm sprintf(usr->name,"#%d",uid); 29916c2ba93SPeter Wemm } else { 3006980f0ebSPhilippe Charnier if ((usr->name = (char *) 3016980f0ebSPhilippe Charnier malloc(strlen(pwd->pw_name) + 1))) 30216c2ba93SPeter Wemm strcpy(usr->name,pwd->pw_name); 30316c2ba93SPeter Wemm } 3046980f0ebSPhilippe Charnier if (!usr->name) 3056980f0ebSPhilippe Charnier errx(1, "allocate users"); 30616c2ba93SPeter Wemm 30716c2ba93SPeter Wemm return usr; 30816c2ba93SPeter Wemm 30916c2ba93SPeter Wemm } else if (usr->uid == uid) 31016c2ba93SPeter Wemm return usr; 31116c2ba93SPeter Wemm 31216c2ba93SPeter Wemm if (usr <= users) 31316c2ba93SPeter Wemm usr = users + nusers; 31416c2ba93SPeter Wemm } 31516c2ba93SPeter Wemm usrrehash(); 31616c2ba93SPeter Wemm } 31716c2ba93SPeter Wemm } 31816c2ba93SPeter Wemm 3196980f0ebSPhilippe Charnier static int 32057cdc152SMike Heffner cmpusers(v1,v2) 32157cdc152SMike Heffner const void *v1, *v2; 32216c2ba93SPeter Wemm { 32357cdc152SMike Heffner const struct user *u1, *u2; 32457cdc152SMike Heffner u1 = (const struct user *)v1; 32557cdc152SMike Heffner u2 = (const struct user *)v2; 32657cdc152SMike Heffner 32716c2ba93SPeter Wemm return u2->space - u1->space; 32816c2ba93SPeter Wemm } 32916c2ba93SPeter Wemm 33016c2ba93SPeter Wemm #define sortusers(users) (qsort((users),nusers,sizeof(struct user), \ 33116c2ba93SPeter Wemm cmpusers)) 33216c2ba93SPeter Wemm 3336980f0ebSPhilippe Charnier static void 3346980f0ebSPhilippe Charnier uses(uid,blks,act) 33516c2ba93SPeter Wemm uid_t uid; 33616c2ba93SPeter Wemm daddr_t blks; 33716c2ba93SPeter Wemm time_t act; 33816c2ba93SPeter Wemm { 33916c2ba93SPeter Wemm static time_t today; 34016c2ba93SPeter Wemm register struct user *usr; 34116c2ba93SPeter Wemm 34216c2ba93SPeter Wemm if (!today) 34316c2ba93SPeter Wemm time(&today); 34416c2ba93SPeter Wemm 34516c2ba93SPeter Wemm usr = user(uid); 34616c2ba93SPeter Wemm usr->count++; 34716c2ba93SPeter Wemm usr->space += blks; 34816c2ba93SPeter Wemm 34916c2ba93SPeter Wemm if (today - act > 90L * 24L * 60L * 60L) 35016c2ba93SPeter Wemm usr->spc90 += blks; 35116c2ba93SPeter Wemm if (today - act > 60L * 24L * 60L * 60L) 35216c2ba93SPeter Wemm usr->spc60 += blks; 35316c2ba93SPeter Wemm if (today - act > 30L * 24L * 60L * 60L) 35416c2ba93SPeter Wemm usr->spc30 += blks; 35516c2ba93SPeter Wemm } 35616c2ba93SPeter Wemm 35716c2ba93SPeter Wemm #ifdef COMPAT 35816c2ba93SPeter Wemm #define FSZCNT 500 35916c2ba93SPeter Wemm #else 36016c2ba93SPeter Wemm #define FSZCNT 512 36116c2ba93SPeter Wemm #endif 36216c2ba93SPeter Wemm struct fsizes { 36316c2ba93SPeter Wemm struct fsizes *fsz_next; 36416c2ba93SPeter Wemm daddr_t fsz_first, fsz_last; 36516c2ba93SPeter Wemm ino_t fsz_count[FSZCNT]; 36616c2ba93SPeter Wemm daddr_t fsz_sz[FSZCNT]; 36716c2ba93SPeter Wemm } *fsizes; 36816c2ba93SPeter Wemm 3696980f0ebSPhilippe Charnier static void 3706980f0ebSPhilippe Charnier initfsizes() 37116c2ba93SPeter Wemm { 37216c2ba93SPeter Wemm register struct fsizes *fp; 37357cdc152SMike Heffner register int i; 37416c2ba93SPeter Wemm 37516c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) { 37616c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) { 37716c2ba93SPeter Wemm fp->fsz_count[i] = 0; 37816c2ba93SPeter Wemm fp->fsz_sz[i] = 0; 37916c2ba93SPeter Wemm } 38016c2ba93SPeter Wemm } 38116c2ba93SPeter Wemm } 38216c2ba93SPeter Wemm 3836980f0ebSPhilippe Charnier static void 3846980f0ebSPhilippe Charnier dofsizes(fd, super, name) 38557cdc152SMike Heffner int fd; 38616c2ba93SPeter Wemm struct fs *super; 38716c2ba93SPeter Wemm char *name; 38816c2ba93SPeter Wemm { 38916c2ba93SPeter Wemm ino_t inode, maxino; 3901c85e6a3SKirk McKusick union dinode *dp; 39116c2ba93SPeter Wemm daddr_t sz, ksz; 39216c2ba93SPeter Wemm struct fsizes *fp, **fsp; 39357cdc152SMike Heffner register int i; 39416c2ba93SPeter Wemm 39516c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 39616c2ba93SPeter Wemm #ifdef COMPAT 3976980f0ebSPhilippe Charnier if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes)))) 398652b7200SPhilippe Charnier errx(1, "allocate fsize structure"); 39916c2ba93SPeter Wemm #endif /* COMPAT */ 40016c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) { 40116c2ba93SPeter Wemm errno = 0; 4021c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 40316c2ba93SPeter Wemm #ifdef COMPAT 4041c85e6a3SKirk McKusick && ((DIP(super, dp, di_mode) & IFMT) == IFREG 4051c85e6a3SKirk McKusick || (DIP(super, dp, di_mode) & IFMT) == IFDIR) 40616c2ba93SPeter Wemm #else /* COMPAT */ 4071c85e6a3SKirk McKusick && !isfree(super, dp) 40816c2ba93SPeter Wemm #endif /* COMPAT */ 40916c2ba93SPeter Wemm ) { 4101c85e6a3SKirk McKusick sz = estimate ? virtualblocks(super, dp) : 4111c85e6a3SKirk McKusick actualblocks(super, dp); 41216c2ba93SPeter Wemm #ifdef COMPAT 41316c2ba93SPeter Wemm if (sz >= FSZCNT) { 41416c2ba93SPeter Wemm fsizes->fsz_count[FSZCNT-1]++; 41516c2ba93SPeter Wemm fsizes->fsz_sz[FSZCNT-1] += sz; 41616c2ba93SPeter Wemm } else { 41716c2ba93SPeter Wemm fsizes->fsz_count[sz]++; 41816c2ba93SPeter Wemm fsizes->fsz_sz[sz] += sz; 41916c2ba93SPeter Wemm } 42016c2ba93SPeter Wemm #else /* COMPAT */ 42116c2ba93SPeter Wemm ksz = SIZE(sz); 4226980f0ebSPhilippe Charnier for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) { 42316c2ba93SPeter Wemm if (ksz < fp->fsz_last) 42416c2ba93SPeter Wemm break; 42516c2ba93SPeter Wemm } 42616c2ba93SPeter Wemm if (!fp || ksz < fp->fsz_first) { 42716c2ba93SPeter Wemm if (!(fp = (struct fsizes *) 4286980f0ebSPhilippe Charnier malloc(sizeof(struct fsizes)))) 429652b7200SPhilippe Charnier errx(1, "allocate fsize structure"); 43016c2ba93SPeter Wemm fp->fsz_next = *fsp; 43116c2ba93SPeter Wemm *fsp = fp; 43216c2ba93SPeter Wemm fp->fsz_first = (ksz / FSZCNT) * FSZCNT; 43316c2ba93SPeter Wemm fp->fsz_last = fp->fsz_first + FSZCNT; 43416c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) { 43516c2ba93SPeter Wemm fp->fsz_count[i] = 0; 43616c2ba93SPeter Wemm fp->fsz_sz[i] = 0; 43716c2ba93SPeter Wemm } 43816c2ba93SPeter Wemm } 43916c2ba93SPeter Wemm fp->fsz_count[ksz % FSZCNT]++; 44016c2ba93SPeter Wemm fp->fsz_sz[ksz % FSZCNT] += sz; 44116c2ba93SPeter Wemm #endif /* COMPAT */ 44216c2ba93SPeter Wemm } else if (errno) { 4436980f0ebSPhilippe Charnier err(1, "%s", name); 44416c2ba93SPeter Wemm } 44516c2ba93SPeter Wemm } 44616c2ba93SPeter Wemm sz = 0; 44716c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) { 44816c2ba93SPeter Wemm for (i = 0; i < FSZCNT; i++) { 44916c2ba93SPeter Wemm if (fp->fsz_count[i]) 4509f60cc9eSDag-Erling Smørgrav printf("%jd\t%jd\t%d\n", 4519f60cc9eSDag-Erling Smørgrav (intmax_t)(fp->fsz_first + i), 4529f60cc9eSDag-Erling Smørgrav (intmax_t)fp->fsz_count[i], 45316c2ba93SPeter Wemm SIZE(sz += fp->fsz_sz[i])); 45416c2ba93SPeter Wemm } 45516c2ba93SPeter Wemm } 45616c2ba93SPeter Wemm } 45716c2ba93SPeter Wemm 4586980f0ebSPhilippe Charnier static void 4596980f0ebSPhilippe Charnier douser(fd, super, name) 46057cdc152SMike Heffner int fd; 46116c2ba93SPeter Wemm struct fs *super; 46216c2ba93SPeter Wemm char *name; 46316c2ba93SPeter Wemm { 46416c2ba93SPeter Wemm ino_t inode, maxino; 46516c2ba93SPeter Wemm struct user *usr, *usrs; 4661c85e6a3SKirk McKusick union dinode *dp; 46757cdc152SMike Heffner register int n; 46816c2ba93SPeter Wemm 46916c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 47016c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) { 47116c2ba93SPeter Wemm errno = 0; 4721c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 4731c85e6a3SKirk McKusick && !isfree(super, dp)) 4741c85e6a3SKirk McKusick uses(DIP(super, dp, di_uid), 4751c85e6a3SKirk McKusick estimate ? virtualblocks(super, dp) : 4761c85e6a3SKirk McKusick actualblocks(super, dp), 4771c85e6a3SKirk McKusick DIP(super, dp, di_atime)); 47816c2ba93SPeter Wemm else if (errno) { 4796980f0ebSPhilippe Charnier err(1, "%s", name); 48016c2ba93SPeter Wemm } 48116c2ba93SPeter Wemm } 4826980f0ebSPhilippe Charnier if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user)))) 4836980f0ebSPhilippe Charnier errx(1, "allocate users"); 48416c2ba93SPeter Wemm bcopy(users,usrs,nusers * sizeof(struct user)); 48516c2ba93SPeter Wemm sortusers(usrs); 48616c2ba93SPeter Wemm for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) { 48716c2ba93SPeter Wemm printf("%5d",SIZE(usr->space)); 48816c2ba93SPeter Wemm if (count) 48957cdc152SMike Heffner printf("\t%5ld",usr->count); 49016c2ba93SPeter Wemm printf("\t%-8s",usr->name); 49116c2ba93SPeter Wemm if (unused) 49216c2ba93SPeter Wemm printf("\t%5d\t%5d\t%5d", 49316c2ba93SPeter Wemm SIZE(usr->spc30), 49416c2ba93SPeter Wemm SIZE(usr->spc60), 49516c2ba93SPeter Wemm SIZE(usr->spc90)); 49616c2ba93SPeter Wemm printf("\n"); 49716c2ba93SPeter Wemm } 49816c2ba93SPeter Wemm free(usrs); 49916c2ba93SPeter Wemm } 50016c2ba93SPeter Wemm 5016980f0ebSPhilippe Charnier static void 5026980f0ebSPhilippe Charnier donames(fd, super, name) 50357cdc152SMike Heffner int fd; 50416c2ba93SPeter Wemm struct fs *super; 50516c2ba93SPeter Wemm char *name; 50616c2ba93SPeter Wemm { 50716c2ba93SPeter Wemm int c; 50818b51f79SStefan Farfeleder ino_t inode; 50916c2ba93SPeter Wemm ino_t maxino; 5101c85e6a3SKirk McKusick union dinode *dp; 51116c2ba93SPeter Wemm 51216c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 51316c2ba93SPeter Wemm /* first skip the name of the filesystem */ 51416c2ba93SPeter Wemm while ((c = getchar()) != EOF && (c < '0' || c > '9')) 51516c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n'); 51616c2ba93SPeter Wemm ungetc(c,stdin); 51757cdc152SMike Heffner while (scanf("%u",&inode) == 1) { 51857cdc152SMike Heffner if (inode > maxino) { 5196980f0ebSPhilippe Charnier warnx("illegal inode %d",inode); 52016c2ba93SPeter Wemm return; 52116c2ba93SPeter Wemm } 52216c2ba93SPeter Wemm errno = 0; 5231c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 5241c85e6a3SKirk McKusick && !isfree(super, dp)) { 5251c85e6a3SKirk McKusick printf("%s\t",user(DIP(super, dp, di_uid))->name); 52616c2ba93SPeter Wemm /* now skip whitespace */ 52716c2ba93SPeter Wemm while ((c = getchar()) == ' ' || c == '\t'); 52816c2ba93SPeter Wemm /* and print out the remainder of the input line */ 52916c2ba93SPeter Wemm while (c != EOF && c != '\n') { 53016c2ba93SPeter Wemm putchar(c); 53116c2ba93SPeter Wemm c = getchar(); 53216c2ba93SPeter Wemm } 53316c2ba93SPeter Wemm putchar('\n'); 53416c2ba93SPeter Wemm } else { 53516c2ba93SPeter Wemm if (errno) { 5366980f0ebSPhilippe Charnier err(1, "%s", name); 53716c2ba93SPeter Wemm } 53816c2ba93SPeter Wemm /* skip this line */ 53916c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n'); 54016c2ba93SPeter Wemm } 54116c2ba93SPeter Wemm if (c == EOF) 54216c2ba93SPeter Wemm break; 54316c2ba93SPeter Wemm } 54416c2ba93SPeter Wemm } 54516c2ba93SPeter Wemm 5466980f0ebSPhilippe Charnier static void 5476980f0ebSPhilippe Charnier usage() 54816c2ba93SPeter Wemm { 54916c2ba93SPeter Wemm #ifdef COMPAT 5506980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n"); 55116c2ba93SPeter Wemm #else /* COMPAT */ 5526980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n"); 55316c2ba93SPeter Wemm #endif /* COMPAT */ 55416c2ba93SPeter Wemm exit(1); 55516c2ba93SPeter Wemm } 55616c2ba93SPeter Wemm 5571c85e6a3SKirk McKusick /* 5581c85e6a3SKirk McKusick * Possible superblock locations ordered from most to least likely. 5591c85e6a3SKirk McKusick */ 5601c85e6a3SKirk McKusick static int sblock_try[] = SBLOCKSEARCH; 5611c85e6a3SKirk McKusick static char superblock[SBLOCKSIZE]; 56216c2ba93SPeter Wemm 5636980f0ebSPhilippe Charnier void 56416c2ba93SPeter Wemm quot(name,mp) 56516c2ba93SPeter Wemm char *name, *mp; 56616c2ba93SPeter Wemm { 5671c85e6a3SKirk McKusick int i, fd; 5681c85e6a3SKirk McKusick struct fs *fs; 56916c2ba93SPeter Wemm 57057cdc152SMike Heffner get_inode(-1, NULL, 0); /* flush cache */ 57116c2ba93SPeter Wemm inituser(); 57216c2ba93SPeter Wemm initfsizes(); 5731c85e6a3SKirk McKusick if ((fd = open(name,0)) < 0) { 5746980f0ebSPhilippe Charnier warn("%s", name); 57516c2ba93SPeter Wemm close(fd); 57616c2ba93SPeter Wemm return; 57716c2ba93SPeter Wemm } 5781c85e6a3SKirk McKusick for (i = 0; sblock_try[i] != -1; i++) { 5791c85e6a3SKirk McKusick if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) { 5801c85e6a3SKirk McKusick close(fd); 5811c85e6a3SKirk McKusick return; 5821c85e6a3SKirk McKusick } 5831c85e6a3SKirk McKusick if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) { 5841c85e6a3SKirk McKusick close(fd); 5851c85e6a3SKirk McKusick return; 5861c85e6a3SKirk McKusick } 5871c85e6a3SKirk McKusick fs = (struct fs *)superblock; 5881c85e6a3SKirk McKusick if ((fs->fs_magic == FS_UFS1_MAGIC || 5891c85e6a3SKirk McKusick (fs->fs_magic == FS_UFS2_MAGIC && 5906c45bec6STim J. Robbins fs->fs_sblockloc == sblock_try[i])) && 5911c85e6a3SKirk McKusick fs->fs_bsize <= MAXBSIZE && 5921c85e6a3SKirk McKusick fs->fs_bsize >= sizeof(struct fs)) 5931c85e6a3SKirk McKusick break; 5941c85e6a3SKirk McKusick } 5951c85e6a3SKirk McKusick if (sblock_try[i] == -1) { 5966980f0ebSPhilippe Charnier warnx("%s: not a BSD filesystem",name); 59716c2ba93SPeter Wemm close(fd); 59816c2ba93SPeter Wemm return; 59916c2ba93SPeter Wemm } 60016c2ba93SPeter Wemm printf("%s:",name); 60116c2ba93SPeter Wemm if (mp) 60216c2ba93SPeter Wemm printf(" (%s)",mp); 60316c2ba93SPeter Wemm putchar('\n'); 6041c85e6a3SKirk McKusick (*func)(fd, fs, name); 60516c2ba93SPeter Wemm close(fd); 60616c2ba93SPeter Wemm } 60716c2ba93SPeter Wemm 6086980f0ebSPhilippe Charnier int 6096980f0ebSPhilippe Charnier main(argc,argv) 61057cdc152SMike Heffner int argc; 61116c2ba93SPeter Wemm char **argv; 61216c2ba93SPeter Wemm { 61316c2ba93SPeter Wemm char all = 0; 61416c2ba93SPeter Wemm struct statfs *mp; 61581f1ec27SPaul Saab struct fstab *fs; 61616c2ba93SPeter Wemm char dev[MNAMELEN + 1]; 61716c2ba93SPeter Wemm char *nm; 61816c2ba93SPeter Wemm int cnt; 61916c2ba93SPeter Wemm 62016c2ba93SPeter Wemm func = douser; 62116c2ba93SPeter Wemm #ifndef COMPAT 62216c2ba93SPeter Wemm header = getbsize(&headerlen,&blocksize); 62316c2ba93SPeter Wemm #endif 62416c2ba93SPeter Wemm while (--argc > 0 && **++argv == '-') { 62516c2ba93SPeter Wemm while (*++*argv) { 62616c2ba93SPeter Wemm switch (**argv) { 62716c2ba93SPeter Wemm case 'n': 62816c2ba93SPeter Wemm func = donames; 62916c2ba93SPeter Wemm break; 63016c2ba93SPeter Wemm case 'c': 63116c2ba93SPeter Wemm func = dofsizes; 63216c2ba93SPeter Wemm break; 63316c2ba93SPeter Wemm case 'a': 63416c2ba93SPeter Wemm all = 1; 63516c2ba93SPeter Wemm break; 63616c2ba93SPeter Wemm case 'f': 63716c2ba93SPeter Wemm count = 1; 63816c2ba93SPeter Wemm break; 63916c2ba93SPeter Wemm case 'h': 64016c2ba93SPeter Wemm estimate = 1; 64116c2ba93SPeter Wemm break; 64216c2ba93SPeter Wemm #ifndef COMPAT 64316c2ba93SPeter Wemm case 'k': 64416c2ba93SPeter Wemm blocksize = 1024; 64516c2ba93SPeter Wemm break; 64616c2ba93SPeter Wemm #endif /* COMPAT */ 64716c2ba93SPeter Wemm case 'v': 64816c2ba93SPeter Wemm unused = 1; 64916c2ba93SPeter Wemm break; 65016c2ba93SPeter Wemm default: 65116c2ba93SPeter Wemm usage(); 65216c2ba93SPeter Wemm } 65316c2ba93SPeter Wemm } 65416c2ba93SPeter Wemm } 65516c2ba93SPeter Wemm if (all) { 65616c2ba93SPeter Wemm cnt = getmntinfo(&mp,MNT_NOWAIT); 65716c2ba93SPeter Wemm for (; --cnt >= 0; mp++) { 658b49d184bSBruce Evans if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) { 6596980f0ebSPhilippe Charnier if ((nm = strrchr(mp->f_mntfromname,'/'))) { 6601a37aa56SDavid E. O'Brien sprintf(dev,"%s%s",_PATH_DEV,nm + 1); 66116c2ba93SPeter Wemm nm = dev; 66216c2ba93SPeter Wemm } else 66316c2ba93SPeter Wemm nm = mp->f_mntfromname; 66416c2ba93SPeter Wemm quot(nm,mp->f_mntonname); 66516c2ba93SPeter Wemm } 66616c2ba93SPeter Wemm } 66716c2ba93SPeter Wemm } 66881f1ec27SPaul Saab while (--argc >= 0) { 66981f1ec27SPaul Saab if ((fs = getfsfile(*argv)) != NULL) 67081f1ec27SPaul Saab quot(fs->fs_spec, 0); 67181f1ec27SPaul Saab else 67281f1ec27SPaul Saab quot(*argv,0); 67381f1ec27SPaul Saab argv++; 67481f1ec27SPaul Saab } 67516c2ba93SPeter Wemm return 0; 67616c2ba93SPeter Wemm } 677