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> 481a37aa56SDavid E. O'Brien #include <paths.h> 496980f0ebSPhilippe Charnier #include <pwd.h> 5016c2ba93SPeter Wemm #include <stdio.h> 5116c2ba93SPeter Wemm #include <stdlib.h> 5216c2ba93SPeter Wemm #include <string.h> 537649cb00SKirk McKusick #include <time.h> 546980f0ebSPhilippe Charnier #include <unistd.h> 5516c2ba93SPeter Wemm 5616c2ba93SPeter Wemm /* some flags of what to do: */ 5716c2ba93SPeter Wemm static char estimate; 5816c2ba93SPeter Wemm static char count; 5916c2ba93SPeter Wemm static char unused; 6057cdc152SMike Heffner static void (*func)(int, struct fs *, char *); 6116c2ba93SPeter Wemm static long blocksize; 6216c2ba93SPeter Wemm static char *header; 63bc6ba9aeSMike Barcroft static int headerlen; 6416c2ba93SPeter Wemm 651c85e6a3SKirk McKusick static union dinode *get_inode(int, struct fs *, ino_t); 661c85e6a3SKirk McKusick static int virtualblocks(struct fs *, union dinode *); 671c85e6a3SKirk McKusick static int isfree(struct fs *, union dinode *); 6857cdc152SMike Heffner static void inituser(void); 6957cdc152SMike Heffner static void usrrehash(void); 7057cdc152SMike Heffner static struct user *user(uid_t); 7157cdc152SMike Heffner static int cmpusers(const void *, const void *); 7257cdc152SMike Heffner static void uses(uid_t, daddr_t, time_t); 7357cdc152SMike Heffner static void initfsizes(void); 7457cdc152SMike Heffner static void dofsizes(int, struct fs *, char *); 7557cdc152SMike Heffner static void douser(int, struct fs *, char *); 7657cdc152SMike Heffner static void donames(int, struct fs *, char *); 7757cdc152SMike Heffner static void usage(void); 7857cdc152SMike Heffner static void quot(char *, char *); 7957cdc152SMike Heffner 8016c2ba93SPeter Wemm /* 8116c2ba93SPeter Wemm * Original BSD quot doesn't round to number of frags/blocks, 8216c2ba93SPeter Wemm * doesn't account for indirection blocks and gets it totally 8316c2ba93SPeter Wemm * wrong if the size is a multiple of the blocksize. 8416c2ba93SPeter Wemm * The new code always counts the number of 512 byte blocks 8516c2ba93SPeter Wemm * instead of the number of kilobytes and converts them to 8616c2ba93SPeter Wemm * kByte when done (on request). 879983067eSMatthew Dillon * 889983067eSMatthew Dillon * Due to the size of modern disks, we must cast intermediate 899983067eSMatthew Dillon * values to 64 bits to prevent potential overflows. 9016c2ba93SPeter Wemm */ 9116c2ba93SPeter Wemm #ifdef COMPAT 9216c2ba93SPeter Wemm #define SIZE(n) (n) 9316c2ba93SPeter Wemm #else 949983067eSMatthew Dillon #define SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize)) 9516c2ba93SPeter Wemm #endif 9616c2ba93SPeter Wemm 9716c2ba93SPeter Wemm #define INOCNT(fs) ((fs)->fs_ipg) 981c85e6a3SKirk McKusick #define INOSZ(fs) \ 991c85e6a3SKirk McKusick (((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \ 1001c85e6a3SKirk McKusick sizeof(struct ufs2_dinode)) * INOCNT(fs)) 10116c2ba93SPeter Wemm 1021c85e6a3SKirk McKusick union dinode { 1031c85e6a3SKirk McKusick struct ufs1_dinode dp1; 1041c85e6a3SKirk McKusick struct ufs2_dinode dp2; 1051c85e6a3SKirk McKusick }; 1061c85e6a3SKirk McKusick #define DIP(fs, dp, field) \ 1071c85e6a3SKirk McKusick (((fs)->fs_magic == FS_UFS1_MAGIC) ? \ 1081c85e6a3SKirk McKusick (dp)->dp1.field : (dp)->dp2.field) 1091c85e6a3SKirk McKusick 1101c85e6a3SKirk McKusick static union dinode * 1118f518424SDag-Erling Smørgrav get_inode(int fd, struct fs *super, ino_t ino) 11216c2ba93SPeter Wemm { 1131c85e6a3SKirk McKusick static caddr_t ipbuf; 114bee3d34fSDavid Malone static struct cg *cgp; 11516c2ba93SPeter Wemm static ino_t last; 116bee3d34fSDavid Malone static int cg; 117bee3d34fSDavid Malone struct ufs2_dinode *di2; 11816c2ba93SPeter Wemm 11916c2ba93SPeter Wemm if (fd < 0) { /* flush cache */ 1201c85e6a3SKirk McKusick if (ipbuf) { 1211c85e6a3SKirk McKusick free(ipbuf); 1221c85e6a3SKirk McKusick ipbuf = 0; 123c433b438SMaxim Konovalov if (super != NULL && super->fs_magic == FS_UFS2_MAGIC) { 124bee3d34fSDavid Malone free(cgp); 125bee3d34fSDavid Malone cgp = 0; 126bee3d34fSDavid Malone } 12716c2ba93SPeter Wemm } 12816c2ba93SPeter Wemm return 0; 12916c2ba93SPeter Wemm } 13016c2ba93SPeter Wemm 1311c85e6a3SKirk McKusick if (!ipbuf || ino < last || ino >= last + INOCNT(super)) { 132bee3d34fSDavid Malone if (super->fs_magic == FS_UFS2_MAGIC && 133bee3d34fSDavid Malone (!cgp || cg != ino_to_cg(super, ino))) { 134bee3d34fSDavid Malone cg = ino_to_cg(super, ino); 135bee3d34fSDavid Malone if (!cgp && !(cgp = malloc(super->fs_cgsize))) 136bee3d34fSDavid Malone errx(1, "allocate cg"); 137bee3d34fSDavid Malone if (lseek(fd, (off_t)cgtod(super, cg) << super->fs_fshift, 0) < 0) 138bee3d34fSDavid Malone err(1, "lseek cg"); 139bee3d34fSDavid Malone if (read(fd, cgp, super->fs_cgsize) != super->fs_cgsize) 140bee3d34fSDavid Malone err(1, "read cg"); 141bee3d34fSDavid Malone if (!cg_chkmagic(cgp)) 142bee3d34fSDavid Malone errx(1, "cg has bad magic"); 143bee3d34fSDavid Malone } 1441c85e6a3SKirk McKusick if (!ipbuf 1451c85e6a3SKirk McKusick && !(ipbuf = malloc(INOSZ(super)))) 1466980f0ebSPhilippe Charnier errx(1, "allocate inodes"); 1476e560addSPedro F. Giffuni last = rounddown(ino, INOCNT(super)); 148c9d12677SJordan K. Hubbard if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0 1491c85e6a3SKirk McKusick || read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super)) 1506980f0ebSPhilippe Charnier err(1, "read inodes"); 15116c2ba93SPeter Wemm } 15216c2ba93SPeter Wemm 1531c85e6a3SKirk McKusick if (super->fs_magic == FS_UFS1_MAGIC) 1541c85e6a3SKirk McKusick return ((union dinode *) 1551c85e6a3SKirk McKusick &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]); 156bee3d34fSDavid Malone di2 = &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]; 157bee3d34fSDavid Malone /* If the inode is unused, it might be unallocated too, so zero it. */ 158bee3d34fSDavid Malone if (isclr(cg_inosused(cgp), ino % super->fs_ipg)) 159bee3d34fSDavid Malone bzero(di2, sizeof (*di2)); 160bee3d34fSDavid Malone return ((union dinode *)di2); 16116c2ba93SPeter Wemm } 16216c2ba93SPeter Wemm 16316c2ba93SPeter Wemm #ifdef COMPAT 1641c85e6a3SKirk McKusick #define actualblocks(fs, dp) (DIP(fs, dp, di_blocks) / 2) 16516c2ba93SPeter Wemm #else 1661c85e6a3SKirk McKusick #define actualblocks(fs, dp) DIP(fs, dp, di_blocks) 16716c2ba93SPeter Wemm #endif 16816c2ba93SPeter Wemm 1698f518424SDag-Erling Smørgrav static int virtualblocks(struct fs *super, union dinode *dp) 17016c2ba93SPeter Wemm { 1718f518424SDag-Erling Smørgrav off_t nblk, sz; 17216c2ba93SPeter Wemm 1731c85e6a3SKirk McKusick sz = DIP(super, dp, di_size); 17416c2ba93SPeter Wemm #ifdef COMPAT 1751dc349abSEd Maste if (lblkno(super,sz) >= UFS_NDADDR) { 17616c2ba93SPeter Wemm nblk = blkroundup(super,sz); 17716c2ba93SPeter Wemm if (sz == nblk) 17816c2ba93SPeter Wemm nblk += super->fs_bsize; 17916c2ba93SPeter Wemm } 18016c2ba93SPeter Wemm 18116c2ba93SPeter Wemm return sz / 1024; 18216c2ba93SPeter Wemm 18316c2ba93SPeter Wemm #else /* COMPAT */ 18416c2ba93SPeter Wemm 1851dc349abSEd Maste if (lblkno(super,sz) >= UFS_NDADDR) { 18616c2ba93SPeter Wemm nblk = blkroundup(super,sz); 18716c2ba93SPeter Wemm sz = lblkno(super,nblk); 1881dc349abSEd Maste sz = (sz - UFS_NDADDR + NINDIR(super) - 1) / NINDIR(super); 18916c2ba93SPeter Wemm while (sz > 0) { 19016c2ba93SPeter Wemm nblk += sz * super->fs_bsize; 19116c2ba93SPeter Wemm /* sz - 1 rounded up */ 19216c2ba93SPeter Wemm sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super); 19316c2ba93SPeter Wemm } 19416c2ba93SPeter Wemm } else 19516c2ba93SPeter Wemm nblk = fragroundup(super,sz); 19616c2ba93SPeter Wemm 19716c2ba93SPeter Wemm return nblk / 512; 19816c2ba93SPeter Wemm #endif /* COMPAT */ 19916c2ba93SPeter Wemm } 20016c2ba93SPeter Wemm 2016980f0ebSPhilippe Charnier static int 2028f518424SDag-Erling Smørgrav isfree(struct fs *super, union dinode *dp) 20316c2ba93SPeter Wemm { 20416c2ba93SPeter Wemm #ifdef COMPAT 2051c85e6a3SKirk McKusick return (DIP(super, dp, di_mode) & IFMT) == 0; 20616c2ba93SPeter Wemm #else /* COMPAT */ 20716c2ba93SPeter Wemm 2081c85e6a3SKirk McKusick switch (DIP(super, dp, di_mode) & IFMT) { 20916c2ba93SPeter Wemm case IFIFO: 21016c2ba93SPeter Wemm case IFLNK: /* should check FASTSYMLINK? */ 21116c2ba93SPeter Wemm case IFDIR: 21216c2ba93SPeter Wemm case IFREG: 21316c2ba93SPeter Wemm return 0; 214bee3d34fSDavid Malone case IFCHR: 215bee3d34fSDavid Malone case IFBLK: 216bee3d34fSDavid Malone case IFSOCK: 217bee3d34fSDavid Malone case IFWHT: 218bee3d34fSDavid Malone case 0: 21916c2ba93SPeter Wemm return 1; 220bee3d34fSDavid Malone default: 221bee3d34fSDavid Malone errx(1, "unknown IFMT 0%o", DIP(super, dp, di_mode) & IFMT); 22216c2ba93SPeter Wemm } 22316c2ba93SPeter Wemm #endif 22416c2ba93SPeter Wemm } 22516c2ba93SPeter Wemm 22616c2ba93SPeter Wemm static struct user { 22716c2ba93SPeter Wemm uid_t uid; 22816c2ba93SPeter Wemm char *name; 22916c2ba93SPeter Wemm daddr_t space; 23016c2ba93SPeter Wemm long count; 23116c2ba93SPeter Wemm daddr_t spc30; 23216c2ba93SPeter Wemm daddr_t spc60; 23316c2ba93SPeter Wemm daddr_t spc90; 23416c2ba93SPeter Wemm } *users; 23516c2ba93SPeter Wemm static int nusers; 23616c2ba93SPeter Wemm 2376980f0ebSPhilippe Charnier static void 2388f518424SDag-Erling Smørgrav inituser(void) 23916c2ba93SPeter Wemm { 2408f518424SDag-Erling Smørgrav int i; 2418f518424SDag-Erling Smørgrav struct user *usr; 24216c2ba93SPeter Wemm 24316c2ba93SPeter Wemm if (!nusers) { 24416c2ba93SPeter Wemm nusers = 8; 24516c2ba93SPeter Wemm if (!(users = 2466980f0ebSPhilippe Charnier (struct user *)calloc(nusers,sizeof(struct user)))) 2476980f0ebSPhilippe Charnier errx(1, "allocate users"); 24816c2ba93SPeter Wemm } else { 24916c2ba93SPeter Wemm for (usr = users, i = nusers; --i >= 0; usr++) { 25016c2ba93SPeter Wemm usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0; 25116c2ba93SPeter Wemm usr->count = 0; 25216c2ba93SPeter Wemm } 25316c2ba93SPeter Wemm } 25416c2ba93SPeter Wemm } 25516c2ba93SPeter Wemm 2566980f0ebSPhilippe Charnier static void 2578f518424SDag-Erling Smørgrav usrrehash(void) 25816c2ba93SPeter Wemm { 2598f518424SDag-Erling Smørgrav int i; 2608f518424SDag-Erling Smørgrav struct user *usr, *usrn; 26116c2ba93SPeter Wemm struct user *svusr; 26216c2ba93SPeter Wemm 26316c2ba93SPeter Wemm svusr = users; 26416c2ba93SPeter Wemm nusers <<= 1; 2656980f0ebSPhilippe Charnier if (!(users = (struct user *)calloc(nusers,sizeof(struct user)))) 2666980f0ebSPhilippe Charnier errx(1, "allocate users"); 26716c2ba93SPeter Wemm for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) { 26816c2ba93SPeter Wemm for (usrn = users + (usr->uid&(nusers - 1)); usrn->name; 26916c2ba93SPeter Wemm usrn--) { 27016c2ba93SPeter Wemm if (usrn <= users) 27116c2ba93SPeter Wemm usrn = users + nusers; 27216c2ba93SPeter Wemm } 27316c2ba93SPeter Wemm *usrn = *usr; 27416c2ba93SPeter Wemm } 27516c2ba93SPeter Wemm } 27616c2ba93SPeter Wemm 2776980f0ebSPhilippe Charnier static struct user * 2788f518424SDag-Erling Smørgrav user(uid_t uid) 27916c2ba93SPeter Wemm { 2808f518424SDag-Erling Smørgrav struct user *usr; 2818f518424SDag-Erling Smørgrav int i; 28216c2ba93SPeter Wemm struct passwd *pwd; 28316c2ba93SPeter Wemm 28416c2ba93SPeter Wemm while (1) { 28516c2ba93SPeter Wemm for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0; 28616c2ba93SPeter Wemm usr--) { 28716c2ba93SPeter Wemm if (!usr->name) { 28816c2ba93SPeter Wemm usr->uid = uid; 28916c2ba93SPeter Wemm 29016c2ba93SPeter Wemm if (!(pwd = getpwuid(uid))) { 2916980f0ebSPhilippe Charnier if ((usr->name = (char *)malloc(7))) 29216c2ba93SPeter Wemm sprintf(usr->name,"#%d",uid); 29316c2ba93SPeter Wemm } else { 2946980f0ebSPhilippe Charnier if ((usr->name = (char *) 2956980f0ebSPhilippe Charnier malloc(strlen(pwd->pw_name) + 1))) 29616c2ba93SPeter Wemm strcpy(usr->name,pwd->pw_name); 29716c2ba93SPeter Wemm } 2986980f0ebSPhilippe Charnier if (!usr->name) 2996980f0ebSPhilippe Charnier errx(1, "allocate users"); 30016c2ba93SPeter Wemm 30116c2ba93SPeter Wemm return usr; 30216c2ba93SPeter Wemm 30316c2ba93SPeter Wemm } else if (usr->uid == uid) 30416c2ba93SPeter Wemm return usr; 30516c2ba93SPeter Wemm 30616c2ba93SPeter Wemm if (usr <= users) 30716c2ba93SPeter Wemm usr = users + nusers; 30816c2ba93SPeter Wemm } 30916c2ba93SPeter Wemm usrrehash(); 31016c2ba93SPeter Wemm } 31116c2ba93SPeter Wemm } 31216c2ba93SPeter Wemm 3136980f0ebSPhilippe Charnier static int 3148f518424SDag-Erling Smørgrav cmpusers(const void *v1, const void *v2) 31516c2ba93SPeter Wemm { 31657cdc152SMike Heffner const struct user *u1, *u2; 31757cdc152SMike Heffner u1 = (const struct user *)v1; 31857cdc152SMike Heffner u2 = (const struct user *)v2; 31957cdc152SMike Heffner 32016c2ba93SPeter Wemm return u2->space - u1->space; 32116c2ba93SPeter Wemm } 32216c2ba93SPeter Wemm 32316c2ba93SPeter Wemm #define sortusers(users) (qsort((users),nusers,sizeof(struct user), \ 32416c2ba93SPeter Wemm cmpusers)) 32516c2ba93SPeter Wemm 3266980f0ebSPhilippe Charnier static void 3278f518424SDag-Erling Smørgrav uses(uid_t uid, daddr_t blks, time_t act) 32816c2ba93SPeter Wemm { 32916c2ba93SPeter Wemm static time_t today; 3308f518424SDag-Erling Smørgrav struct user *usr; 33116c2ba93SPeter Wemm 33216c2ba93SPeter Wemm if (!today) 33316c2ba93SPeter Wemm time(&today); 33416c2ba93SPeter Wemm 33516c2ba93SPeter Wemm usr = user(uid); 33616c2ba93SPeter Wemm usr->count++; 33716c2ba93SPeter Wemm usr->space += blks; 33816c2ba93SPeter Wemm 33916c2ba93SPeter Wemm if (today - act > 90L * 24L * 60L * 60L) 34016c2ba93SPeter Wemm usr->spc90 += blks; 34116c2ba93SPeter Wemm if (today - act > 60L * 24L * 60L * 60L) 34216c2ba93SPeter Wemm usr->spc60 += blks; 34316c2ba93SPeter Wemm if (today - act > 30L * 24L * 60L * 60L) 34416c2ba93SPeter Wemm usr->spc30 += blks; 34516c2ba93SPeter Wemm } 34616c2ba93SPeter Wemm 34716c2ba93SPeter Wemm #ifdef COMPAT 34816c2ba93SPeter Wemm #define FSZCNT 500 34916c2ba93SPeter Wemm #else 35016c2ba93SPeter Wemm #define FSZCNT 512 35116c2ba93SPeter Wemm #endif 35216c2ba93SPeter Wemm struct fsizes { 35316c2ba93SPeter Wemm struct fsizes *fsz_next; 35416c2ba93SPeter Wemm daddr_t fsz_first, fsz_last; 35516c2ba93SPeter Wemm ino_t fsz_count[FSZCNT]; 35616c2ba93SPeter Wemm daddr_t fsz_sz[FSZCNT]; 35716c2ba93SPeter Wemm } *fsizes; 35816c2ba93SPeter Wemm 3596980f0ebSPhilippe Charnier static void 3608f518424SDag-Erling Smørgrav initfsizes(void) 36116c2ba93SPeter Wemm { 3628f518424SDag-Erling Smørgrav struct fsizes *fp; 3638f518424SDag-Erling Smørgrav int i; 36416c2ba93SPeter Wemm 36516c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) { 36616c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) { 36716c2ba93SPeter Wemm fp->fsz_count[i] = 0; 36816c2ba93SPeter Wemm fp->fsz_sz[i] = 0; 36916c2ba93SPeter Wemm } 37016c2ba93SPeter Wemm } 37116c2ba93SPeter Wemm } 37216c2ba93SPeter Wemm 3736980f0ebSPhilippe Charnier static void 3748f518424SDag-Erling Smørgrav dofsizes(int fd, struct fs *super, char *name) 37516c2ba93SPeter Wemm { 37616c2ba93SPeter Wemm ino_t inode, maxino; 3771c85e6a3SKirk McKusick union dinode *dp; 37816c2ba93SPeter Wemm daddr_t sz, ksz; 37916c2ba93SPeter Wemm struct fsizes *fp, **fsp; 3808f518424SDag-Erling Smørgrav int i; 38116c2ba93SPeter Wemm 38216c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 38316c2ba93SPeter Wemm #ifdef COMPAT 3846980f0ebSPhilippe Charnier if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes)))) 385652b7200SPhilippe Charnier errx(1, "allocate fsize structure"); 38616c2ba93SPeter Wemm #endif /* COMPAT */ 38716c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) { 38816c2ba93SPeter Wemm errno = 0; 3891c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 39016c2ba93SPeter Wemm #ifdef COMPAT 3911c85e6a3SKirk McKusick && ((DIP(super, dp, di_mode) & IFMT) == IFREG 3921c85e6a3SKirk McKusick || (DIP(super, dp, di_mode) & IFMT) == IFDIR) 39316c2ba93SPeter Wemm #else /* COMPAT */ 3941c85e6a3SKirk McKusick && !isfree(super, dp) 39516c2ba93SPeter Wemm #endif /* COMPAT */ 39616c2ba93SPeter Wemm ) { 3971c85e6a3SKirk McKusick sz = estimate ? virtualblocks(super, dp) : 3981c85e6a3SKirk McKusick actualblocks(super, dp); 39916c2ba93SPeter Wemm #ifdef COMPAT 40016c2ba93SPeter Wemm if (sz >= FSZCNT) { 40116c2ba93SPeter Wemm fsizes->fsz_count[FSZCNT-1]++; 40216c2ba93SPeter Wemm fsizes->fsz_sz[FSZCNT-1] += sz; 40316c2ba93SPeter Wemm } else { 40416c2ba93SPeter Wemm fsizes->fsz_count[sz]++; 40516c2ba93SPeter Wemm fsizes->fsz_sz[sz] += sz; 40616c2ba93SPeter Wemm } 40716c2ba93SPeter Wemm #else /* COMPAT */ 40816c2ba93SPeter Wemm ksz = SIZE(sz); 4096980f0ebSPhilippe Charnier for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) { 41016c2ba93SPeter Wemm if (ksz < fp->fsz_last) 41116c2ba93SPeter Wemm break; 41216c2ba93SPeter Wemm } 41316c2ba93SPeter Wemm if (!fp || ksz < fp->fsz_first) { 41416c2ba93SPeter Wemm if (!(fp = (struct fsizes *) 4156980f0ebSPhilippe Charnier malloc(sizeof(struct fsizes)))) 416652b7200SPhilippe Charnier errx(1, "allocate fsize structure"); 41716c2ba93SPeter Wemm fp->fsz_next = *fsp; 41816c2ba93SPeter Wemm *fsp = fp; 4196e560addSPedro F. Giffuni fp->fsz_first = rounddown(ksz, FSZCNT); 42016c2ba93SPeter Wemm fp->fsz_last = fp->fsz_first + FSZCNT; 42116c2ba93SPeter Wemm for (i = FSZCNT; --i >= 0;) { 42216c2ba93SPeter Wemm fp->fsz_count[i] = 0; 42316c2ba93SPeter Wemm fp->fsz_sz[i] = 0; 42416c2ba93SPeter Wemm } 42516c2ba93SPeter Wemm } 42616c2ba93SPeter Wemm fp->fsz_count[ksz % FSZCNT]++; 42716c2ba93SPeter Wemm fp->fsz_sz[ksz % FSZCNT] += sz; 42816c2ba93SPeter Wemm #endif /* COMPAT */ 42916c2ba93SPeter Wemm } else if (errno) { 4306980f0ebSPhilippe Charnier err(1, "%s", name); 43116c2ba93SPeter Wemm } 43216c2ba93SPeter Wemm } 43316c2ba93SPeter Wemm sz = 0; 43416c2ba93SPeter Wemm for (fp = fsizes; fp; fp = fp->fsz_next) { 43516c2ba93SPeter Wemm for (i = 0; i < FSZCNT; i++) { 43616c2ba93SPeter Wemm if (fp->fsz_count[i]) 4379f60cc9eSDag-Erling Smørgrav printf("%jd\t%jd\t%d\n", 4389f60cc9eSDag-Erling Smørgrav (intmax_t)(fp->fsz_first + i), 4399f60cc9eSDag-Erling Smørgrav (intmax_t)fp->fsz_count[i], 44016c2ba93SPeter Wemm SIZE(sz += fp->fsz_sz[i])); 44116c2ba93SPeter Wemm } 44216c2ba93SPeter Wemm } 44316c2ba93SPeter Wemm } 44416c2ba93SPeter Wemm 4456980f0ebSPhilippe Charnier static void 4468f518424SDag-Erling Smørgrav douser(int fd, struct fs *super, char *name) 44716c2ba93SPeter Wemm { 44816c2ba93SPeter Wemm ino_t inode, maxino; 44916c2ba93SPeter Wemm struct user *usr, *usrs; 4501c85e6a3SKirk McKusick union dinode *dp; 4518f518424SDag-Erling Smørgrav int n; 45216c2ba93SPeter Wemm 45316c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 45416c2ba93SPeter Wemm for (inode = 0; inode < maxino; inode++) { 45516c2ba93SPeter Wemm errno = 0; 4561c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 4571c85e6a3SKirk McKusick && !isfree(super, dp)) 4581c85e6a3SKirk McKusick uses(DIP(super, dp, di_uid), 4591c85e6a3SKirk McKusick estimate ? virtualblocks(super, dp) : 4601c85e6a3SKirk McKusick actualblocks(super, dp), 4611c85e6a3SKirk McKusick DIP(super, dp, di_atime)); 46216c2ba93SPeter Wemm else if (errno) { 4636980f0ebSPhilippe Charnier err(1, "%s", name); 46416c2ba93SPeter Wemm } 46516c2ba93SPeter Wemm } 4666980f0ebSPhilippe Charnier if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user)))) 4676980f0ebSPhilippe Charnier errx(1, "allocate users"); 46816c2ba93SPeter Wemm bcopy(users,usrs,nusers * sizeof(struct user)); 46916c2ba93SPeter Wemm sortusers(usrs); 47016c2ba93SPeter Wemm for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) { 47116c2ba93SPeter Wemm printf("%5d",SIZE(usr->space)); 47216c2ba93SPeter Wemm if (count) 47357cdc152SMike Heffner printf("\t%5ld",usr->count); 47416c2ba93SPeter Wemm printf("\t%-8s",usr->name); 47516c2ba93SPeter Wemm if (unused) 47616c2ba93SPeter Wemm printf("\t%5d\t%5d\t%5d", 47716c2ba93SPeter Wemm SIZE(usr->spc30), 47816c2ba93SPeter Wemm SIZE(usr->spc60), 47916c2ba93SPeter Wemm SIZE(usr->spc90)); 48016c2ba93SPeter Wemm printf("\n"); 48116c2ba93SPeter Wemm } 48216c2ba93SPeter Wemm free(usrs); 48316c2ba93SPeter Wemm } 48416c2ba93SPeter Wemm 4856980f0ebSPhilippe Charnier static void 4868f518424SDag-Erling Smørgrav donames(int fd, struct fs *super, char *name) 48716c2ba93SPeter Wemm { 48816c2ba93SPeter Wemm int c; 48916c2ba93SPeter Wemm ino_t maxino; 490b424efd5SMatthew D Fleming uintmax_t inode; 4911c85e6a3SKirk McKusick union dinode *dp; 49216c2ba93SPeter Wemm 49316c2ba93SPeter Wemm maxino = super->fs_ncg * super->fs_ipg - 1; 49416c2ba93SPeter Wemm /* first skip the name of the filesystem */ 49516c2ba93SPeter Wemm while ((c = getchar()) != EOF && (c < '0' || c > '9')) 49616c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n'); 49716c2ba93SPeter Wemm ungetc(c,stdin); 498b424efd5SMatthew D Fleming while (scanf("%ju", &inode) == 1) { 49957cdc152SMike Heffner if (inode > maxino) { 500b424efd5SMatthew D Fleming warnx("illegal inode %ju", inode); 50116c2ba93SPeter Wemm return; 50216c2ba93SPeter Wemm } 50316c2ba93SPeter Wemm errno = 0; 5041c85e6a3SKirk McKusick if ((dp = get_inode(fd,super,inode)) 5051c85e6a3SKirk McKusick && !isfree(super, dp)) { 5061c85e6a3SKirk McKusick printf("%s\t",user(DIP(super, dp, di_uid))->name); 50716c2ba93SPeter Wemm /* now skip whitespace */ 50816c2ba93SPeter Wemm while ((c = getchar()) == ' ' || c == '\t'); 50916c2ba93SPeter Wemm /* and print out the remainder of the input line */ 51016c2ba93SPeter Wemm while (c != EOF && c != '\n') { 51116c2ba93SPeter Wemm putchar(c); 51216c2ba93SPeter Wemm c = getchar(); 51316c2ba93SPeter Wemm } 51416c2ba93SPeter Wemm putchar('\n'); 51516c2ba93SPeter Wemm } else { 51616c2ba93SPeter Wemm if (errno) { 5176980f0ebSPhilippe Charnier err(1, "%s", name); 51816c2ba93SPeter Wemm } 51916c2ba93SPeter Wemm /* skip this line */ 52016c2ba93SPeter Wemm while ((c = getchar()) != EOF && c != '\n'); 52116c2ba93SPeter Wemm } 52216c2ba93SPeter Wemm if (c == EOF) 52316c2ba93SPeter Wemm break; 52416c2ba93SPeter Wemm } 52516c2ba93SPeter Wemm } 52616c2ba93SPeter Wemm 5276980f0ebSPhilippe Charnier static void 5288f518424SDag-Erling Smørgrav usage(void) 52916c2ba93SPeter Wemm { 53016c2ba93SPeter Wemm #ifdef COMPAT 5316980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n"); 53216c2ba93SPeter Wemm #else /* COMPAT */ 5336980f0ebSPhilippe Charnier fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n"); 53416c2ba93SPeter Wemm #endif /* COMPAT */ 53516c2ba93SPeter Wemm exit(1); 53616c2ba93SPeter Wemm } 53716c2ba93SPeter Wemm 5381c85e6a3SKirk McKusick /* 5391c85e6a3SKirk McKusick * Possible superblock locations ordered from most to least likely. 5401c85e6a3SKirk McKusick */ 5411c85e6a3SKirk McKusick static int sblock_try[] = SBLOCKSEARCH; 5421c85e6a3SKirk McKusick static char superblock[SBLOCKSIZE]; 54316c2ba93SPeter Wemm 5446980f0ebSPhilippe Charnier void 5458f518424SDag-Erling Smørgrav quot(char *name, char *mp) 54616c2ba93SPeter Wemm { 5471c85e6a3SKirk McKusick int i, fd; 5481c85e6a3SKirk McKusick struct fs *fs; 54916c2ba93SPeter Wemm 55057cdc152SMike Heffner get_inode(-1, NULL, 0); /* flush cache */ 55116c2ba93SPeter Wemm inituser(); 55216c2ba93SPeter Wemm initfsizes(); 5531c85e6a3SKirk McKusick if ((fd = open(name,0)) < 0) { 5546980f0ebSPhilippe Charnier warn("%s", name); 55516c2ba93SPeter Wemm close(fd); 55616c2ba93SPeter Wemm return; 55716c2ba93SPeter Wemm } 5581c85e6a3SKirk McKusick for (i = 0; sblock_try[i] != -1; i++) { 5591c85e6a3SKirk McKusick if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) { 5601c85e6a3SKirk McKusick close(fd); 5611c85e6a3SKirk McKusick return; 5621c85e6a3SKirk McKusick } 5631c85e6a3SKirk McKusick if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) { 5641c85e6a3SKirk McKusick close(fd); 5651c85e6a3SKirk McKusick return; 5661c85e6a3SKirk McKusick } 5671c85e6a3SKirk McKusick fs = (struct fs *)superblock; 5681c85e6a3SKirk McKusick if ((fs->fs_magic == FS_UFS1_MAGIC || 5691c85e6a3SKirk McKusick (fs->fs_magic == FS_UFS2_MAGIC && 5706c45bec6STim J. Robbins fs->fs_sblockloc == sblock_try[i])) && 5711c85e6a3SKirk McKusick fs->fs_bsize <= MAXBSIZE && 5721c85e6a3SKirk McKusick fs->fs_bsize >= sizeof(struct fs)) 5731c85e6a3SKirk McKusick break; 5741c85e6a3SKirk McKusick } 5751c85e6a3SKirk McKusick if (sblock_try[i] == -1) { 5766980f0ebSPhilippe Charnier warnx("%s: not a BSD filesystem",name); 57716c2ba93SPeter Wemm close(fd); 57816c2ba93SPeter Wemm return; 57916c2ba93SPeter Wemm } 58016c2ba93SPeter Wemm printf("%s:",name); 58116c2ba93SPeter Wemm if (mp) 58216c2ba93SPeter Wemm printf(" (%s)",mp); 58316c2ba93SPeter Wemm putchar('\n'); 5841c85e6a3SKirk McKusick (*func)(fd, fs, name); 58516c2ba93SPeter Wemm close(fd); 58616c2ba93SPeter Wemm } 58716c2ba93SPeter Wemm 5886980f0ebSPhilippe Charnier int 5898f518424SDag-Erling Smørgrav main(int argc, char *argv[]) 59016c2ba93SPeter Wemm { 59116c2ba93SPeter Wemm char all = 0; 59216c2ba93SPeter Wemm struct statfs *mp; 59381f1ec27SPaul Saab struct fstab *fs; 59416c2ba93SPeter Wemm int cnt; 59516c2ba93SPeter Wemm 59616c2ba93SPeter Wemm func = douser; 59716c2ba93SPeter Wemm #ifndef COMPAT 59816c2ba93SPeter Wemm header = getbsize(&headerlen,&blocksize); 59916c2ba93SPeter Wemm #endif 60016c2ba93SPeter Wemm while (--argc > 0 && **++argv == '-') { 60116c2ba93SPeter Wemm while (*++*argv) { 60216c2ba93SPeter Wemm switch (**argv) { 60316c2ba93SPeter Wemm case 'n': 60416c2ba93SPeter Wemm func = donames; 60516c2ba93SPeter Wemm break; 60616c2ba93SPeter Wemm case 'c': 60716c2ba93SPeter Wemm func = dofsizes; 60816c2ba93SPeter Wemm break; 60916c2ba93SPeter Wemm case 'a': 61016c2ba93SPeter Wemm all = 1; 61116c2ba93SPeter Wemm break; 61216c2ba93SPeter Wemm case 'f': 61316c2ba93SPeter Wemm count = 1; 61416c2ba93SPeter Wemm break; 61516c2ba93SPeter Wemm case 'h': 61616c2ba93SPeter Wemm estimate = 1; 61716c2ba93SPeter Wemm break; 61816c2ba93SPeter Wemm #ifndef COMPAT 61916c2ba93SPeter Wemm case 'k': 62016c2ba93SPeter Wemm blocksize = 1024; 62116c2ba93SPeter Wemm break; 62216c2ba93SPeter Wemm #endif /* COMPAT */ 62316c2ba93SPeter Wemm case 'v': 62416c2ba93SPeter Wemm unused = 1; 62516c2ba93SPeter Wemm break; 62616c2ba93SPeter Wemm default: 62716c2ba93SPeter Wemm usage(); 62816c2ba93SPeter Wemm } 62916c2ba93SPeter Wemm } 63016c2ba93SPeter Wemm } 63116c2ba93SPeter Wemm if (all) { 63216c2ba93SPeter Wemm cnt = getmntinfo(&mp,MNT_NOWAIT); 63316c2ba93SPeter Wemm for (; --cnt >= 0; mp++) { 634b4eca767SEd Schouten if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) 635b4eca767SEd Schouten quot(mp->f_mntfromname, mp->f_mntonname); 63616c2ba93SPeter Wemm } 63716c2ba93SPeter Wemm } 63881f1ec27SPaul Saab while (--argc >= 0) { 63981f1ec27SPaul Saab if ((fs = getfsfile(*argv)) != NULL) 64081f1ec27SPaul Saab quot(fs->fs_spec, 0); 64181f1ec27SPaul Saab else 64281f1ec27SPaul Saab quot(*argv,0); 64381f1ec27SPaul Saab argv++; 64481f1ec27SPaul Saab } 64516c2ba93SPeter Wemm return 0; 64616c2ba93SPeter Wemm } 647