121517Smckusick /* 2*61532Sbostic * Copyright (c) 1980, 1990, 1993 3*61532Sbostic * The Regents of the University of California. All rights reserved. 434364Sbostic * 541411Smckusick * This code is derived from software contributed to Berkeley by 641411Smckusick * Robert Elz at The University of Melbourne. 741411Smckusick * 842707Sbostic * %sccs.include.redist.c% 921517Smckusick */ 1021517Smckusick 1112703Smckusick #ifndef lint 12*61532Sbostic static char copyright[] = 13*61532Sbostic "@(#) Copyright (c) 1980, 1990, 1993\n\ 14*61532Sbostic The Regents of the University of California. All rights reserved.\n"; 1534364Sbostic #endif /* not lint */ 1612660Smckusick 1721517Smckusick #ifndef lint 18*61532Sbostic static char sccsid[] = "@(#)quotacheck.c 8.1 (Berkeley) 06/05/93"; 1934364Sbostic #endif /* not lint */ 2021517Smckusick 2112660Smckusick /* 2241411Smckusick * Fix up / report on disk quotas & usage 2312660Smckusick */ 2412660Smckusick #include <sys/param.h> 2546783Sbostic #include <sys/stat.h> 2654158Sbostic 2751623Sbostic #include <ufs/ufs/dinode.h> 2851623Sbostic #include <ufs/ufs/quota.h> 2951623Sbostic #include <ufs/ffs/fs.h> 3054158Sbostic 3146783Sbostic #include <fcntl.h> 3212703Smckusick #include <fstab.h> 3312802Smckusick #include <pwd.h> 3441411Smckusick #include <grp.h> 3546783Sbostic #include <errno.h> 3646783Sbostic #include <unistd.h> 3738511Sbostic #include <stdio.h> 3846783Sbostic #include <stdlib.h> 3946783Sbostic #include <string.h> 4012660Smckusick 4145251Smckusick char *qfname = QUOTAFILENAME; 4245251Smckusick char *qfextension[] = INITQFNAMES; 4345251Smckusick char *quotagroup = QUOTAGROUP; 4445251Smckusick 4512660Smckusick union { 4612660Smckusick struct fs sblk; 4712703Smckusick char dummy[MAXBSIZE]; 4812660Smckusick } un; 4912660Smckusick #define sblock un.sblk 5041411Smckusick long dev_bsize = 1; 5141411Smckusick long maxino; 5212703Smckusick 5341443Smckusick struct quotaname { 5441443Smckusick long flags; 5541443Smckusick char grpqfname[MAXPATHLEN + 1]; 5641443Smckusick char usrqfname[MAXPATHLEN + 1]; 5741443Smckusick }; 5841443Smckusick #define HASUSR 1 5941443Smckusick #define HASGRP 2 6041443Smckusick 6112703Smckusick struct fileusage { 6241411Smckusick struct fileusage *fu_next; 6341411Smckusick u_long fu_curinodes; 6441411Smckusick u_long fu_curblocks; 6541411Smckusick u_long fu_id; 6641411Smckusick char fu_name[1]; 6741411Smckusick /* actually bigger */ 6812703Smckusick }; 6941411Smckusick #define FUHASH 1024 /* must be power of two */ 7041411Smckusick struct fileusage *fuhead[MAXQUOTAS][FUHASH]; 7112660Smckusick 7241411Smckusick int aflag; /* all file systems */ 7341411Smckusick int gflag; /* check group quotas */ 7441411Smckusick int uflag; /* check user quotas */ 7541411Smckusick int vflag; /* verbose */ 7641411Smckusick int fi; /* open disk file descriptor */ 7741411Smckusick u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */ 7812703Smckusick 7954158Sbostic struct fileusage * 8054158Sbostic addid __P((u_long, int, char *)); 8154158Sbostic char *blockcheck __P((char *)); 8254158Sbostic void bread __P((daddr_t, char *, long)); 8354158Sbostic int chkquota __P((char *, char *, struct quotaname *)); 8454158Sbostic void err __P((const char *, ...)); 8554158Sbostic void freeinodebuf __P((void)); 8654158Sbostic struct dinode * 8754158Sbostic getnextinode __P((ino_t)); 8854158Sbostic int getquotagid __P((void)); 8954158Sbostic int hasquota __P((struct fstab *, int, char **)); 9054158Sbostic struct fileusage * 9154158Sbostic lookup __P((u_long, int)); 9254158Sbostic void *needchk __P((struct fstab *)); 9354158Sbostic int oneof __P((char *, char*[], int)); 9454158Sbostic void resetinodebuf __P((void)); 9554158Sbostic int update __P((char *, char *, int)); 9654158Sbostic void usage __P((void)); 9754158Sbostic 9854158Sbostic int 9912660Smckusick main(argc, argv) 10012703Smckusick int argc; 10154158Sbostic char *argv[]; 10212660Smckusick { 10312703Smckusick register struct fstab *fs; 10412802Smckusick register struct passwd *pw; 10541411Smckusick register struct group *gr; 10654158Sbostic struct quotaname *auxdata; 10741411Smckusick int i, argnum, maxrun, errs = 0; 10854158Sbostic long done = 0; 10954158Sbostic char ch, *name; 11012660Smckusick 11141411Smckusick while ((ch = getopt(argc, argv, "aguvl:")) != EOF) { 11241411Smckusick switch(ch) { 11341411Smckusick case 'a': 11441411Smckusick aflag++; 11541411Smckusick break; 11641411Smckusick case 'g': 11741411Smckusick gflag++; 11841411Smckusick break; 11941411Smckusick case 'u': 12041411Smckusick uflag++; 12141411Smckusick break; 12241411Smckusick case 'v': 12341411Smckusick vflag++; 12441411Smckusick break; 12541411Smckusick case 'l': 12641411Smckusick maxrun = atoi(optarg); 12741411Smckusick break; 12841411Smckusick default: 12941411Smckusick usage(); 13041411Smckusick } 13112660Smckusick } 13241411Smckusick argc -= optind; 13341411Smckusick argv += optind; 13441411Smckusick if ((argc == 0 && !aflag) || (argc > 0 && aflag)) 13541411Smckusick usage(); 13641411Smckusick if (!gflag && !uflag) { 13741411Smckusick gflag++; 13841411Smckusick uflag++; 13912703Smckusick } 14041411Smckusick if (gflag) { 14141411Smckusick setgrent(); 14241411Smckusick while ((gr = getgrent()) != 0) 14341411Smckusick (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name); 14441411Smckusick endgrent(); 14524758Sserge } 14641411Smckusick if (uflag) { 14741411Smckusick setpwent(); 14841411Smckusick while ((pw = getpwent()) != 0) 14941411Smckusick (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name); 15041411Smckusick endpwent(); 15112660Smckusick } 15241411Smckusick if (aflag) 15341411Smckusick exit(checkfstab(1, maxrun, needchk, chkquota)); 15454158Sbostic if (setfsent() == 0) 15554158Sbostic err("%s: can't open", FSTAB); 15641411Smckusick while ((fs = getfsent()) != NULL) { 15741411Smckusick if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || 15841411Smckusick (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) && 15941411Smckusick (auxdata = needchk(fs)) && 16041411Smckusick (name = blockcheck(fs->fs_spec))) { 16141411Smckusick done |= 1 << argnum; 16241411Smckusick errs += chkquota(name, fs->fs_file, auxdata); 16324758Sserge } 16412660Smckusick } 16541411Smckusick endfsent(); 16612703Smckusick for (i = 0; i < argc; i++) 16712703Smckusick if ((done & (1 << i)) == 0) 16824782Sserge fprintf(stderr, "%s not found in %s\n", 16924782Sserge argv[i], FSTAB); 17012703Smckusick exit(errs); 17112703Smckusick } 17212660Smckusick 17354158Sbostic void 17441411Smckusick usage() 17524758Sserge { 17654158Sbostic (void)fprintf(stderr, "usage:\t%s\n\t%s\n", 17746783Sbostic "quotacheck -a [-guv]", 17846783Sbostic "quotacheck [-guv] filesys ..."); 17941411Smckusick exit(1); 18041411Smckusick } 18124758Sserge 18254158Sbostic void * 18341411Smckusick needchk(fs) 18441411Smckusick register struct fstab *fs; 18541411Smckusick { 18641443Smckusick register struct quotaname *qnp; 18741443Smckusick char *qfnp; 18824758Sserge 18941443Smckusick if (strcmp(fs->fs_vfstype, "ufs") || 19041443Smckusick strcmp(fs->fs_type, FSTAB_RW)) 19154158Sbostic return (NULL); 19254158Sbostic if ((qnp = malloc(sizeof(*qnp))) == NULL) 19354158Sbostic err("%s", strerror(errno)); 19441443Smckusick qnp->flags = 0; 19541443Smckusick if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) { 19641443Smckusick strcpy(qnp->grpqfname, qfnp); 19741443Smckusick qnp->flags |= HASGRP; 19841443Smckusick } 19941443Smckusick if (uflag && hasquota(fs, USRQUOTA, &qfnp)) { 20041443Smckusick strcpy(qnp->usrqfname, qfnp); 20141443Smckusick qnp->flags |= HASUSR; 20241443Smckusick } 20341443Smckusick if (qnp->flags) 20454158Sbostic return (qnp); 20554158Sbostic free(qnp); 20654158Sbostic return (NULL); 20741411Smckusick } 20824758Sserge 20941411Smckusick /* 21041411Smckusick * Scan the specified filesystem to check quota(s) present on it. 21141411Smckusick */ 21254158Sbostic int 21341443Smckusick chkquota(fsname, mntpt, qnp) 21441411Smckusick char *fsname, *mntpt; 21541443Smckusick register struct quotaname *qnp; 21641411Smckusick { 21741411Smckusick register struct fileusage *fup; 21841411Smckusick register struct dinode *dp; 21941411Smckusick int cg, i, mode, errs = 0; 22041411Smckusick ino_t ino; 22124758Sserge 22254158Sbostic if ((fi = open(fsname, O_RDONLY, 0)) < 0) { 22341411Smckusick perror(fsname); 22441411Smckusick return (1); 22541411Smckusick } 22641411Smckusick if (vflag) { 22754158Sbostic (void)printf("*** Checking "); 22841443Smckusick if (qnp->flags & HASUSR) 22954158Sbostic (void)printf("%s%s", qfextension[USRQUOTA], 23041443Smckusick (qnp->flags & HASGRP) ? " and " : ""); 23141443Smckusick if (qnp->flags & HASGRP) 23254158Sbostic (void)printf("%s", qfextension[GRPQUOTA]); 23354158Sbostic (void)printf(" quotas for %s (%s)\n", fsname, mntpt); 23441411Smckusick } 23541411Smckusick sync(); 23641411Smckusick bread(SBOFF, (char *)&sblock, (long)SBSIZE); 23741411Smckusick dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); 23841411Smckusick maxino = sblock.fs_ncg * sblock.fs_ipg; 23941411Smckusick resetinodebuf(); 24041411Smckusick for (ino = 0, cg = 0; cg < sblock.fs_ncg; cg++) { 24141411Smckusick for (i = 0; i < sblock.fs_ipg; i++, ino++) { 24241411Smckusick if (ino < ROOTINO) 24324758Sserge continue; 24441411Smckusick if ((dp = getnextinode(ino)) == NULL) 24524758Sserge continue; 24641411Smckusick if ((mode = dp->di_mode & IFMT) == 0) 24741411Smckusick continue; 24841443Smckusick if (qnp->flags & HASGRP) { 24941411Smckusick fup = addid((u_long)dp->di_gid, GRPQUOTA, 25041411Smckusick (char *)0); 25141411Smckusick fup->fu_curinodes++; 25241411Smckusick if (mode == IFREG || mode == IFDIR || 25341411Smckusick mode == IFLNK) 25441411Smckusick fup->fu_curblocks += dp->di_blocks; 25524758Sserge } 25641443Smckusick if (qnp->flags & HASUSR) { 25741411Smckusick fup = addid((u_long)dp->di_uid, USRQUOTA, 25841411Smckusick (char *)0); 25941411Smckusick fup->fu_curinodes++; 26041411Smckusick if (mode == IFREG || mode == IFDIR || 26141411Smckusick mode == IFLNK) 26241411Smckusick fup->fu_curblocks += dp->di_blocks; 26341411Smckusick } 26424758Sserge } 26541411Smckusick } 26641411Smckusick freeinodebuf(); 26741443Smckusick if (qnp->flags & HASUSR) 26841443Smckusick errs += update(mntpt, qnp->usrqfname, USRQUOTA); 26941443Smckusick if (qnp->flags & HASGRP) 27041443Smckusick errs += update(mntpt, qnp->grpqfname, GRPQUOTA); 27141411Smckusick close(fi); 27224758Sserge return (errs); 27324758Sserge } 27424758Sserge 27541411Smckusick /* 27641411Smckusick * Update a specified quota file. 27741411Smckusick */ 27854158Sbostic int 27941443Smckusick update(fsname, quotafile, type) 28041443Smckusick char *fsname, *quotafile; 28141411Smckusick register int type; 28212703Smckusick { 28312703Smckusick register struct fileusage *fup; 28425377Sserge register FILE *qfi, *qfo; 28541411Smckusick register u_long id, lastid; 28612703Smckusick struct dqblk dqbuf; 28721085Smckusick static int warned = 0; 28841411Smckusick static struct dqblk zerodqbuf; 28941411Smckusick static struct fileusage zerofileusage; 29012660Smckusick 29141411Smckusick if ((qfo = fopen(quotafile, "r+")) == NULL) { 29246783Sbostic if (errno == ENOENT) 29346783Sbostic qfo = fopen(quotafile, "w+"); 29446783Sbostic if (qfo) { 29546783Sbostic (void) fprintf(stderr, 29646783Sbostic "quotacheck: creating quota file %s\n", quotafile); 29746783Sbostic #define MODE (S_IRUSR|S_IWUSR|S_IRGRP) 29846783Sbostic (void) fchown(fileno(qfo), getuid(), getquotagid()); 29946783Sbostic (void) fchmod(fileno(qfo), MODE); 30046783Sbostic } else { 30146783Sbostic (void) fprintf(stderr, 30246783Sbostic "quotacheck: %s: %s\n", quotafile, strerror(errno)); 30341411Smckusick return (1); 30441411Smckusick } 30512660Smckusick } 30641411Smckusick if ((qfi = fopen(quotafile, "r")) == NULL) { 30746783Sbostic (void) fprintf(stderr, 30846783Sbostic "quotacheck: %s: %s\n", quotafile, strerror(errno)); 30946783Sbostic (void) fclose(qfo); 31012703Smckusick return (1); 31112660Smckusick } 31241411Smckusick if (quotactl(fsname, QCMD(Q_SYNC, type), (u_long)0, (caddr_t)0) < 0 && 31341411Smckusick errno == EOPNOTSUPP && !warned && vflag) { 31421085Smckusick warned++; 31554158Sbostic (void)printf("*** Warning: %s\n", 31641411Smckusick "Quotas are not compiled into this kernel"); 31721085Smckusick } 31841411Smckusick for (lastid = highid[type], id = 0; id <= lastid; id++) { 31941411Smckusick if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0) 32012802Smckusick dqbuf = zerodqbuf; 32141411Smckusick if ((fup = lookup(id, type)) == 0) 32224758Sserge fup = &zerofileusage; 32341411Smckusick if (dqbuf.dqb_curinodes == fup->fu_curinodes && 32441411Smckusick dqbuf.dqb_curblocks == fup->fu_curblocks) { 32541411Smckusick fup->fu_curinodes = 0; 32641411Smckusick fup->fu_curblocks = 0; 32725377Sserge fseek(qfo, (long)sizeof(struct dqblk), 1); 32812703Smckusick continue; 32912802Smckusick } 33012703Smckusick if (vflag) { 33141411Smckusick if (aflag) 33241411Smckusick printf("%s: ", fsname); 33341411Smckusick printf("%-8s fixed:", fup->fu_name); 33441411Smckusick if (dqbuf.dqb_curinodes != fup->fu_curinodes) 33554158Sbostic (void)printf("\tinodes %d -> %d", 33641411Smckusick dqbuf.dqb_curinodes, fup->fu_curinodes); 33741411Smckusick if (dqbuf.dqb_curblocks != fup->fu_curblocks) 33854158Sbostic (void)printf("\tblocks %d -> %d", 33941411Smckusick dqbuf.dqb_curblocks, fup->fu_curblocks); 34054158Sbostic (void)printf("\n"); 34112660Smckusick } 34241411Smckusick /* 34341411Smckusick * Reset time limit if have a soft limit and were 34441411Smckusick * previously under it, but are now over it. 34541411Smckusick */ 34641411Smckusick if (dqbuf.dqb_bsoftlimit && 34741411Smckusick dqbuf.dqb_curblocks < dqbuf.dqb_bsoftlimit && 34841411Smckusick fup->fu_curblocks >= dqbuf.dqb_bsoftlimit) 34941411Smckusick dqbuf.dqb_btime = 0; 35041411Smckusick if (dqbuf.dqb_isoftlimit && 35141411Smckusick dqbuf.dqb_curblocks < dqbuf.dqb_isoftlimit && 35241411Smckusick fup->fu_curblocks >= dqbuf.dqb_isoftlimit) 35341411Smckusick dqbuf.dqb_itime = 0; 35441411Smckusick dqbuf.dqb_curinodes = fup->fu_curinodes; 35541411Smckusick dqbuf.dqb_curblocks = fup->fu_curblocks; 35641411Smckusick fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo); 35741411Smckusick (void) quotactl(fsname, QCMD(Q_SETUSE, type), id, 35841411Smckusick (caddr_t)&dqbuf); 35941411Smckusick fup->fu_curinodes = 0; 36041411Smckusick fup->fu_curblocks = 0; 36112660Smckusick } 36241411Smckusick fclose(qfi); 36325377Sserge fflush(qfo); 36441411Smckusick ftruncate(fileno(qfo), 36541411Smckusick (off_t)((highid[type] + 1) * sizeof(struct dqblk))); 36625377Sserge fclose(qfo); 36712703Smckusick return (0); 36812660Smckusick } 36912660Smckusick 37041411Smckusick /* 37141411Smckusick * Check to see if target appears in list of size cnt. 37241411Smckusick */ 37354158Sbostic int 37441411Smckusick oneof(target, list, cnt) 37541411Smckusick register char *target, *list[]; 37641411Smckusick int cnt; 37712660Smckusick { 37812703Smckusick register int i; 37912660Smckusick 38041411Smckusick for (i = 0; i < cnt; i++) 38141411Smckusick if (strcmp(target, list[i]) == 0) 38241411Smckusick return (i); 38341411Smckusick return (-1); 38412660Smckusick } 38512660Smckusick 38641411Smckusick /* 38741443Smckusick * Determine the group identifier for quota files. 38841443Smckusick */ 38954158Sbostic int 39041443Smckusick getquotagid() 39141443Smckusick { 39241443Smckusick struct group *gr; 39341443Smckusick 39441443Smckusick if (gr = getgrnam(quotagroup)) 39541443Smckusick return (gr->gr_gid); 39641443Smckusick return (-1); 39741443Smckusick } 39841443Smckusick 39941443Smckusick /* 40041411Smckusick * Check to see if a particular quota is to be enabled. 40141411Smckusick */ 40254158Sbostic int 40341443Smckusick hasquota(fs, type, qfnamep) 40441443Smckusick register struct fstab *fs; 40541411Smckusick int type; 40641443Smckusick char **qfnamep; 40712660Smckusick { 40841411Smckusick register char *opt; 40954158Sbostic char *cp; 41041411Smckusick static char initname, usrname[100], grpname[100]; 41141443Smckusick static char buf[BUFSIZ]; 41212660Smckusick 41341411Smckusick if (!initname) { 41454158Sbostic (void)snprintf(usrname, sizeof(usrname), 41554158Sbostic "%s%s", qfextension[USRQUOTA], qfname); 41654158Sbostic (void)snprintf(grpname, sizeof(grpname), 41754158Sbostic "%s%s", qfextension[GRPQUOTA], qfname); 41841411Smckusick initname = 1; 41912660Smckusick } 42041443Smckusick strcpy(buf, fs->fs_mntops); 42141411Smckusick for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { 42241443Smckusick if (cp = index(opt, '=')) 42341443Smckusick *cp++ = '\0'; 42441411Smckusick if (type == USRQUOTA && strcmp(opt, usrname) == 0) 42541443Smckusick break; 42641411Smckusick if (type == GRPQUOTA && strcmp(opt, grpname) == 0) 42741443Smckusick break; 42825377Sserge } 42941443Smckusick if (!opt) 43041443Smckusick return (0); 43154158Sbostic if (cp) 43241443Smckusick *qfnamep = cp; 43354158Sbostic else { 43454158Sbostic (void)snprintf(buf, sizeof(buf), 43554158Sbostic "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); 43654158Sbostic *qfnamep = buf; 43741443Smckusick } 43841443Smckusick return (1); 43912660Smckusick } 44012660Smckusick 44141411Smckusick /* 44241411Smckusick * Routines to manage the file usage table. 44341411Smckusick * 44441411Smckusick * Lookup an id of a specific type. 44541411Smckusick */ 44612703Smckusick struct fileusage * 44741411Smckusick lookup(id, type) 44841411Smckusick u_long id; 44941411Smckusick int type; 45012660Smckusick { 45112703Smckusick register struct fileusage *fup; 45212660Smckusick 45341411Smckusick for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next) 45441411Smckusick if (fup->fu_id == id) 45512703Smckusick return (fup); 45654158Sbostic return (NULL); 45712660Smckusick } 45812660Smckusick 45941411Smckusick /* 46041411Smckusick * Add a new file usage id if it does not already exist. 46141411Smckusick */ 46212703Smckusick struct fileusage * 46341411Smckusick addid(id, type, name) 46441411Smckusick u_long id; 46541411Smckusick int type; 46641411Smckusick char *name; 46712660Smckusick { 46812703Smckusick struct fileusage *fup, **fhp; 46941411Smckusick int len; 47012660Smckusick 47141411Smckusick if (fup = lookup(id, type)) 47212703Smckusick return (fup); 47341411Smckusick if (name) 47441411Smckusick len = strlen(name); 47541411Smckusick else 47641411Smckusick len = 10; 47754158Sbostic if ((fup = calloc(1, sizeof(*fup) + len)) == NULL) 47854158Sbostic err("%s", strerror(errno)); 47941411Smckusick fhp = &fuhead[type][id & (FUHASH - 1)]; 48012703Smckusick fup->fu_next = *fhp; 48112703Smckusick *fhp = fup; 48241411Smckusick fup->fu_id = id; 48341411Smckusick if (id > highid[type]) 48441411Smckusick highid[type] = id; 48554158Sbostic if (name) 48641411Smckusick bcopy(name, fup->fu_name, len + 1); 48754158Sbostic else 48854158Sbostic (void)sprintf(fup->fu_name, "%u", id); 48912703Smckusick return (fup); 49012660Smckusick } 49112660Smckusick 49241411Smckusick /* 49341411Smckusick * Special purpose version of ginode used to optimize pass 49441411Smckusick * over all the inodes in numerical order. 49541411Smckusick */ 49641411Smckusick ino_t nextino, lastinum; 49741411Smckusick long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 49841411Smckusick struct dinode *inodebuf; 49941411Smckusick #define INOBUFSIZE 56*1024 /* size of buffer to read inodes */ 50041411Smckusick 50141411Smckusick struct dinode * 50241411Smckusick getnextinode(inumber) 50341411Smckusick ino_t inumber; 50412660Smckusick { 50541411Smckusick long size; 50641411Smckusick daddr_t dblk; 50741411Smckusick static struct dinode *dp; 50812660Smckusick 50954158Sbostic if (inumber != nextino++ || inumber > maxino) 51054158Sbostic err("bad inode number %d to nextinode", inumber); 51141411Smckusick if (inumber >= lastinum) { 51241411Smckusick readcnt++; 51341411Smckusick dblk = fsbtodb(&sblock, itod(&sblock, lastinum)); 51441411Smckusick if (readcnt % readpercg == 0) { 51541411Smckusick size = partialsize; 51641411Smckusick lastinum += partialcnt; 51741411Smckusick } else { 51841411Smckusick size = inobufsize; 51941411Smckusick lastinum += fullcnt; 52041411Smckusick } 52141411Smckusick bread(dblk, (char *)inodebuf, size); 52241411Smckusick dp = inodebuf; 52341411Smckusick } 52441411Smckusick return (dp++); 52512660Smckusick } 52641411Smckusick 52741411Smckusick /* 52841411Smckusick * Prepare to scan a set of inodes. 52941411Smckusick */ 53054158Sbostic void 53141411Smckusick resetinodebuf() 53241411Smckusick { 53341411Smckusick 53441411Smckusick nextino = 0; 53541411Smckusick lastinum = 0; 53641411Smckusick readcnt = 0; 53741411Smckusick inobufsize = blkroundup(&sblock, INOBUFSIZE); 53841411Smckusick fullcnt = inobufsize / sizeof(struct dinode); 53941411Smckusick readpercg = sblock.fs_ipg / fullcnt; 54041411Smckusick partialcnt = sblock.fs_ipg % fullcnt; 54141411Smckusick partialsize = partialcnt * sizeof(struct dinode); 54241411Smckusick if (partialcnt != 0) { 54341411Smckusick readpercg++; 54441411Smckusick } else { 54541411Smckusick partialcnt = fullcnt; 54641411Smckusick partialsize = inobufsize; 54741411Smckusick } 54841411Smckusick if (inodebuf == NULL && 54954158Sbostic (inodebuf = malloc((u_int)inobufsize)) == NULL) 55054158Sbostic err("%s", strerror(errno)); 55141411Smckusick while (nextino < ROOTINO) 55241411Smckusick getnextinode(nextino); 55341411Smckusick } 55441411Smckusick 55541411Smckusick /* 55641411Smckusick * Free up data structures used to scan inodes. 55741411Smckusick */ 55854158Sbostic void 55941411Smckusick freeinodebuf() 56041411Smckusick { 56141411Smckusick 56241411Smckusick if (inodebuf != NULL) 56354158Sbostic free(inodebuf); 56441411Smckusick inodebuf = NULL; 56541411Smckusick } 56641411Smckusick 56741411Smckusick /* 56841411Smckusick * Read specified disk blocks. 56941411Smckusick */ 57054158Sbostic void 57141411Smckusick bread(bno, buf, cnt) 57241411Smckusick daddr_t bno; 57341411Smckusick char *buf; 57441411Smckusick long cnt; 57541411Smckusick { 57641411Smckusick 57758002Sralph if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0 || 57854158Sbostic read(fi, buf, cnt) != cnt) 57954158Sbostic err("block %ld", bno); 58054158Sbostic } 58141411Smckusick 58254158Sbostic #if __STDC__ 58354158Sbostic #include <stdarg.h> 58454158Sbostic #else 58554158Sbostic #include <varargs.h> 58654158Sbostic #endif 58754158Sbostic 58854158Sbostic void 58954158Sbostic #if __STDC__ 59054158Sbostic err(const char *fmt, ...) 59154158Sbostic #else 59254158Sbostic err(fmt, va_alist) 59354158Sbostic char *fmt; 59454158Sbostic va_dcl 59554158Sbostic #endif 59654158Sbostic { 59754158Sbostic va_list ap; 59854158Sbostic #if __STDC__ 59954158Sbostic va_start(ap, fmt); 60054158Sbostic #else 60154158Sbostic va_start(ap); 60254158Sbostic #endif 60354158Sbostic (void)fprintf(stderr, "quotacheck: "); 60454158Sbostic (void)vfprintf(stderr, fmt, ap); 60554158Sbostic va_end(ap); 60654158Sbostic (void)fprintf(stderr, "\n"); 60754158Sbostic exit(1); 60854158Sbostic /* NOTREACHED */ 60941411Smckusick } 610