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 34b728350eSDavid E. O'Brien #include <sys/cdefs.h> 35b728350eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 3616c2ba93SPeter Wemm 3716c2ba93SPeter Wemm #include <sys/param.h> 389f60cc9eSDag-Erling Smørgrav #include <sys/stdint.h> 3916c2ba93SPeter Wemm #include <sys/mount.h> 40386f1d1bSPoul-Henning Kamp #include <sys/disklabel.h> 411c85e6a3SKirk McKusick #include <ufs/ufs/dinode.h> 4216c2ba93SPeter Wemm #include <ufs/ffs/fs.h> 4316c2ba93SPeter Wemm 446980f0ebSPhilippe Charnier #include <err.h> 456980f0ebSPhilippe Charnier #include <fcntl.h> 4681f1ec27SPaul Saab #include <fstab.h> 476980f0ebSPhilippe Charnier #include <errno.h> 48dffce215SKirk McKusick #include <libufs.h> 491a37aa56SDavid E. O'Brien #include <paths.h> 506980f0ebSPhilippe Charnier #include <pwd.h> 5116c2ba93SPeter Wemm #include <stdio.h> 5216c2ba93SPeter Wemm #include <stdlib.h> 5316c2ba93SPeter Wemm #include <string.h> 547649cb00SKirk McKusick #include <time.h> 556980f0ebSPhilippe Charnier #include <unistd.h> 5616c2ba93SPeter Wemm 5716c2ba93SPeter Wemm /* some flags of what to do: */ 5816c2ba93SPeter Wemm static char estimate; 5916c2ba93SPeter Wemm static char count; 6016c2ba93SPeter Wemm static char unused; 6157cdc152SMike Heffner static void (*func)(int, struct fs *, char *); 6216c2ba93SPeter Wemm static long blocksize; 6316c2ba93SPeter Wemm static char *header; 64bc6ba9aeSMike Barcroft static int headerlen; 6516c2ba93SPeter Wemm 661c85e6a3SKirk McKusick static union dinode *get_inode(int, struct fs *, ino_t); 671c85e6a3SKirk McKusick static int virtualblocks(struct fs *, union dinode *); 681c85e6a3SKirk McKusick static int isfree(struct fs *, union dinode *); 6957cdc152SMike Heffner static void inituser(void); 7057cdc152SMike Heffner static void usrrehash(void); 7157cdc152SMike Heffner static struct user *user(uid_t); 7257cdc152SMike Heffner static int cmpusers(const void *, const void *); 7357cdc152SMike Heffner static void uses(uid_t, daddr_t, time_t); 7457cdc152SMike Heffner static void initfsizes(void); 7557cdc152SMike Heffner static void dofsizes(int, struct fs *, char *); 7657cdc152SMike Heffner static void douser(int, struct fs *, char *); 7757cdc152SMike Heffner static void donames(int, struct fs *, char *); 7857cdc152SMike Heffner static void usage(void); 7957cdc152SMike Heffner static void quot(char *, char *); 8057cdc152SMike Heffner 8116c2ba93SPeter Wemm /* 8216c2ba93SPeter Wemm * Original BSD quot doesn't round to number of frags/blocks, 8316c2ba93SPeter Wemm * doesn't account for indirection blocks and gets it totally 8416c2ba93SPeter Wemm * wrong if the size is a multiple of the blocksize. 8516c2ba93SPeter Wemm * The new code always counts the number of 512 byte blocks 8616c2ba93SPeter Wemm * instead of the number of kilobytes and converts them to 8716c2ba93SPeter Wemm * kByte when done (on request). 889983067eSMatthew Dillon * 899983067eSMatthew Dillon * Due to the size of modern disks, we must cast intermediate 909983067eSMatthew Dillon * values to 64 bits to prevent potential overflows. 9116c2ba93SPeter Wemm */ 9216c2ba93SPeter Wemm #ifdef COMPAT 9316c2ba93SPeter Wemm #define SIZE(n) (n) 9416c2ba93SPeter Wemm #else 959983067eSMatthew Dillon #define SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize)) 9616c2ba93SPeter Wemm #endif 9716c2ba93SPeter Wemm 9816c2ba93SPeter Wemm #define INOCNT(fs) ((fs)->fs_ipg) 991c85e6a3SKirk McKusick #define INOSZ(fs) \ 1001c85e6a3SKirk McKusick (((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \ 1011c85e6a3SKirk McKusick sizeof(struct ufs2_dinode)) * INOCNT(fs)) 10216c2ba93SPeter Wemm 1031c85e6a3SKirk McKusick union dinode { 1041c85e6a3SKirk McKusick struct ufs1_dinode dp1; 1051c85e6a3SKirk McKusick struct ufs2_dinode dp2; 1061c85e6a3SKirk McKusick }; 1071c85e6a3SKirk McKusick #define DIP(fs, dp, field) \ 1081c85e6a3SKirk McKusick (((fs)->fs_magic == FS_UFS1_MAGIC) ? \ 1091c85e6a3SKirk McKusick (dp)->dp1.field : (dp)->dp2.field) 1101c85e6a3SKirk McKusick 1111c85e6a3SKirk McKusick static union dinode * 1128f518424SDag-Erling Smørgrav get_inode(int fd, struct fs *super, 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"); 1486e560addSPedro F. Giffuni last = rounddown(ino, 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 1708f518424SDag-Erling Smørgrav static int virtualblocks(struct fs *super, union dinode *dp) 17116c2ba93SPeter Wemm { 1728f518424SDag-Erling Smørgrav off_t nblk, sz; 17316c2ba93SPeter Wemm 1741c85e6a3SKirk McKusick sz = DIP(super, dp, di_size); 17516c2ba93SPeter Wemm #ifdef COMPAT 1761dc349abSEd Maste if (lblkno(super,sz) >= UFS_NDADDR) { 17716c2ba93SPeter Wemm nblk = blkroundup(super,sz); 17816c2ba93SPeter Wemm if (sz == nblk) 17916c2ba93SPeter Wemm nblk += super->fs_bsize; 18016c2ba93SPeter Wemm } 18116c2ba93SPeter Wemm 18216c2ba93SPeter Wemm return sz / 1024; 18316c2ba93SPeter Wemm 18416c2ba93SPeter Wemm #else /* COMPAT */ 18516c2ba93SPeter Wemm 1861dc349abSEd Maste if (lblkno(super,sz) >= UFS_NDADDR) { 18716c2ba93SPeter Wemm nblk = blkroundup(super,sz); 18816c2ba93SPeter Wemm sz = lblkno(super,nblk); 1891dc349abSEd Maste sz = (sz - UFS_NDADDR + NINDIR(super) - 1) / NINDIR(super); 19016c2ba93SPeter Wemm while (sz > 0) { 19116c2ba93SPeter Wemm nblk += sz * super->fs_bsize; 19216c2ba93SPeter Wemm /* sz - 1 rounded up */ 19316c2ba93SPeter Wemm sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super); 19416c2ba93SPeter Wemm } 19516c2ba93SPeter Wemm } else 19616c2ba93SPeter Wemm nblk = fragroundup(super,sz); 19716c2ba93SPeter Wemm 19816c2ba93SPeter Wemm return nblk / 512; 19916c2ba93SPeter Wemm #endif /* COMPAT */ 20016c2ba93SPeter Wemm } 20116c2ba93SPeter Wemm 2026980f0ebSPhilippe Charnier static int 2038f518424SDag-Erling Smørgrav isfree(struct fs *super, union dinode *dp) 20416c2ba93SPeter Wemm { 20516c2ba93SPeter Wemm #ifdef COMPAT 206d8ba45e2SEd Maste return (DIP(super, dp, di_mode) & IFMT) == 0; 20716c2ba93SPeter Wemm #else /* COMPAT */ 20816c2ba93SPeter Wemm 209d8ba45e2SEd Maste switch (DIP(super, dp, di_mode) & IFMT) { 210d8ba45e2SEd Maste case IFIFO: 211d8ba45e2SEd Maste case IFLNK: /* should check FASTSYMLINK? */ 212d8ba45e2SEd Maste case IFDIR: 213d8ba45e2SEd Maste case IFREG: 21416c2ba93SPeter Wemm return 0; 215d8ba45e2SEd Maste case IFCHR: 216d8ba45e2SEd Maste case IFBLK: 217d8ba45e2SEd Maste case IFSOCK: 218d8ba45e2SEd Maste case IFWHT: 219bee3d34fSDavid Malone case 0: 22016c2ba93SPeter Wemm return 1; 221bee3d34fSDavid Malone default: 222d8ba45e2SEd Maste errx(1, "unknown IFMT 0%o", DIP(super, dp, di_mode) & IFMT); 22316c2ba93SPeter Wemm } 22416c2ba93SPeter Wemm #endif 22516c2ba93SPeter Wemm } 22616c2ba93SPeter Wemm 22716c2ba93SPeter Wemm static struct user { 22816c2ba93SPeter Wemm uid_t uid; 22916c2ba93SPeter Wemm char *name; 23016c2ba93SPeter Wemm daddr_t space; 23116c2ba93SPeter Wemm long count; 23216c2ba93SPeter Wemm daddr_t spc30; 23316c2ba93SPeter Wemm daddr_t spc60; 23416c2ba93SPeter Wemm daddr_t spc90; 23516c2ba93SPeter Wemm } *users; 23616c2ba93SPeter Wemm static int nusers; 23716c2ba93SPeter Wemm 2386980f0ebSPhilippe Charnier static void 2398f518424SDag-Erling Smørgrav inituser(void) 24016c2ba93SPeter Wemm { 2418f518424SDag-Erling Smørgrav int i; 2428f518424SDag-Erling Smørgrav struct user *usr; 24316c2ba93SPeter Wemm 24416c2ba93SPeter Wemm if (!nusers) { 24516c2ba93SPeter Wemm nusers = 8; 24616c2ba93SPeter Wemm if (!(users = 2476980f0ebSPhilippe Charnier (struct user *)calloc(nusers,sizeof(struct user)))) 2486980f0ebSPhilippe Charnier errx(1, "allocate users"); 24916c2ba93SPeter Wemm } else { 25016c2ba93SPeter Wemm for (usr = users, i = nusers; --i >= 0; usr++) { 25116c2ba93SPeter Wemm usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0; 25216c2ba93SPeter Wemm usr->count = 0; 25316c2ba93SPeter Wemm } 25416c2ba93SPeter Wemm } 25516c2ba93SPeter Wemm } 25616c2ba93SPeter Wemm 2576980f0ebSPhilippe Charnier static void 2588f518424SDag-Erling Smørgrav usrrehash(void) 25916c2ba93SPeter Wemm { 2608f518424SDag-Erling Smørgrav int i; 2618f518424SDag-Erling Smørgrav struct user *usr, *usrn; 26216c2ba93SPeter Wemm struct user *svusr; 26316c2ba93SPeter Wemm 26416c2ba93SPeter Wemm svusr = users; 26516c2ba93SPeter Wemm nusers <<= 1; 2666980f0ebSPhilippe Charnier if (!(users = (struct user *)calloc(nusers,sizeof(struct user)))) 2676980f0ebSPhilippe Charnier errx(1, "allocate users"); 26816c2ba93SPeter Wemm for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) { 26916c2ba93SPeter Wemm for (usrn = users + (usr->uid&(nusers - 1)); usrn->name; 27016c2ba93SPeter Wemm usrn--) { 27116c2ba93SPeter Wemm if (usrn <= users) 27216c2ba93SPeter Wemm usrn = users + nusers; 27316c2ba93SPeter Wemm } 27416c2ba93SPeter Wemm *usrn = *usr; 27516c2ba93SPeter Wemm } 27616c2ba93SPeter Wemm } 27716c2ba93SPeter Wemm 2786980f0ebSPhilippe Charnier static struct user * 2798f518424SDag-Erling Smørgrav user(uid_t uid) 28016c2ba93SPeter Wemm { 2818f518424SDag-Erling Smørgrav struct user *usr; 2828f518424SDag-Erling Smørgrav int i; 28316c2ba93SPeter Wemm struct passwd *pwd; 28416c2ba93SPeter Wemm 28516c2ba93SPeter Wemm while (1) { 28616c2ba93SPeter Wemm for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0; 28716c2ba93SPeter Wemm usr--) { 28816c2ba93SPeter Wemm if (!usr->name) { 28916c2ba93SPeter Wemm usr->uid = uid; 29016c2ba93SPeter Wemm 29116c2ba93SPeter Wemm if (!(pwd = getpwuid(uid))) { 2926980f0ebSPhilippe Charnier if ((usr->name = (char *)malloc(7))) 29316c2ba93SPeter Wemm sprintf(usr->name,"#%d",uid); 29416c2ba93SPeter Wemm } else { 2956980f0ebSPhilippe Charnier if ((usr->name = (char *) 2966980f0ebSPhilippe Charnier malloc(strlen(pwd->pw_name) + 1))) 29716c2ba93SPeter Wemm strcpy(usr->name,pwd->pw_name); 29816c2ba93SPeter Wemm } 2996980f0ebSPhilippe Charnier if (!usr->name) 3006980f0ebSPhilippe Charnier errx(1, "allocate users"); 30116c2ba93SPeter Wemm 30216c2ba93SPeter Wemm return usr; 30316c2ba93SPeter Wemm 30416c2ba93SPeter Wemm } else if (usr->uid == uid) 30516c2ba93SPeter Wemm return usr; 30616c2ba93SPeter Wemm 30716c2ba93SPeter Wemm if (usr <= users) 30816c2ba93SPeter Wemm usr = users + nusers; 30916c2ba93SPeter Wemm } 31016c2ba93SPeter Wemm usrrehash(); 31116c2ba93SPeter Wemm } 31216c2ba93SPeter Wemm } 31316c2ba93SPeter Wemm 3146980f0ebSPhilippe Charnier static int 3158f518424SDag-Erling Smørgrav cmpusers(const void *v1, const void *v2) 31616c2ba93SPeter Wemm { 31757cdc152SMike Heffner const struct user *u1, *u2; 31857cdc152SMike Heffner u1 = (const struct user *)v1; 31957cdc152SMike Heffner u2 = (const struct user *)v2; 32057cdc152SMike Heffner 32116c2ba93SPeter Wemm return u2->space - u1->space; 32216c2ba93SPeter Wemm } 32316c2ba93SPeter Wemm 32416c2ba93SPeter Wemm #define sortusers(users) (qsort((users),nusers,sizeof(struct user), \ 32516c2ba93SPeter Wemm cmpusers)) 32616c2ba93SPeter Wemm 3276980f0ebSPhilippe Charnier static void 3288f518424SDag-Erling Smørgrav uses(uid_t uid, daddr_t blks, time_t act) 32916c2ba93SPeter Wemm { 33016c2ba93SPeter Wemm static time_t today; 3318f518424SDag-Erling Smørgrav struct user *usr; 33216c2ba93SPeter Wemm 33316c2ba93SPeter Wemm if (!today) 33416c2ba93SPeter Wemm time(&today); 33516c2ba93SPeter Wemm 33616c2ba93SPeter Wemm usr = user(uid); 33716c2ba93SPeter Wemm usr->count++; 33816c2ba93SPeter Wemm usr->space += blks; 33916c2ba93SPeter Wemm 34016c2ba93SPeter Wemm if (today - act > 90L * 24L * 60L * 60L) 34116c2ba93SPeter Wemm usr->spc90 += blks; 34216c2ba93SPeter Wemm if (today - act > 60L * 24L * 60L * 60L) 34316c2ba93SPeter Wemm usr->spc60 += blks; 34416c2ba93SPeter Wemm if (today - act > 30L * 24L * 60L * 60L) 34516c2ba93SPeter Wemm usr->spc30 += blks; 34616c2ba93SPeter Wemm } 34716c2ba93SPeter Wemm 34816c2ba93SPeter Wemm #ifdef COMPAT 34916c2ba93SPeter Wemm #define FSZCNT 500 35016c2ba93SPeter Wemm #else 35116c2ba93SPeter Wemm #define FSZCNT 512 35216c2ba93SPeter Wemm #endif 35316c2ba93SPeter Wemm struct fsizes { 35416c2ba93SPeter Wemm struct fsizes *fsz_next; 35516c2ba93SPeter Wemm daddr_t fsz_first, fsz_last; 35616c2ba93SPeter Wemm ino_t fsz_count[FSZCNT]; 35716c2ba93SPeter Wemm daddr_t fsz_sz[FSZCNT]; 35816c2ba93SPeter Wemm } *fsizes; 35916c2ba93SPeter Wemm 3606980f0ebSPhilippe Charnier static void 3618f518424SDag-Erling Smørgrav initfsizes(void) 36216c2ba93SPeter Wemm { 3638f518424SDag-Erling Smørgrav struct fsizes *fp; 3648f518424SDag-Erling Smørgrav int i; 36516c2ba93SPeter Wemm 36616c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) { 36716c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) { 36816c2ba93SPeter Wemm fp->fsz_count[i] = 0; 36916c2ba93SPeter Wemm fp->fsz_sz[i] = 0; 37016c2ba93SPeter Wemm } 37116c2ba93SPeter Wemm } 37216c2ba93SPeter Wemm } 37316c2ba93SPeter Wemm 3746980f0ebSPhilippe Charnier static void 3758f518424SDag-Erling Smørgrav dofsizes(int fd, struct fs *super, char *name) 37616c2ba93SPeter Wemm { 37716c2ba93SPeter Wemm ino_t inode, maxino; 3781c85e6a3SKirk McKusick union dinode *dp; 37916c2ba93SPeter Wemm daddr_t sz, ksz; 38016c2ba93SPeter Wemm struct fsizes *fp, **fsp; 3818f518424SDag-Erling Smørgrav int i; 38216c2ba93SPeter Wemm 38316c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 38416c2ba93SPeter Wemm #ifdef COMPAT 3856980f0ebSPhilippe Charnier if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes)))) 386652b7200SPhilippe Charnier errx(1, "allocate fsize structure"); 38716c2ba93SPeter Wemm #endif /* COMPAT */ 38816c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) { 38916c2ba93SPeter Wemm errno = 0; 3901c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 39116c2ba93SPeter Wemm #ifdef COMPAT 392d8ba45e2SEd Maste && ((DIP(super, dp, di_mode) & IFMT) == IFREG 393d8ba45e2SEd Maste || (DIP(super, dp, di_mode) & IFMT) == IFDIR) 39416c2ba93SPeter Wemm #else /* COMPAT */ 3951c85e6a3SKirk McKusick && !isfree(super, dp) 39616c2ba93SPeter Wemm #endif /* COMPAT */ 39716c2ba93SPeter Wemm ) { 3981c85e6a3SKirk McKusick sz = estimate ? virtualblocks(super, dp) : 3991c85e6a3SKirk McKusick actualblocks(super, dp); 40016c2ba93SPeter Wemm #ifdef COMPAT 40116c2ba93SPeter Wemm if (sz >= FSZCNT) { 40216c2ba93SPeter Wemm fsizes->fsz_count[FSZCNT-1]++; 40316c2ba93SPeter Wemm fsizes->fsz_sz[FSZCNT-1] += sz; 40416c2ba93SPeter Wemm } else { 40516c2ba93SPeter Wemm fsizes->fsz_count[sz]++; 40616c2ba93SPeter Wemm fsizes->fsz_sz[sz] += sz; 40716c2ba93SPeter Wemm } 40816c2ba93SPeter Wemm #else /* COMPAT */ 40916c2ba93SPeter Wemm ksz = SIZE(sz); 4106980f0ebSPhilippe Charnier for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) { 41116c2ba93SPeter Wemm if (ksz < fp->fsz_last) 41216c2ba93SPeter Wemm break; 41316c2ba93SPeter Wemm } 41416c2ba93SPeter Wemm if (!fp || ksz < fp->fsz_first) { 41516c2ba93SPeter Wemm if (!(fp = (struct fsizes *) 4166980f0ebSPhilippe Charnier malloc(sizeof(struct fsizes)))) 417652b7200SPhilippe Charnier errx(1, "allocate fsize structure"); 41816c2ba93SPeter Wemm fp->fsz_next = *fsp; 41916c2ba93SPeter Wemm *fsp = fp; 4206e560addSPedro F. Giffuni fp->fsz_first = rounddown(ksz, FSZCNT); 42116c2ba93SPeter Wemm fp->fsz_last = fp->fsz_first + FSZCNT; 42216c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) { 42316c2ba93SPeter Wemm fp->fsz_count[i] = 0; 42416c2ba93SPeter Wemm fp->fsz_sz[i] = 0; 42516c2ba93SPeter Wemm } 42616c2ba93SPeter Wemm } 42716c2ba93SPeter Wemm fp->fsz_count[ksz % FSZCNT]++; 42816c2ba93SPeter Wemm fp->fsz_sz[ksz % FSZCNT] += sz; 42916c2ba93SPeter Wemm #endif /* COMPAT */ 43016c2ba93SPeter Wemm } else if (errno) { 4316980f0ebSPhilippe Charnier err(1, "%s", name); 43216c2ba93SPeter Wemm } 43316c2ba93SPeter Wemm } 43416c2ba93SPeter Wemm sz = 0; 43516c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) { 43616c2ba93SPeter Wemm for (i = 0; i < FSZCNT; i++) { 43716c2ba93SPeter Wemm if (fp->fsz_count[i]) 4389f60cc9eSDag-Erling Smørgrav printf("%jd\t%jd\t%d\n", 4399f60cc9eSDag-Erling Smørgrav (intmax_t)(fp->fsz_first + i), 4409f60cc9eSDag-Erling Smørgrav (intmax_t)fp->fsz_count[i], 44116c2ba93SPeter Wemm SIZE(sz += fp->fsz_sz[i])); 44216c2ba93SPeter Wemm } 44316c2ba93SPeter Wemm } 44416c2ba93SPeter Wemm } 44516c2ba93SPeter Wemm 4466980f0ebSPhilippe Charnier static void 4478f518424SDag-Erling Smørgrav douser(int fd, struct fs *super, char *name) 44816c2ba93SPeter Wemm { 44916c2ba93SPeter Wemm ino_t inode, maxino; 45016c2ba93SPeter Wemm struct user *usr, *usrs; 4511c85e6a3SKirk McKusick union dinode *dp; 4528f518424SDag-Erling Smørgrav int n; 45316c2ba93SPeter Wemm 45416c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 45516c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) { 45616c2ba93SPeter Wemm errno = 0; 4571c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 4581c85e6a3SKirk McKusick && !isfree(super, dp)) 4591c85e6a3SKirk McKusick uses(DIP(super, dp, di_uid), 4601c85e6a3SKirk McKusick estimate ? virtualblocks(super, dp) : 4611c85e6a3SKirk McKusick actualblocks(super, dp), 4621c85e6a3SKirk McKusick DIP(super, dp, di_atime)); 46316c2ba93SPeter Wemm else if (errno) { 4646980f0ebSPhilippe Charnier err(1, "%s", name); 46516c2ba93SPeter Wemm } 46616c2ba93SPeter Wemm } 4676980f0ebSPhilippe Charnier if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user)))) 4686980f0ebSPhilippe Charnier errx(1, "allocate users"); 46916c2ba93SPeter Wemm bcopy(users,usrs,nusers * sizeof(struct user)); 47016c2ba93SPeter Wemm sortusers(usrs); 47116c2ba93SPeter Wemm for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) { 47216c2ba93SPeter Wemm printf("%5d",SIZE(usr->space)); 47316c2ba93SPeter Wemm if (count) 47457cdc152SMike Heffner printf("\t%5ld",usr->count); 47516c2ba93SPeter Wemm printf("\t%-8s",usr->name); 47616c2ba93SPeter Wemm if (unused) 47716c2ba93SPeter Wemm printf("\t%5d\t%5d\t%5d", 47816c2ba93SPeter Wemm SIZE(usr->spc30), 47916c2ba93SPeter Wemm SIZE(usr->spc60), 48016c2ba93SPeter Wemm SIZE(usr->spc90)); 48116c2ba93SPeter Wemm printf("\n"); 48216c2ba93SPeter Wemm } 48316c2ba93SPeter Wemm free(usrs); 48416c2ba93SPeter Wemm } 48516c2ba93SPeter Wemm 4866980f0ebSPhilippe Charnier static void 4878f518424SDag-Erling Smørgrav donames(int fd, struct fs *super, char *name) 48816c2ba93SPeter Wemm { 48916c2ba93SPeter Wemm int c; 49016c2ba93SPeter Wemm ino_t maxino; 491b424efd5SMatthew D Fleming uintmax_t inode; 4921c85e6a3SKirk McKusick union dinode *dp; 49316c2ba93SPeter Wemm 49416c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 49516c2ba93SPeter Wemm /* first skip the name of the filesystem */ 49616c2ba93SPeter Wemm while ((c = getchar()) != EOF && (c < '0' || c > '9')) 49716c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n'); 49816c2ba93SPeter Wemm ungetc(c,stdin); 499b424efd5SMatthew D Fleming while (scanf("%ju", &inode) == 1) { 50057cdc152SMike Heffner if (inode > maxino) { 501b424efd5SMatthew D Fleming warnx("illegal inode %ju", inode); 50216c2ba93SPeter Wemm return; 50316c2ba93SPeter Wemm } 50416c2ba93SPeter Wemm errno = 0; 5051c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 5061c85e6a3SKirk McKusick && !isfree(super, dp)) { 5071c85e6a3SKirk McKusick printf("%s\t",user(DIP(super, dp, di_uid))->name); 50816c2ba93SPeter Wemm /* now skip whitespace */ 50916c2ba93SPeter Wemm while ((c = getchar()) == ' ' || c == '\t'); 51016c2ba93SPeter Wemm /* and print out the remainder of the input line */ 51116c2ba93SPeter Wemm while (c != EOF && c != '\n') { 51216c2ba93SPeter Wemm putchar(c); 51316c2ba93SPeter Wemm c = getchar(); 51416c2ba93SPeter Wemm } 51516c2ba93SPeter Wemm putchar('\n'); 51616c2ba93SPeter Wemm } else { 51716c2ba93SPeter Wemm if (errno) { 5186980f0ebSPhilippe Charnier err(1, "%s", name); 51916c2ba93SPeter Wemm } 52016c2ba93SPeter Wemm /* skip this line */ 52116c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n'); 52216c2ba93SPeter Wemm } 52316c2ba93SPeter Wemm if (c == EOF) 52416c2ba93SPeter Wemm break; 52516c2ba93SPeter Wemm } 52616c2ba93SPeter Wemm } 52716c2ba93SPeter Wemm 5286980f0ebSPhilippe Charnier static void 5298f518424SDag-Erling Smørgrav usage(void) 53016c2ba93SPeter Wemm { 53116c2ba93SPeter Wemm #ifdef COMPAT 5326980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n"); 53316c2ba93SPeter Wemm #else /* COMPAT */ 5346980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n"); 53516c2ba93SPeter Wemm #endif /* COMPAT */ 53616c2ba93SPeter Wemm exit(1); 53716c2ba93SPeter Wemm } 53816c2ba93SPeter Wemm 5396980f0ebSPhilippe Charnier void 5408f518424SDag-Erling Smørgrav quot(char *name, char *mp) 54116c2ba93SPeter Wemm { 542dffce215SKirk McKusick int fd; 5431c85e6a3SKirk McKusick struct fs *fs; 54416c2ba93SPeter Wemm 54557cdc152SMike Heffner get_inode(-1, NULL, 0); /* flush cache */ 54616c2ba93SPeter Wemm inituser(); 54716c2ba93SPeter Wemm initfsizes(); 5481c85e6a3SKirk McKusick if ((fd = open(name,0)) < 0) { 5496980f0ebSPhilippe Charnier warn("%s", name); 55016c2ba93SPeter Wemm close(fd); 55116c2ba93SPeter Wemm return; 55216c2ba93SPeter Wemm } 553dffce215SKirk McKusick switch (sbget(fd, &fs, -1)) { 554dffce215SKirk McKusick case 0: 5551c85e6a3SKirk McKusick break; 556dffce215SKirk McKusick case ENOENT: 557dffce215SKirk McKusick warn("Cannot find file system superblock"); 558dffce215SKirk McKusick close(fd); 559dffce215SKirk McKusick return; 560dffce215SKirk McKusick default: 561dffce215SKirk McKusick warn("Unable to read file system superblock"); 56216c2ba93SPeter Wemm close(fd); 56316c2ba93SPeter Wemm return; 56416c2ba93SPeter Wemm } 56516c2ba93SPeter Wemm printf("%s:",name); 56616c2ba93SPeter Wemm if (mp) 56716c2ba93SPeter Wemm printf(" (%s)",mp); 56816c2ba93SPeter Wemm putchar('\n'); 5691c85e6a3SKirk McKusick (*func)(fd, fs, name); 57016c2ba93SPeter Wemm close(fd); 57116c2ba93SPeter Wemm } 57216c2ba93SPeter Wemm 5736980f0ebSPhilippe Charnier int 5748f518424SDag-Erling Smørgrav main(int argc, char *argv[]) 57516c2ba93SPeter Wemm { 57616c2ba93SPeter Wemm char all = 0; 57716c2ba93SPeter Wemm struct statfs *mp; 57881f1ec27SPaul Saab struct fstab *fs; 57916c2ba93SPeter Wemm int cnt; 58016c2ba93SPeter Wemm 58116c2ba93SPeter Wemm func = douser; 58216c2ba93SPeter Wemm #ifndef COMPAT 58316c2ba93SPeter Wemm header = getbsize(&headerlen,&blocksize); 58416c2ba93SPeter Wemm #endif 58516c2ba93SPeter Wemm while (--argc > 0 && **++argv == '-') { 58616c2ba93SPeter Wemm while (*++*argv) { 58716c2ba93SPeter Wemm switch (**argv) { 58816c2ba93SPeter Wemm case 'n': 58916c2ba93SPeter Wemm func = donames; 59016c2ba93SPeter Wemm break; 59116c2ba93SPeter Wemm case 'c': 59216c2ba93SPeter Wemm func = dofsizes; 59316c2ba93SPeter Wemm break; 59416c2ba93SPeter Wemm case 'a': 59516c2ba93SPeter Wemm all = 1; 59616c2ba93SPeter Wemm break; 59716c2ba93SPeter Wemm case 'f': 59816c2ba93SPeter Wemm count = 1; 59916c2ba93SPeter Wemm break; 60016c2ba93SPeter Wemm case 'h': 60116c2ba93SPeter Wemm estimate = 1; 60216c2ba93SPeter Wemm break; 60316c2ba93SPeter Wemm #ifndef COMPAT 60416c2ba93SPeter Wemm case 'k': 60516c2ba93SPeter Wemm blocksize = 1024; 60616c2ba93SPeter Wemm break; 60716c2ba93SPeter Wemm #endif /* COMPAT */ 60816c2ba93SPeter Wemm case 'v': 60916c2ba93SPeter Wemm unused = 1; 61016c2ba93SPeter Wemm break; 61116c2ba93SPeter Wemm default: 61216c2ba93SPeter Wemm usage(); 61316c2ba93SPeter Wemm } 61416c2ba93SPeter Wemm } 61516c2ba93SPeter Wemm } 61616c2ba93SPeter Wemm if (all) { 61716c2ba93SPeter Wemm cnt = getmntinfo(&mp,MNT_NOWAIT); 61816c2ba93SPeter Wemm for (; --cnt >= 0; mp++) { 619b4eca767SEd Schouten if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) 620b4eca767SEd Schouten quot(mp->f_mntfromname, mp->f_mntonname); 62116c2ba93SPeter Wemm } 62216c2ba93SPeter Wemm } 62381f1ec27SPaul Saab while (--argc >= 0) { 62481f1ec27SPaul Saab if ((fs = getfsfile(*argv)) != NULL) 62581f1ec27SPaul Saab quot(fs->fs_spec, 0); 62681f1ec27SPaul Saab else 62781f1ec27SPaul Saab quot(*argv,0); 62881f1ec27SPaul Saab argv++; 62981f1ec27SPaul Saab } 63016c2ba93SPeter Wemm return 0; 63116c2ba93SPeter Wemm } 632