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 * 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"); 14516c2ba93SPeter Wemm last = (ino / INOCNT(super)) * 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 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 17316c2ba93SPeter Wemm if (lblkno(super,sz) >= 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 18316c2ba93SPeter Wemm if (lblkno(super,sz) >= NDADDR) { 18416c2ba93SPeter Wemm nblk = blkroundup(super,sz); 18516c2ba93SPeter Wemm sz = lblkno(super,nblk); 18616c2ba93SPeter Wemm sz = (sz - 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 2008f518424SDag-Erling Smørgrav isfree(struct fs *super, union dinode *dp) 20116c2ba93SPeter Wemm { 20216c2ba93SPeter Wemm #ifdef COMPAT 2031c85e6a3SKirk McKusick return (DIP(super, dp, di_mode) & IFMT) == 0; 20416c2ba93SPeter Wemm #else /* COMPAT */ 20516c2ba93SPeter Wemm 2061c85e6a3SKirk McKusick switch (DIP(super, dp, di_mode) & IFMT) { 20716c2ba93SPeter Wemm case IFIFO: 20816c2ba93SPeter Wemm case IFLNK: /* should check FASTSYMLINK? */ 20916c2ba93SPeter Wemm case IFDIR: 21016c2ba93SPeter Wemm case IFREG: 21116c2ba93SPeter Wemm return 0; 212bee3d34fSDavid Malone case IFCHR: 213bee3d34fSDavid Malone case IFBLK: 214bee3d34fSDavid Malone case IFSOCK: 215bee3d34fSDavid Malone case IFWHT: 216bee3d34fSDavid Malone case 0: 21716c2ba93SPeter Wemm return 1; 218bee3d34fSDavid Malone default: 219bee3d34fSDavid Malone 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 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 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 * 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 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 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 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 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 3891c85e6a3SKirk McKusick && ((DIP(super, dp, di_mode) & IFMT) == IFREG 3901c85e6a3SKirk McKusick || (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; 41716c2ba93SPeter Wemm fp->fsz_first = (ksz / FSZCNT) * 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 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 4848f518424SDag-Erling Smørgrav donames(int fd, struct fs *super, char *name) 48516c2ba93SPeter Wemm { 48616c2ba93SPeter Wemm int c; 48718b51f79SStefan Farfeleder ino_t inode; 48816c2ba93SPeter Wemm ino_t maxino; 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); 49657cdc152SMike Heffner while (scanf("%u",&inode) == 1) { 49757cdc152SMike Heffner if (inode > maxino) { 4986980f0ebSPhilippe Charnier warnx("illegal inode %d",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 5268f518424SDag-Erling Smørgrav usage(void) 52716c2ba93SPeter Wemm { 52816c2ba93SPeter Wemm #ifdef COMPAT 5296980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n"); 53016c2ba93SPeter Wemm #else /* COMPAT */ 5316980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n"); 53216c2ba93SPeter Wemm #endif /* COMPAT */ 53316c2ba93SPeter Wemm exit(1); 53416c2ba93SPeter Wemm } 53516c2ba93SPeter Wemm 5361c85e6a3SKirk McKusick /* 5371c85e6a3SKirk McKusick * Possible superblock locations ordered from most to least likely. 5381c85e6a3SKirk McKusick */ 5391c85e6a3SKirk McKusick static int sblock_try[] = SBLOCKSEARCH; 5401c85e6a3SKirk McKusick static char superblock[SBLOCKSIZE]; 54116c2ba93SPeter Wemm 5426980f0ebSPhilippe Charnier void 5438f518424SDag-Erling Smørgrav quot(char *name, char *mp) 54416c2ba93SPeter Wemm { 5451c85e6a3SKirk McKusick int i, fd; 5461c85e6a3SKirk McKusick struct fs *fs; 54716c2ba93SPeter Wemm 54857cdc152SMike Heffner get_inode(-1, NULL, 0); /* flush cache */ 54916c2ba93SPeter Wemm inituser(); 55016c2ba93SPeter Wemm initfsizes(); 5511c85e6a3SKirk McKusick if ((fd = open(name,0)) < 0) { 5526980f0ebSPhilippe Charnier warn("%s", name); 55316c2ba93SPeter Wemm close(fd); 55416c2ba93SPeter Wemm return; 55516c2ba93SPeter Wemm } 5561c85e6a3SKirk McKusick for (i = 0; sblock_try[i] != -1; i++) { 5571c85e6a3SKirk McKusick if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) { 5581c85e6a3SKirk McKusick close(fd); 5591c85e6a3SKirk McKusick return; 5601c85e6a3SKirk McKusick } 5611c85e6a3SKirk McKusick if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) { 5621c85e6a3SKirk McKusick close(fd); 5631c85e6a3SKirk McKusick return; 5641c85e6a3SKirk McKusick } 5651c85e6a3SKirk McKusick fs = (struct fs *)superblock; 5661c85e6a3SKirk McKusick if ((fs->fs_magic == FS_UFS1_MAGIC || 5671c85e6a3SKirk McKusick (fs->fs_magic == FS_UFS2_MAGIC && 5686c45bec6STim J. Robbins fs->fs_sblockloc == sblock_try[i])) && 5691c85e6a3SKirk McKusick fs->fs_bsize <= MAXBSIZE && 5701c85e6a3SKirk McKusick fs->fs_bsize >= sizeof(struct fs)) 5711c85e6a3SKirk McKusick break; 5721c85e6a3SKirk McKusick } 5731c85e6a3SKirk McKusick if (sblock_try[i] == -1) { 5746980f0ebSPhilippe Charnier warnx("%s: not a BSD filesystem",name); 57516c2ba93SPeter Wemm close(fd); 57616c2ba93SPeter Wemm return; 57716c2ba93SPeter Wemm } 57816c2ba93SPeter Wemm printf("%s:",name); 57916c2ba93SPeter Wemm if (mp) 58016c2ba93SPeter Wemm printf(" (%s)",mp); 58116c2ba93SPeter Wemm putchar('\n'); 5821c85e6a3SKirk McKusick (*func)(fd, fs, name); 58316c2ba93SPeter Wemm close(fd); 58416c2ba93SPeter Wemm } 58516c2ba93SPeter Wemm 5866980f0ebSPhilippe Charnier int 5878f518424SDag-Erling Smørgrav main(int argc, char *argv[]) 58816c2ba93SPeter Wemm { 58916c2ba93SPeter Wemm char all = 0; 59016c2ba93SPeter Wemm struct statfs *mp; 59181f1ec27SPaul Saab struct fstab *fs; 59216c2ba93SPeter Wemm int cnt; 59316c2ba93SPeter Wemm 59416c2ba93SPeter Wemm func = douser; 59516c2ba93SPeter Wemm #ifndef COMPAT 59616c2ba93SPeter Wemm header = getbsize(&headerlen,&blocksize); 59716c2ba93SPeter Wemm #endif 59816c2ba93SPeter Wemm while (--argc > 0 && **++argv == '-') { 59916c2ba93SPeter Wemm while (*++*argv) { 60016c2ba93SPeter Wemm switch (**argv) { 60116c2ba93SPeter Wemm case 'n': 60216c2ba93SPeter Wemm func = donames; 60316c2ba93SPeter Wemm break; 60416c2ba93SPeter Wemm case 'c': 60516c2ba93SPeter Wemm func = dofsizes; 60616c2ba93SPeter Wemm break; 60716c2ba93SPeter Wemm case 'a': 60816c2ba93SPeter Wemm all = 1; 60916c2ba93SPeter Wemm break; 61016c2ba93SPeter Wemm case 'f': 61116c2ba93SPeter Wemm count = 1; 61216c2ba93SPeter Wemm break; 61316c2ba93SPeter Wemm case 'h': 61416c2ba93SPeter Wemm estimate = 1; 61516c2ba93SPeter Wemm break; 61616c2ba93SPeter Wemm #ifndef COMPAT 61716c2ba93SPeter Wemm case 'k': 61816c2ba93SPeter Wemm blocksize = 1024; 61916c2ba93SPeter Wemm break; 62016c2ba93SPeter Wemm #endif /* COMPAT */ 62116c2ba93SPeter Wemm case 'v': 62216c2ba93SPeter Wemm unused = 1; 62316c2ba93SPeter Wemm break; 62416c2ba93SPeter Wemm default: 62516c2ba93SPeter Wemm usage(); 62616c2ba93SPeter Wemm } 62716c2ba93SPeter Wemm } 62816c2ba93SPeter Wemm } 62916c2ba93SPeter Wemm if (all) { 63016c2ba93SPeter Wemm cnt = getmntinfo(&mp,MNT_NOWAIT); 63116c2ba93SPeter Wemm for (; --cnt >= 0; mp++) { 632b4eca767SEd Schouten if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) 633b4eca767SEd Schouten quot(mp->f_mntfromname, mp->f_mntonname); 63416c2ba93SPeter Wemm } 63516c2ba93SPeter Wemm } 63681f1ec27SPaul Saab while (--argc >= 0) { 63781f1ec27SPaul Saab if ((fs = getfsfile(*argv)) != NULL) 63881f1ec27SPaul Saab quot(fs->fs_spec, 0); 63981f1ec27SPaul Saab else 64081f1ec27SPaul Saab quot(*argv,0); 64181f1ec27SPaul Saab argv++; 64281f1ec27SPaul Saab } 64316c2ba93SPeter Wemm return 0; 64416c2ba93SPeter Wemm } 645