quot.c revision 108458
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 3212032Speter#ifndef lint 3330262Scharnierstatic const char rcsid[] = 3450479Speter "$FreeBSD: head/usr.sbin/quot/quot.c 108458 2002-12-30 18:21:47Z mike $"; 3512032Speter#endif /* not lint */ 3612032Speter 3712032Speter#include <sys/param.h> 3896638Sdes#include <sys/stdint.h> 3912032Speter#include <sys/mount.h> 4096479Sphk#include <sys/disklabel.h> 4112032Speter#include <sys/time.h> 4298542Smckusick#include <ufs/ufs/dinode.h> 4312032Speter#include <ufs/ffs/fs.h> 4412032Speter 4530262Scharnier#include <err.h> 4630262Scharnier#include <fcntl.h> 4774071Sps#include <fstab.h> 4830262Scharnier#include <errno.h> 4969793Sobrien#include <paths.h> 5030262Scharnier#include <pwd.h> 5112032Speter#include <stdio.h> 5212032Speter#include <stdlib.h> 5312032Speter#include <string.h> 5430262Scharnier#include <unistd.h> 5512032Speter 5612032Speter/* some flags of what to do: */ 5712032Speterstatic char estimate; 5812032Speterstatic char count; 5912032Speterstatic char unused; 6087554Smikehstatic void (*func)(int, struct fs *, char *); 6112032Speterstatic long blocksize; 6212032Speterstatic char *header; 63108458Smikestatic int headerlen; 6412032Speter 6598542Smckusickstatic union dinode *get_inode(int, struct fs *, ino_t); 6698542Smckusickstatic int virtualblocks(struct fs *, union dinode *); 6798542Smckusickstatic int isfree(struct fs *, union dinode *); 6887554Smikehstatic void inituser(void); 6987554Smikehstatic void usrrehash(void); 7087554Smikehstatic struct user *user(uid_t); 7187554Smikehstatic int cmpusers(const void *, const void *); 7287554Smikehstatic void uses(uid_t, daddr_t, time_t); 7387554Smikehstatic void initfsizes(void); 7487554Smikehstatic void dofsizes(int, struct fs *, char *); 7587554Smikehstatic void douser(int, struct fs *, char *); 7687554Smikehstatic void donames(int, struct fs *, char *); 7787554Smikehstatic void usage(void); 7887554Smikehstatic void quot(char *, char *); 7987554Smikeh 8012032Speter/* 8112032Speter * Original BSD quot doesn't round to number of frags/blocks, 8212032Speter * doesn't account for indirection blocks and gets it totally 8312032Speter * wrong if the size is a multiple of the blocksize. 8412032Speter * The new code always counts the number of 512 byte blocks 8512032Speter * instead of the number of kilobytes and converts them to 8612032Speter * kByte when done (on request). 8741727Sdillon * 8841727Sdillon * Due to the size of modern disks, we must cast intermediate 8941727Sdillon * values to 64 bits to prevent potential overflows. 9012032Speter */ 9112032Speter#ifdef COMPAT 9212032Speter#define SIZE(n) (n) 9312032Speter#else 9441727Sdillon#define SIZE(n) ((int)(((quad_t)(n) * 512 + blocksize - 1)/blocksize)) 9512032Speter#endif 9612032Speter 9712032Speter#define INOCNT(fs) ((fs)->fs_ipg) 9898542Smckusick#define INOSZ(fs) \ 9998542Smckusick (((fs)->fs_magic == FS_UFS1_MAGIC ? sizeof(struct ufs1_dinode) : \ 10098542Smckusick sizeof(struct ufs2_dinode)) * INOCNT(fs)) 10112032Speter 10298542Smckusickunion dinode { 10398542Smckusick struct ufs1_dinode dp1; 10498542Smckusick struct ufs2_dinode dp2; 10598542Smckusick}; 10698542Smckusick#define DIP(fs, dp, field) \ 10798542Smckusick (((fs)->fs_magic == FS_UFS1_MAGIC) ? \ 10898542Smckusick (dp)->dp1.field : (dp)->dp2.field) 10998542Smckusick 11098542Smckusickstatic union dinode * 11130262Scharnierget_inode(fd,super,ino) 11287554Smikeh int fd; 11312032Speter struct fs *super; 11412032Speter ino_t ino; 11512032Speter{ 11698542Smckusick static caddr_t ipbuf; 11712032Speter static ino_t last; 11812032Speter 11912032Speter if (fd < 0) { /* flush cache */ 12098542Smckusick if (ipbuf) { 12198542Smckusick free(ipbuf); 12298542Smckusick ipbuf = 0; 12312032Speter } 12412032Speter return 0; 12512032Speter } 12612032Speter 12798542Smckusick if (!ipbuf || ino < last || ino >= last + INOCNT(super)) { 12898542Smckusick if (!ipbuf 12998542Smckusick && !(ipbuf = malloc(INOSZ(super)))) 13030262Scharnier errx(1, "allocate inodes"); 13112032Speter last = (ino / INOCNT(super)) * INOCNT(super); 13228160Sjkh if (lseek(fd, (off_t)ino_to_fsba(super, last) << super->fs_fshift, 0) < (off_t)0 13398542Smckusick || read(fd, ipbuf, INOSZ(super)) != (ssize_t)INOSZ(super)) 13430262Scharnier err(1, "read inodes"); 13512032Speter } 13612032Speter 13798542Smckusick if (super->fs_magic == FS_UFS1_MAGIC) 13898542Smckusick return ((union dinode *) 13998542Smckusick &((struct ufs1_dinode *)ipbuf)[ino % INOCNT(super)]); 14098542Smckusick return ((union dinode *) 14198542Smckusick &((struct ufs2_dinode *)ipbuf)[ino % INOCNT(super)]); 14212032Speter} 14312032Speter 14412032Speter#ifdef COMPAT 14598542Smckusick#define actualblocks(fs, dp) (DIP(fs, dp, di_blocks) / 2) 14612032Speter#else 14798542Smckusick#define actualblocks(fs, dp) DIP(fs, dp, di_blocks) 14812032Speter#endif 14912032Speter 15098542Smckusickstatic int virtualblocks(super, dp) 15112032Speter struct fs *super; 15298542Smckusick union dinode *dp; 15312032Speter{ 15412032Speter register off_t nblk, sz; 15512032Speter 15698542Smckusick sz = DIP(super, dp, di_size); 15712032Speter#ifdef COMPAT 15812032Speter if (lblkno(super,sz) >= NDADDR) { 15912032Speter nblk = blkroundup(super,sz); 16012032Speter if (sz == nblk) 16112032Speter nblk += super->fs_bsize; 16212032Speter } 16312032Speter 16412032Speter return sz / 1024; 16512032Speter 16612032Speter#else /* COMPAT */ 16712032Speter 16812032Speter if (lblkno(super,sz) >= NDADDR) { 16912032Speter nblk = blkroundup(super,sz); 17012032Speter sz = lblkno(super,nblk); 17112032Speter sz = (sz - NDADDR + NINDIR(super) - 1) / NINDIR(super); 17212032Speter while (sz > 0) { 17312032Speter nblk += sz * super->fs_bsize; 17412032Speter /* sz - 1 rounded up */ 17512032Speter sz = (sz - 1 + NINDIR(super) - 1) / NINDIR(super); 17612032Speter } 17712032Speter } else 17812032Speter nblk = fragroundup(super,sz); 17912032Speter 18012032Speter return nblk / 512; 18112032Speter#endif /* COMPAT */ 18212032Speter} 18312032Speter 18430262Scharnierstatic int 18598542Smckusickisfree(super, dp) 18698542Smckusick struct fs *super; 18798542Smckusick union dinode *dp; 18812032Speter{ 18912032Speter#ifdef COMPAT 19098542Smckusick return (DIP(super, dp, di_mode) & IFMT) == 0; 19112032Speter#else /* COMPAT */ 19212032Speter 19398542Smckusick switch (DIP(super, dp, di_mode) & IFMT) { 19412032Speter case IFIFO: 19512032Speter case IFLNK: /* should check FASTSYMLINK? */ 19612032Speter case IFDIR: 19712032Speter case IFREG: 19812032Speter return 0; 19912032Speter default: 20012032Speter return 1; 20112032Speter } 20212032Speter#endif 20312032Speter} 20412032Speter 20512032Speterstatic struct user { 20612032Speter uid_t uid; 20712032Speter char *name; 20812032Speter daddr_t space; 20912032Speter long count; 21012032Speter daddr_t spc30; 21112032Speter daddr_t spc60; 21212032Speter daddr_t spc90; 21312032Speter} *users; 21412032Speterstatic int nusers; 21512032Speter 21630262Scharnierstatic void 21730262Scharnierinituser() 21812032Speter{ 21987554Smikeh register int i; 22012032Speter register struct user *usr; 22112032Speter 22212032Speter if (!nusers) { 22312032Speter nusers = 8; 22412032Speter if (!(users = 22530262Scharnier (struct user *)calloc(nusers,sizeof(struct user)))) 22630262Scharnier errx(1, "allocate users"); 22712032Speter } else { 22812032Speter for (usr = users, i = nusers; --i >= 0; usr++) { 22912032Speter usr->space = usr->spc30 = usr->spc60 = usr->spc90 = 0; 23012032Speter usr->count = 0; 23112032Speter } 23212032Speter } 23312032Speter} 23412032Speter 23530262Scharnierstatic void 23630262Scharnierusrrehash() 23712032Speter{ 23887554Smikeh register int i; 23912032Speter register struct user *usr, *usrn; 24012032Speter struct user *svusr; 24112032Speter 24212032Speter svusr = users; 24312032Speter nusers <<= 1; 24430262Scharnier if (!(users = (struct user *)calloc(nusers,sizeof(struct user)))) 24530262Scharnier errx(1, "allocate users"); 24612032Speter for (usr = svusr, i = nusers >> 1; --i >= 0; usr++) { 24712032Speter for (usrn = users + (usr->uid&(nusers - 1)); usrn->name; 24812032Speter usrn--) { 24912032Speter if (usrn <= users) 25012032Speter usrn = users + nusers; 25112032Speter } 25212032Speter *usrn = *usr; 25312032Speter } 25412032Speter} 25512032Speter 25630262Scharnierstatic struct user * 25730262Scharnieruser(uid) 25812032Speter uid_t uid; 25912032Speter{ 26012032Speter register struct user *usr; 26187554Smikeh register int i; 26212032Speter struct passwd *pwd; 26312032Speter 26412032Speter while (1) { 26512032Speter for (usr = users + (uid&(nusers - 1)), i = nusers; --i >= 0; 26612032Speter usr--) { 26712032Speter if (!usr->name) { 26812032Speter usr->uid = uid; 26912032Speter 27012032Speter if (!(pwd = getpwuid(uid))) { 27130262Scharnier if ((usr->name = (char *)malloc(7))) 27212032Speter sprintf(usr->name,"#%d",uid); 27312032Speter } else { 27430262Scharnier if ((usr->name = (char *) 27530262Scharnier malloc(strlen(pwd->pw_name) + 1))) 27612032Speter strcpy(usr->name,pwd->pw_name); 27712032Speter } 27830262Scharnier if (!usr->name) 27930262Scharnier errx(1, "allocate users"); 28012032Speter 28112032Speter return usr; 28212032Speter 28312032Speter } else if (usr->uid == uid) 28412032Speter return usr; 28512032Speter 28612032Speter if (usr <= users) 28712032Speter usr = users + nusers; 28812032Speter } 28912032Speter usrrehash(); 29012032Speter } 29112032Speter} 29212032Speter 29330262Scharnierstatic int 29487554Smikehcmpusers(v1,v2) 29587554Smikeh const void *v1, *v2; 29612032Speter{ 29787554Smikeh const struct user *u1, *u2; 29887554Smikeh u1 = (const struct user *)v1; 29987554Smikeh u2 = (const struct user *)v2; 30087554Smikeh 30112032Speter return u2->space - u1->space; 30212032Speter} 30312032Speter 30412032Speter#define sortusers(users) (qsort((users),nusers,sizeof(struct user), \ 30512032Speter cmpusers)) 30612032Speter 30730262Scharnierstatic void 30830262Scharnieruses(uid,blks,act) 30912032Speter uid_t uid; 31012032Speter daddr_t blks; 31112032Speter time_t act; 31212032Speter{ 31312032Speter static time_t today; 31412032Speter register struct user *usr; 31512032Speter 31612032Speter if (!today) 31712032Speter time(&today); 31812032Speter 31912032Speter usr = user(uid); 32012032Speter usr->count++; 32112032Speter usr->space += blks; 32212032Speter 32312032Speter if (today - act > 90L * 24L * 60L * 60L) 32412032Speter usr->spc90 += blks; 32512032Speter if (today - act > 60L * 24L * 60L * 60L) 32612032Speter usr->spc60 += blks; 32712032Speter if (today - act > 30L * 24L * 60L * 60L) 32812032Speter usr->spc30 += blks; 32912032Speter} 33012032Speter 33112032Speter#ifdef COMPAT 33212032Speter#define FSZCNT 500 33312032Speter#else 33412032Speter#define FSZCNT 512 33512032Speter#endif 33612032Speterstruct fsizes { 33712032Speter struct fsizes *fsz_next; 33812032Speter daddr_t fsz_first, fsz_last; 33912032Speter ino_t fsz_count[FSZCNT]; 34012032Speter daddr_t fsz_sz[FSZCNT]; 34112032Speter} *fsizes; 34212032Speter 34330262Scharnierstatic void 34430262Scharnierinitfsizes() 34512032Speter{ 34612032Speter register struct fsizes *fp; 34787554Smikeh register int i; 34812032Speter 34912032Speter for (fp = fsizes; fp; fp = fp->fsz_next) { 35012032Speter for (i = FSZCNT; --i >= 0;) { 35112032Speter fp->fsz_count[i] = 0; 35212032Speter fp->fsz_sz[i] = 0; 35312032Speter } 35412032Speter } 35512032Speter} 35612032Speter 35730262Scharnierstatic void 35898542Smckusickdofsizes(fd, super, name) 35987554Smikeh int fd; 36012032Speter struct fs *super; 36112032Speter char *name; 36212032Speter{ 36312032Speter ino_t inode, maxino; 36498542Smckusick union dinode *dp; 36512032Speter daddr_t sz, ksz; 36612032Speter struct fsizes *fp, **fsp; 36787554Smikeh register int i; 36812032Speter 36912032Speter maxino = super->fs_ncg * super->fs_ipg - 1; 37012032Speter#ifdef COMPAT 37130262Scharnier if (!(fsizes = (struct fsizes *)malloc(sizeof(struct fsizes)))) 37253764Scharnier errx(1, "allocate fsize structure"); 37312032Speter#endif /* COMPAT */ 37412032Speter for (inode = 0; inode < maxino; inode++) { 37512032Speter errno = 0; 37698542Smckusick if ((dp = get_inode(fd,super,inode)) 37712032Speter#ifdef COMPAT 37898542Smckusick && ((DIP(super, dp, di_mode) & IFMT) == IFREG 37998542Smckusick || (DIP(super, dp, di_mode) & IFMT) == IFDIR) 38012032Speter#else /* COMPAT */ 38198542Smckusick && !isfree(super, dp) 38212032Speter#endif /* COMPAT */ 38312032Speter ) { 38498542Smckusick sz = estimate ? virtualblocks(super, dp) : 38598542Smckusick actualblocks(super, dp); 38612032Speter#ifdef COMPAT 38712032Speter if (sz >= FSZCNT) { 38812032Speter fsizes->fsz_count[FSZCNT-1]++; 38912032Speter fsizes->fsz_sz[FSZCNT-1] += sz; 39012032Speter } else { 39112032Speter fsizes->fsz_count[sz]++; 39212032Speter fsizes->fsz_sz[sz] += sz; 39312032Speter } 39412032Speter#else /* COMPAT */ 39512032Speter ksz = SIZE(sz); 39630262Scharnier for (fsp = &fsizes; (fp = *fsp); fsp = &fp->fsz_next) { 39712032Speter if (ksz < fp->fsz_last) 39812032Speter break; 39912032Speter } 40012032Speter if (!fp || ksz < fp->fsz_first) { 40112032Speter if (!(fp = (struct fsizes *) 40230262Scharnier malloc(sizeof(struct fsizes)))) 40353764Scharnier errx(1, "allocate fsize structure"); 40412032Speter fp->fsz_next = *fsp; 40512032Speter *fsp = fp; 40612032Speter fp->fsz_first = (ksz / FSZCNT) * FSZCNT; 40712032Speter fp->fsz_last = fp->fsz_first + FSZCNT; 40812032Speter for (i = FSZCNT; --i >= 0;) { 40912032Speter fp->fsz_count[i] = 0; 41012032Speter fp->fsz_sz[i] = 0; 41112032Speter } 41212032Speter } 41312032Speter fp->fsz_count[ksz % FSZCNT]++; 41412032Speter fp->fsz_sz[ksz % FSZCNT] += sz; 41512032Speter#endif /* COMPAT */ 41612032Speter } else if (errno) { 41730262Scharnier err(1, "%s", name); 41812032Speter } 41912032Speter } 42012032Speter sz = 0; 42112032Speter for (fp = fsizes; fp; fp = fp->fsz_next) { 42212032Speter for (i = 0; i < FSZCNT; i++) { 42312032Speter if (fp->fsz_count[i]) 42496638Sdes printf("%jd\t%jd\t%d\n", 42596638Sdes (intmax_t)(fp->fsz_first + i), 42696638Sdes (intmax_t)fp->fsz_count[i], 42712032Speter SIZE(sz += fp->fsz_sz[i])); 42812032Speter } 42912032Speter } 43012032Speter} 43112032Speter 43230262Scharnierstatic void 43398542Smckusickdouser(fd, super, name) 43487554Smikeh int fd; 43512032Speter struct fs *super; 43612032Speter char *name; 43712032Speter{ 43812032Speter ino_t inode, maxino; 43912032Speter struct user *usr, *usrs; 44098542Smckusick union dinode *dp; 44187554Smikeh register int n; 44212032Speter 44312032Speter maxino = super->fs_ncg * super->fs_ipg - 1; 44412032Speter for (inode = 0; inode < maxino; inode++) { 44512032Speter errno = 0; 44698542Smckusick if ((dp = get_inode(fd,super,inode)) 44798542Smckusick && !isfree(super, dp)) 44898542Smckusick uses(DIP(super, dp, di_uid), 44998542Smckusick estimate ? virtualblocks(super, dp) : 45098542Smckusick actualblocks(super, dp), 45198542Smckusick DIP(super, dp, di_atime)); 45212032Speter else if (errno) { 45330262Scharnier err(1, "%s", name); 45412032Speter } 45512032Speter } 45630262Scharnier if (!(usrs = (struct user *)malloc(nusers * sizeof(struct user)))) 45730262Scharnier errx(1, "allocate users"); 45812032Speter bcopy(users,usrs,nusers * sizeof(struct user)); 45912032Speter sortusers(usrs); 46012032Speter for (usr = usrs, n = nusers; --n >= 0 && usr->count; usr++) { 46112032Speter printf("%5d",SIZE(usr->space)); 46212032Speter if (count) 46387554Smikeh printf("\t%5ld",usr->count); 46412032Speter printf("\t%-8s",usr->name); 46512032Speter if (unused) 46612032Speter printf("\t%5d\t%5d\t%5d", 46712032Speter SIZE(usr->spc30), 46812032Speter SIZE(usr->spc60), 46912032Speter SIZE(usr->spc90)); 47012032Speter printf("\n"); 47112032Speter } 47212032Speter free(usrs); 47312032Speter} 47412032Speter 47530262Scharnierstatic void 47698542Smckusickdonames(fd, super, name) 47787554Smikeh int fd; 47812032Speter struct fs *super; 47912032Speter char *name; 48012032Speter{ 48112032Speter int c; 48212032Speter ino_t inode, inode1; 48312032Speter ino_t maxino; 48498542Smckusick union dinode *dp; 48512032Speter 48612032Speter maxino = super->fs_ncg * super->fs_ipg - 1; 48712032Speter /* first skip the name of the filesystem */ 48812032Speter while ((c = getchar()) != EOF && (c < '0' || c > '9')) 48912032Speter while ((c = getchar()) != EOF && c != '\n'); 49012032Speter ungetc(c,stdin); 49112032Speter inode1 = -1; 49287554Smikeh while (scanf("%u",&inode) == 1) { 49387554Smikeh if (inode > maxino) { 49430262Scharnier warnx("illegal inode %d",inode); 49512032Speter return; 49612032Speter } 49712032Speter errno = 0; 49898542Smckusick if ((dp = get_inode(fd,super,inode)) 49998542Smckusick && !isfree(super, dp)) { 50098542Smckusick printf("%s\t",user(DIP(super, dp, di_uid))->name); 50112032Speter /* now skip whitespace */ 50212032Speter while ((c = getchar()) == ' ' || c == '\t'); 50312032Speter /* and print out the remainder of the input line */ 50412032Speter while (c != EOF && c != '\n') { 50512032Speter putchar(c); 50612032Speter c = getchar(); 50712032Speter } 50812032Speter putchar('\n'); 50912032Speter inode1 = inode; 51012032Speter } else { 51112032Speter if (errno) { 51230262Scharnier err(1, "%s", name); 51312032Speter } 51412032Speter /* skip this line */ 51512032Speter while ((c = getchar()) != EOF && c != '\n'); 51612032Speter } 51712032Speter if (c == EOF) 51812032Speter break; 51912032Speter } 52012032Speter} 52112032Speter 52230262Scharnierstatic void 52330262Scharnierusage() 52412032Speter{ 52512032Speter#ifdef COMPAT 52630262Scharnier fprintf(stderr,"usage: quot [-nfcvha] [filesystem ...]\n"); 52712032Speter#else /* COMPAT */ 52853764Scharnier fprintf(stderr,"usage: quot [-acfhknv] [filesystem ...]\n"); 52912032Speter#endif /* COMPAT */ 53012032Speter exit(1); 53112032Speter} 53212032Speter 53398542Smckusick/* 53498542Smckusick * Possible superblock locations ordered from most to least likely. 53598542Smckusick */ 53698542Smckusickstatic int sblock_try[] = SBLOCKSEARCH; 53798542Smckusickstatic char superblock[SBLOCKSIZE]; 53812032Speter 53930262Scharniervoid 54012032Speterquot(name,mp) 54112032Speter char *name, *mp; 54212032Speter{ 54398542Smckusick int i, fd; 54498542Smckusick struct fs *fs; 54512032Speter 54687554Smikeh get_inode(-1, NULL, 0); /* flush cache */ 54712032Speter inituser(); 54812032Speter initfsizes(); 54998542Smckusick if ((fd = open(name,0)) < 0) { 55030262Scharnier warn("%s", name); 55112032Speter close(fd); 55212032Speter return; 55312032Speter } 55498542Smckusick for (i = 0; sblock_try[i] != -1; i++) { 55598542Smckusick if (lseek(fd, sblock_try[i], 0) != sblock_try[i]) { 55698542Smckusick close(fd); 55798542Smckusick return; 55898542Smckusick } 55998542Smckusick if (read(fd, superblock, SBLOCKSIZE) != SBLOCKSIZE) { 56098542Smckusick close(fd); 56198542Smckusick return; 56298542Smckusick } 56398542Smckusick fs = (struct fs *)superblock; 56498542Smckusick if ((fs->fs_magic == FS_UFS1_MAGIC || 56598542Smckusick (fs->fs_magic == FS_UFS2_MAGIC && 56698542Smckusick fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) && 56798542Smckusick fs->fs_bsize <= MAXBSIZE && 56898542Smckusick fs->fs_bsize >= sizeof(struct fs)) 56998542Smckusick break; 57098542Smckusick } 57198542Smckusick if (sblock_try[i] == -1) { 57230262Scharnier warnx("%s: not a BSD filesystem",name); 57312032Speter close(fd); 57412032Speter return; 57512032Speter } 57612032Speter printf("%s:",name); 57712032Speter if (mp) 57812032Speter printf(" (%s)",mp); 57912032Speter putchar('\n'); 58098542Smckusick (*func)(fd, fs, name); 58112032Speter close(fd); 58212032Speter} 58312032Speter 58430262Scharnierint 58530262Scharniermain(argc,argv) 58687554Smikeh int argc; 58712032Speter char **argv; 58812032Speter{ 58912032Speter char all = 0; 59012032Speter struct statfs *mp; 59174071Sps struct fstab *fs; 59212032Speter char dev[MNAMELEN + 1]; 59312032Speter char *nm; 59412032Speter int cnt; 59512032Speter 59612032Speter func = douser; 59712032Speter#ifndef COMPAT 59812032Speter header = getbsize(&headerlen,&blocksize); 59912032Speter#endif 60012032Speter while (--argc > 0 && **++argv == '-') { 60112032Speter while (*++*argv) { 60212032Speter switch (**argv) { 60312032Speter case 'n': 60412032Speter func = donames; 60512032Speter break; 60612032Speter case 'c': 60712032Speter func = dofsizes; 60812032Speter break; 60912032Speter case 'a': 61012032Speter all = 1; 61112032Speter break; 61212032Speter case 'f': 61312032Speter count = 1; 61412032Speter break; 61512032Speter case 'h': 61612032Speter estimate = 1; 61712032Speter break; 61812032Speter#ifndef COMPAT 61912032Speter case 'k': 62012032Speter blocksize = 1024; 62112032Speter break; 62212032Speter#endif /* COMPAT */ 62312032Speter case 'v': 62412032Speter unused = 1; 62512032Speter break; 62612032Speter default: 62712032Speter usage(); 62812032Speter } 62912032Speter } 63012032Speter } 63112032Speter if (all) { 63212032Speter cnt = getmntinfo(&mp,MNT_NOWAIT); 63312032Speter for (; --cnt >= 0; mp++) { 63432595Sbde if (!strncmp(mp->f_fstypename, "ufs", MFSNAMELEN)) { 63530262Scharnier if ((nm = strrchr(mp->f_mntfromname,'/'))) { 63669793Sobrien sprintf(dev,"%s%s",_PATH_DEV,nm + 1); 63712032Speter nm = dev; 63812032Speter } else 63912032Speter nm = mp->f_mntfromname; 64012032Speter quot(nm,mp->f_mntonname); 64112032Speter } 64212032Speter } 64312032Speter } 64474071Sps while (--argc >= 0) { 64574071Sps if ((fs = getfsfile(*argv)) != NULL) 64674071Sps quot(fs->fs_spec, 0); 64774071Sps else 64874071Sps quot(*argv,0); 64974071Sps argv++; 65074071Sps } 65112032Speter return 0; 65212032Speter} 653