112032Speter/* 212032Speter * Copyright (C) 1991, 1994 Wolfgang Solfrank. 312032Speter * Copyright (C) 1991, 1994 TooLs GmbH. 412032Speter * All rights reserved. 512032Speter * 612032Speter * Redistribution and use in source and binary forms, with or without 712032Speter * modification, are permitted provided that the following conditions 812032Speter * are met: 912032Speter * 1. Redistributions of source code must retain the above copyright 1012032Speter * notice, this list of conditions and the following disclaimer. 1112032Speter * 2. Redistributions in binary form must reproduce the above copyright 1212032Speter * notice, this list of conditions and the following disclaimer in the 1312032Speter * documentation and/or other materials provided with the distribution. 1412032Speter * 3. All advertising materials mentioning features or use of this software 1512032Speter * must display the following acknowledgement: 1612032Speter * This product includes software developed by TooLs GmbH. 1712032Speter * 4. The name of TooLs GmbH may not be used to endorse or promote products 1812032Speter * derived from this software without specific prior written permission. 1912032Speter * 2012032Speter * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 2112032Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2212032Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2312032Speter * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2412032Speter * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2512032Speter * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2612032Speter * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2712032Speter * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2812032Speter * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2912032Speter * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3012032Speter */ 3112032Speter 32114601Sobrien#include <sys/cdefs.h> 33114601Sobrien__FBSDID("$FreeBSD$"); 3412032Speter 3512032Speter#include <sys/param.h> 3696638Sdes#include <sys/stdint.h> 3712032Speter#include <sys/mount.h> 3896479Sphk#include <sys/disklabel.h> 3998542Smckusick#include <ufs/ufs/dinode.h> 4012032Speter#include <ufs/ffs/fs.h> 4112032Speter 4230262Scharnier#include <err.h> 4330262Scharnier#include <fcntl.h> 4474071Sps#include <fstab.h> 4530262Scharnier#include <errno.h> 4669793Sobrien#include <paths.h> 4730262Scharnier#include <pwd.h> 4812032Speter#include <stdio.h> 4912032Speter#include <stdlib.h> 5012032Speter#include <string.h> 51217769Smckusick#include <time.h> 5230262Scharnier#include <unistd.h> 5312032Speter 5412032Speter/* some flags of what to do: */ 5512032Speterstatic char estimate; 5612032Speterstatic char count; 5712032Speterstatic char unused; 5887554Smikehstatic void (*func)(int, struct fs *, char *); 5912032Speterstatic long blocksize; 6012032Speterstatic char *header; 61108458Smikestatic int headerlen; 6212032Speter 6398542Smckusickstatic union dinode *get_inode(int, struct fs *, ino_t); 6498542Smckusickstatic int virtualblocks(struct fs *, union dinode *); 6598542Smckusickstatic int isfree(struct fs *, union dinode *); 6687554Smikehstatic void inituser(void); 6787554Smikehstatic void usrrehash(void); 6887554Smikehstatic struct user *user(uid_t); 6987554Smikehstatic int cmpusers(const void *, const void *); 7087554Smikehstatic void uses(uid_t, daddr_t, time_t); 7187554Smikehstatic void initfsizes(void); 7287554Smikehstatic void dofsizes(int, struct fs *, char *); 7387554Smikehstatic void douser(int, struct fs *, char *); 7487554Smikehstatic void donames(int, struct fs *, char *); 7587554Smikehstatic void usage(void); 7687554Smikehstatic void quot(char *, char *); 7787554Smikeh 7812032Speter/* 7912032Speter * Original BSD quot doesn't round to number of frags/blocks, 8012032Speter * doesn't account for indirection blocks and gets it totally 8112032Speter * wrong if the size is a multiple of the blocksize. 8212032Speter * The new code always counts the number of 512 byte blocks 8312032Speter * instead of the number of kilobytes and converts them to 8412032Speter * kByte when done (on request). 8541727Sdillon * 8641727Sdillon * Due to the size of modern disks, we must cast intermediate 8741727Sdillon * values to 64 bits to prevent potential overflows. 8812032Speter */ 8912032Speter#ifdef COMPAT 9012032Speter#define SIZE(n) (n) 9112032Speter#else 9241727Sdillon#define SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize)) 9312032Speter#endif 9412032Speter 9512032Speter#define INOCNT(fs) ((fs)->fs_ipg) 9698542Smckusick#define INOSZ(fs) \ 9798542Smckusick (((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \ 9898542Smckusick sizeof(struct ufs2_dinode)) * INOCNT(fs)) 9912032Speter 10098542Smckusickunion dinode { 10198542Smckusick struct ufs1_dinode dp1; 10298542Smckusick struct ufs2_dinode dp2; 10398542Smckusick}; 10498542Smckusick#define DIP(fs, dp, field) \ 10598542Smckusick (((fs)->fs_magic == FS_UFS1_MAGIC) ? \ 10698542Smckusick (dp)->dp1.field : (dp)->dp2.field) 10798542Smckusick 10898542Smckusickstatic union dinode * 109180187Sdesget_inode(int fd, struct fs *super, ino_t ino) 11012032Speter{ 11198542Smckusick static caddr_t ipbuf; 112156015Sdwmalone static struct cg *cgp; 11312032Speter static ino_t last; 114156015Sdwmalone static int cg; 115156015Sdwmalone struct ufs2_dinode *di2; 116180187Sdes 11712032Speter if (fd < 0) { /* flush cache */ 11898542Smckusick if (ipbuf) { 11998542Smckusick free(ipbuf); 12098542Smckusick ipbuf = 0; 121162831Smaxim if (super != NULL && super->fs_magic == FS_UFS2_MAGIC) { 122156015Sdwmalone free(cgp); 123156015Sdwmalone cgp = 0; 124156015Sdwmalone } 12512032Speter } 12612032Speter return 0; 12712032Speter } 128180187Sdes 12998542Smckusick if (!ipbuf || ino < last || ino >= last + INOCNT(super)) { 130156015Sdwmalone if (super->fs_magic == FS_UFS2_MAGIC && 131156015Sdwmalone (!cgp || cg != ino_to_cg(super, ino))) { 132156015Sdwmalone cg = ino_to_cg(super, ino); 133156015Sdwmalone if (!cgp && !(cgp = malloc(super->fs_cgsize))) 134156015Sdwmalone errx(1, "allocate cg"); 135156015Sdwmalone if (lseek(fd, (off_t)cgtod(super, cg) << super->fs_fshift, 0) < 0) 136156015Sdwmalone err(1, "lseek cg"); 137156015Sdwmalone if (read(fd, cgp, super->fs_cgsize) != super->fs_cgsize) 138156015Sdwmalone err(1, "read cg"); 139156015Sdwmalone if (!cg_chkmagic(cgp)) 140156015Sdwmalone errx(1, "cg has bad magic"); 141156015Sdwmalone } 14298542Smckusick if (!ipbuf 14398542Smckusick && !(ipbuf = malloc(INOSZ(super)))) 14430262Scharnier errx(1, "allocate inodes"); 14512032Speter last = (ino / INOCNT(super)) * INOCNT(super); 14628160Sjkh if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0 14798542Smckusick || read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super)) 14830262Scharnier err(1, "read inodes"); 14912032Speter } 150180187Sdes 15198542Smckusick if (super->fs_magic == FS_UFS1_MAGIC) 15298542Smckusick return ((union dinode *) 15398542Smckusick &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]); 154156015Sdwmalone di2 = &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]; 155156015Sdwmalone /* If the inode is unused, it might be unallocated too, so zero it. */ 156156015Sdwmalone if (isclr(cg_inosused(cgp), ino % super->fs_ipg)) 157156015Sdwmalone bzero(di2, sizeof (*di2)); 158156015Sdwmalone return ((union dinode *)di2); 15912032Speter} 16012032Speter 16112032Speter#ifdef COMPAT 16298542Smckusick#define actualblocks(fs, dp) (DIP(fs, dp, di_blocks) / 2) 16312032Speter#else 16498542Smckusick#define actualblocks(fs, dp) DIP(fs, dp, di_blocks) 16512032Speter#endif 16612032Speter 167180187Sdesstatic int virtualblocks(struct fs *super, union dinode *dp) 16812032Speter{ 169180187Sdes off_t nblk, sz; 170180187Sdes 17198542Smckusick sz = DIP(super, dp, di_size); 17212032Speter#ifdef COMPAT 17312032Speter if (lblkno(super,sz) >= NDADDR) { 17412032Speter nblk = blkroundup(super,sz); 17512032Speter if (sz == nblk) 17612032Speter nblk += super->fs_bsize; 17712032Speter } 178180187Sdes 17912032Speter return sz / 1024; 180180187Sdes 18112032Speter#else /* COMPAT */ 182180187Sdes 18312032Speter if (lblkno(super,sz) >= NDADDR) { 18412032Speter nblk = blkroundup(super,sz); 18512032Speter sz = lblkno(super,nblk); 18612032Speter sz = (sz - NDADDR + NINDIR(super) - 1) / NINDIR(super); 18712032Speter while (sz > 0) { 18812032Speter nblk += sz * super->fs_bsize; 18912032Speter /* sz - 1 rounded up */ 19012032Speter sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super); 19112032Speter } 19212032Speter } else 19312032Speter nblk = fragroundup(super,sz); 194180187Sdes 19512032Speter return nblk / 512; 19612032Speter#endif /* COMPAT */ 19712032Speter} 19812032Speter 19930262Scharnierstatic int 200180187Sdesisfree(struct fs *super, union dinode *dp) 20112032Speter{ 20212032Speter#ifdef COMPAT 20398542Smckusick return (DIP(super, dp, di_mode) & IFMT) == 0; 20412032Speter#else /* COMPAT */ 205180187Sdes 20698542Smckusick switch (DIP(super, dp, di_mode) & IFMT) { 20712032Speter case IFIFO: 20812032Speter case IFLNK: /* should check FASTSYMLINK? */ 20912032Speter case IFDIR: 21012032Speter case IFREG: 21112032Speter return 0; 212156015Sdwmalone case IFCHR: 213156015Sdwmalone case IFBLK: 214156015Sdwmalone case IFSOCK: 215156015Sdwmalone case IFWHT: 216156015Sdwmalone case 0: 217156015Sdwmalone return 1; 21812032Speter default: 219156015Sdwmalone errx(1, "unknown IFMT 0%o", DIP(super, dp, di_mode) & IFMT); 22012032Speter } 22112032Speter#endif 22212032Speter} 22312032Speter 22412032Speterstatic struct user { 22512032Speter uid_t uid; 22612032Speter char *name; 22712032Speter daddr_t space; 22812032Speter long count; 22912032Speter daddr_t spc30; 23012032Speter daddr_t spc60; 23112032Speter daddr_t spc90; 23212032Speter} *users; 23312032Speterstatic int nusers; 23412032Speter 23530262Scharnierstatic void 236180187Sdesinituser(void) 23712032Speter{ 238180187Sdes int i; 239180187Sdes struct user *usr; 240180187Sdes 24112032Speter if (!nusers) { 24212032Speter nusers = 8; 24312032Speter if (!(users = 24430262Scharnier (struct user *)calloc(nusers,sizeof(struct user)))) 24530262Scharnier errx(1, "allocate users"); 24612032Speter } else { 24712032Speter for (usr = users, i = nusers; --i >= 0; usr++) { 24812032Speter usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0; 24912032Speter usr->count = 0; 25012032Speter } 25112032Speter } 25212032Speter} 25312032Speter 25430262Scharnierstatic void 255180187Sdesusrrehash(void) 25612032Speter{ 257180187Sdes int i; 258180187Sdes struct user *usr, *usrn; 25912032Speter struct user *svusr; 260180187Sdes 26112032Speter svusr = users; 26212032Speter nusers <<= 1; 26330262Scharnier if (!(users = (struct user *)calloc(nusers,sizeof(struct user)))) 26430262Scharnier errx(1, "allocate users"); 26512032Speter for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) { 26612032Speter for (usrn = users + (usr->uid&(nusers - 1)); usrn->name; 26712032Speter usrn--) { 26812032Speter if (usrn <= users) 26912032Speter usrn = users + nusers; 27012032Speter } 27112032Speter *usrn = *usr; 27212032Speter } 27312032Speter} 27412032Speter 27530262Scharnierstatic struct user * 276180187Sdesuser(uid_t uid) 27712032Speter{ 278180187Sdes struct user *usr; 279180187Sdes int i; 28012032Speter struct passwd *pwd; 281180187Sdes 28212032Speter while (1) { 28312032Speter for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0; 28412032Speter usr--) { 28512032Speter if (!usr->name) { 28612032Speter usr->uid = uid; 287180187Sdes 28812032Speter if (!(pwd = getpwuid(uid))) { 28930262Scharnier if ((usr->name = (char *)malloc(7))) 29012032Speter sprintf(usr->name,"#%d",uid); 29112032Speter } else { 29230262Scharnier if ((usr->name = (char *) 29330262Scharnier malloc(strlen(pwd->pw_name) + 1))) 29412032Speter strcpy(usr->name,pwd->pw_name); 29512032Speter } 29630262Scharnier if (!usr->name) 29730262Scharnier errx(1, "allocate users"); 298180187Sdes 29912032Speter return usr; 300180187Sdes 30112032Speter } else if (usr->uid == uid) 30212032Speter return usr; 30312032Speter 30412032Speter if (usr <= users) 30512032Speter usr = users + nusers; 30612032Speter } 30712032Speter usrrehash(); 30812032Speter } 30912032Speter} 31012032Speter 31130262Scharnierstatic int 312180187Sdescmpusers(const void *v1, const void *v2) 31312032Speter{ 31487554Smikeh const struct user *u1, *u2; 31587554Smikeh u1 = (const struct user *)v1; 31687554Smikeh u2 = (const struct user *)v2; 31787554Smikeh 31812032Speter return u2->space - u1->space; 31912032Speter} 32012032Speter 32112032Speter#define sortusers(users) (qsort((users),nusers,sizeof(struct user), \ 32212032Speter cmpusers)) 32312032Speter 32430262Scharnierstatic void 325180187Sdesuses(uid_t uid, daddr_t blks, time_t act) 32612032Speter{ 32712032Speter static time_t today; 328180187Sdes struct user *usr; 329180187Sdes 33012032Speter if (!today) 33112032Speter time(&today); 332180187Sdes 33312032Speter usr = user(uid); 33412032Speter usr->count++; 33512032Speter usr->space += blks; 336180187Sdes 33712032Speter if (today - act > 90L * 24L * 60L * 60L) 33812032Speter usr->spc90 += blks; 33912032Speter if (today - act > 60L * 24L * 60L * 60L) 34012032Speter usr->spc60 += blks; 34112032Speter if (today - act > 30L * 24L * 60L * 60L) 34212032Speter usr->spc30 += blks; 34312032Speter} 34412032Speter 34512032Speter#ifdef COMPAT 34612032Speter#define FSZCNT 500 34712032Speter#else 34812032Speter#define FSZCNT 512 34912032Speter#endif 35012032Speterstruct fsizes { 35112032Speter struct fsizes *fsz_next; 35212032Speter daddr_t fsz_first, fsz_last; 35312032Speter ino_t fsz_count[FSZCNT]; 35412032Speter daddr_t fsz_sz[FSZCNT]; 35512032Speter} *fsizes; 35612032Speter 35730262Scharnierstatic void 358180187Sdesinitfsizes(void) 35912032Speter{ 360180187Sdes struct fsizes *fp; 361180187Sdes int i; 362180187Sdes 36312032Speter for (fp = fsizes; fp; fp = fp->fsz_next) { 36412032Speter for (i = FSZCNT; --i >= 0;) { 36512032Speter fp->fsz_count[i] = 0; 36612032Speter fp->fsz_sz[i] = 0; 36712032Speter } 36812032Speter } 36912032Speter} 37012032Speter 37130262Scharnierstatic void 372180187Sdesdofsizes(int fd, struct fs *super, char *name) 37312032Speter{ 37412032Speter ino_t inode, maxino; 37598542Smckusick union dinode *dp; 37612032Speter daddr_t sz, ksz; 37712032Speter struct fsizes *fp, **fsp; 378180187Sdes int i; 379180187Sdes 38012032Speter maxino = super->fs_ncg * super->fs_ipg - 1; 38112032Speter#ifdef COMPAT 38230262Scharnier if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes)))) 38353764Scharnier errx(1, "allocate fsize structure"); 38412032Speter#endif /* COMPAT */ 38512032Speter for (inode = 0; inode < maxino; inode++) { 38612032Speter errno = 0; 38798542Smckusick if ((dp = get_inode(fd,super,inode)) 38812032Speter#ifdef COMPAT 38998542Smckusick && ((DIP(super, dp, di_mode) & IFMT) == IFREG 39098542Smckusick || (DIP(super, dp, di_mode) & IFMT) == IFDIR) 39112032Speter#else /* COMPAT */ 39298542Smckusick && !isfree(super, dp) 39312032Speter#endif /* COMPAT */ 39412032Speter ) { 39598542Smckusick sz = estimate ? virtualblocks(super, dp) : 39698542Smckusick actualblocks(super, dp); 39712032Speter#ifdef COMPAT 39812032Speter if (sz >= FSZCNT) { 39912032Speter fsizes->fsz_count[FSZCNT-1]++; 40012032Speter fsizes->fsz_sz[FSZCNT-1] += sz; 40112032Speter } else { 40212032Speter fsizes->fsz_count[sz]++; 40312032Speter fsizes->fsz_sz[sz] += sz; 40412032Speter } 40512032Speter#else /* COMPAT */ 40612032Speter ksz = SIZE(sz); 40730262Scharnier for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) { 40812032Speter if (ksz < fp->fsz_last) 40912032Speter break; 41012032Speter } 41112032Speter if (!fp || ksz < fp->fsz_first) { 41212032Speter if (!(fp = (struct fsizes *) 41330262Scharnier malloc(sizeof(struct fsizes)))) 41453764Scharnier errx(1, "allocate fsize structure"); 41512032Speter fp->fsz_next = *fsp; 41612032Speter *fsp = fp; 41712032Speter fp->fsz_first = (ksz / FSZCNT) * FSZCNT; 41812032Speter fp->fsz_last = fp->fsz_first + FSZCNT; 41912032Speter for (i = FSZCNT; --i >= 0;) { 42012032Speter fp->fsz_count[i] = 0; 42112032Speter fp->fsz_sz[i] = 0; 42212032Speter } 42312032Speter } 42412032Speter fp->fsz_count[ksz % FSZCNT]++; 42512032Speter fp->fsz_sz[ksz % FSZCNT] += sz; 42612032Speter#endif /* COMPAT */ 42712032Speter } else if (errno) { 42830262Scharnier err(1, "%s", name); 42912032Speter } 43012032Speter } 43112032Speter sz = 0; 43212032Speter for (fp = fsizes; fp; fp = fp->fsz_next) { 43312032Speter for (i = 0; i < FSZCNT; i++) { 43412032Speter if (fp->fsz_count[i]) 43596638Sdes printf("%jd\t%jd\t%d\n", 43696638Sdes (intmax_t)(fp->fsz_first + i), 43796638Sdes (intmax_t)fp->fsz_count[i], 43812032Speter SIZE(sz += fp->fsz_sz[i])); 43912032Speter } 44012032Speter } 44112032Speter} 44212032Speter 44330262Scharnierstatic void 444180187Sdesdouser(int fd, struct fs *super, char *name) 44512032Speter{ 44612032Speter ino_t inode, maxino; 44712032Speter struct user *usr, *usrs; 44898542Smckusick union dinode *dp; 449180187Sdes int n; 450180187Sdes 45112032Speter maxino = super->fs_ncg * super->fs_ipg - 1; 45212032Speter for (inode = 0; inode < maxino; inode++) { 45312032Speter errno = 0; 45498542Smckusick if ((dp = get_inode(fd,super,inode)) 45598542Smckusick && !isfree(super, dp)) 45698542Smckusick uses(DIP(super, dp, di_uid), 45798542Smckusick estimate ? virtualblocks(super, dp) : 45898542Smckusick actualblocks(super, dp), 45998542Smckusick DIP(super, dp, di_atime)); 46012032Speter else if (errno) { 46130262Scharnier err(1, "%s", name); 46212032Speter } 46312032Speter } 46430262Scharnier if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user)))) 46530262Scharnier errx(1, "allocate users"); 46612032Speter bcopy(users,usrs,nusers * sizeof(struct user)); 46712032Speter sortusers(usrs); 46812032Speter for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) { 46912032Speter printf("%5d",SIZE(usr->space)); 47012032Speter if (count) 47187554Smikeh printf("\t%5ld",usr->count); 47212032Speter printf("\t%-8s",usr->name); 47312032Speter if (unused) 47412032Speter printf("\t%5d\t%5d\t%5d", 47512032Speter SIZE(usr->spc30), 47612032Speter SIZE(usr->spc60), 47712032Speter SIZE(usr->spc90)); 47812032Speter printf("\n"); 47912032Speter } 48012032Speter free(usrs); 48112032Speter} 48212032Speter 48330262Scharnierstatic void 484180187Sdesdonames(int fd, struct fs *super, char *name) 48512032Speter{ 48612032Speter int c; 48712032Speter ino_t maxino; 488241015Smdf uintmax_t inode; 48998542Smckusick union dinode *dp; 490180187Sdes 49112032Speter maxino = super->fs_ncg * super->fs_ipg - 1; 49212032Speter /* first skip the name of the filesystem */ 49312032Speter while ((c = getchar()) != EOF && (c < '0' || c > '9')) 49412032Speter while ((c = getchar()) != EOF && c != '\n'); 49512032Speter ungetc(c,stdin); 496241015Smdf while (scanf("%ju", &inode) == 1) { 49787554Smikeh if (inode > maxino) { 498241015Smdf warnx("illegal inode %ju", inode); 49912032Speter return; 50012032Speter } 50112032Speter errno = 0; 50298542Smckusick if ((dp = get_inode(fd,super,inode)) 50398542Smckusick && !isfree(super, dp)) { 50498542Smckusick printf("%s\t",user(DIP(super, dp, di_uid))->name); 50512032Speter /* now skip whitespace */ 50612032Speter while ((c = getchar()) == ' ' || c == '\t'); 50712032Speter /* and print out the remainder of the input line */ 50812032Speter while (c != EOF && c != '\n') { 50912032Speter putchar(c); 51012032Speter c = getchar(); 51112032Speter } 51212032Speter putchar('\n'); 51312032Speter } else { 51412032Speter if (errno) { 51530262Scharnier err(1, "%s", name); 51612032Speter } 51712032Speter /* skip this line */ 51812032Speter while ((c = getchar()) != EOF && c != '\n'); 51912032Speter } 52012032Speter if (c == EOF) 52112032Speter break; 52212032Speter } 52312032Speter} 52412032Speter 52530262Scharnierstatic void 526180187Sdesusage(void) 52712032Speter{ 52812032Speter#ifdef COMPAT 52930262Scharnier fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n"); 53012032Speter#else /* COMPAT */ 53153764Scharnier fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n"); 53212032Speter#endif /* COMPAT */ 53312032Speter exit(1); 53412032Speter} 53512032Speter 53698542Smckusick/* 53798542Smckusick * Possible superblock locations ordered from most to least likely. 53898542Smckusick */ 53998542Smckusickstatic int sblock_try[] = SBLOCKSEARCH; 54098542Smckusickstatic char superblock[SBLOCKSIZE]; 54112032Speter 54230262Scharniervoid 543180187Sdesquot(char *name, char *mp) 54412032Speter{ 54598542Smckusick int i, fd; 54698542Smckusick struct fs *fs; 547180187Sdes 54887554Smikeh get_inode(-1, NULL, 0); /* flush cache */ 54912032Speter inituser(); 55012032Speter initfsizes(); 55198542Smckusick if ((fd = open(name,0)) < 0) { 55230262Scharnier warn("%s", name); 55312032Speter close(fd); 55412032Speter return; 55512032Speter } 55698542Smckusick for (i = 0; sblock_try[i] != -1; i++) { 55798542Smckusick if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) { 55898542Smckusick close(fd); 55998542Smckusick return; 56098542Smckusick } 56198542Smckusick if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) { 56298542Smckusick close(fd); 56398542Smckusick return; 56498542Smckusick } 56598542Smckusick fs = (struct fs *)superblock; 56698542Smckusick if ((fs->fs_magic == FS_UFS1_MAGIC || 56798542Smckusick (fs->fs_magic == FS_UFS2_MAGIC && 568114009Stjr fs->fs_sblockloc == sblock_try[i])) && 56998542Smckusick fs->fs_bsize <= MAXBSIZE && 57098542Smckusick fs->fs_bsize >= sizeof(struct fs)) 57198542Smckusick break; 57298542Smckusick } 57398542Smckusick if (sblock_try[i] == -1) { 57430262Scharnier warnx("%s: not a BSD filesystem",name); 57512032Speter close(fd); 57612032Speter return; 57712032Speter } 57812032Speter printf("%s:",name); 57912032Speter if (mp) 58012032Speter printf(" (%s)",mp); 58112032Speter putchar('\n'); 58298542Smckusick (*func)(fd, fs, name); 58312032Speter close(fd); 58412032Speter} 58512032Speter 58630262Scharnierint 587180187Sdesmain(int argc, char *argv[]) 58812032Speter{ 58912032Speter char all = 0; 59012032Speter struct statfs *mp; 59174071Sps struct fstab *fs; 59212032Speter int cnt; 593180187Sdes 59412032Speter func = douser; 59512032Speter#ifndef COMPAT 59612032Speter header = getbsize(&headerlen,&blocksize); 59712032Speter#endif 59812032Speter while (--argc > 0 && **++argv == '-') { 59912032Speter while (*++*argv) { 60012032Speter switch (**argv) { 60112032Speter case 'n': 60212032Speter func = donames; 60312032Speter break; 60412032Speter case 'c': 60512032Speter func = dofsizes; 60612032Speter break; 60712032Speter case 'a': 60812032Speter all = 1; 60912032Speter break; 61012032Speter case 'f': 61112032Speter count = 1; 61212032Speter break; 61312032Speter case 'h': 61412032Speter estimate = 1; 61512032Speter break; 61612032Speter#ifndef COMPAT 61712032Speter case 'k': 61812032Speter blocksize = 1024; 61912032Speter break; 62012032Speter#endif /* COMPAT */ 62112032Speter case 'v': 62212032Speter unused = 1; 62312032Speter break; 62412032Speter default: 62512032Speter usage(); 62612032Speter } 62712032Speter } 62812032Speter } 62912032Speter if (all) { 63012032Speter cnt = getmntinfo(&mp,MNT_NOWAIT); 63112032Speter for (; --cnt >= 0; mp++) { 632183018Sed if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) 633183018Sed quot(mp->f_mntfromname, mp->f_mntonname); 63412032Speter } 63512032Speter } 63674071Sps while (--argc >= 0) { 63774071Sps if ((fs = getfsfile(*argv)) != NULL) 63874071Sps quot(fs->fs_spec, 0); 63974071Sps else 64074071Sps quot(*argv,0); 64174071Sps argv++; 64274071Sps } 64312032Speter return 0; 64412032Speter} 645