121517Smckusick /* 241411Smckusick * Copyright (c) 1980, 1990 Regents of the University of California. 334364Sbostic * 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 1221517Smckusick char copyright[] = 1341411Smckusick "@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\ 1421517Smckusick All rights reserved.\n"; 1534364Sbostic #endif /* not lint */ 1612660Smckusick 1721517Smckusick #ifndef lint 18*46783Sbostic static char sccsid[] = "@(#)quotacheck.c 5.16 (Berkeley) 02/28/91"; 1934364Sbostic #endif /* not lint */ 2021517Smckusick 2112660Smckusick /* 2241411Smckusick * Fix up / report on disk quotas & usage 2312660Smckusick */ 2412660Smckusick #include <sys/param.h> 25*46783Sbostic #include <sys/stat.h> 2641411Smckusick #include <ufs/dinode.h> 2738511Sbostic #include <ufs/fs.h> 2838511Sbostic #include <ufs/quota.h> 29*46783Sbostic #include <fcntl.h> 3012703Smckusick #include <fstab.h> 3112802Smckusick #include <pwd.h> 3241411Smckusick #include <grp.h> 33*46783Sbostic #include <errno.h> 34*46783Sbostic #include <unistd.h> 3538511Sbostic #include <stdio.h> 36*46783Sbostic #include <stdlib.h> 37*46783Sbostic #include <string.h> 3812660Smckusick 3945251Smckusick char *qfname = QUOTAFILENAME; 4045251Smckusick char *qfextension[] = INITQFNAMES; 4145251Smckusick char *quotagroup = QUOTAGROUP; 4245251Smckusick 4312660Smckusick union { 4412660Smckusick struct fs sblk; 4512703Smckusick char dummy[MAXBSIZE]; 4612660Smckusick } un; 4712660Smckusick #define sblock un.sblk 4841411Smckusick long dev_bsize = 1; 4941411Smckusick long maxino; 5012703Smckusick 5141443Smckusick struct quotaname { 5241443Smckusick long flags; 5341443Smckusick char grpqfname[MAXPATHLEN + 1]; 5441443Smckusick char usrqfname[MAXPATHLEN + 1]; 5541443Smckusick }; 5641443Smckusick #define HASUSR 1 5741443Smckusick #define HASGRP 2 5841443Smckusick 5912703Smckusick struct fileusage { 6041411Smckusick struct fileusage *fu_next; 6141411Smckusick u_long fu_curinodes; 6241411Smckusick u_long fu_curblocks; 6341411Smckusick u_long fu_id; 6441411Smckusick char fu_name[1]; 6541411Smckusick /* actually bigger */ 6612703Smckusick }; 6741411Smckusick #define FUHASH 1024 /* must be power of two */ 6841411Smckusick struct fileusage *fuhead[MAXQUOTAS][FUHASH]; 6912703Smckusick struct fileusage *lookup(); 7041411Smckusick struct fileusage *addid(); 7141411Smckusick struct dinode *getnextinode(); 7212660Smckusick 7341411Smckusick int aflag; /* all file systems */ 7441411Smckusick int gflag; /* check group quotas */ 7541411Smckusick int uflag; /* check user quotas */ 7641411Smckusick int vflag; /* verbose */ 7741411Smckusick int fi; /* open disk file descriptor */ 7841411Smckusick u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */ 7912703Smckusick 8012660Smckusick main(argc, argv) 8112703Smckusick int argc; 8212660Smckusick char **argv; 8312660Smckusick { 8412703Smckusick register struct fstab *fs; 8512802Smckusick register struct passwd *pw; 8641411Smckusick register struct group *gr; 8741411Smckusick int i, argnum, maxrun, errs = 0; 8841411Smckusick long auxdata, done = 0; 8941411Smckusick char ch, *name, *blockcheck(); 9041411Smckusick int needchk(), chkquota(); 9141411Smckusick extern char *optarg; 9241411Smckusick extern int optind; 9312660Smckusick 9441411Smckusick while ((ch = getopt(argc, argv, "aguvl:")) != EOF) { 9541411Smckusick switch(ch) { 9641411Smckusick case 'a': 9741411Smckusick aflag++; 9841411Smckusick break; 9941411Smckusick case 'g': 10041411Smckusick gflag++; 10141411Smckusick break; 10241411Smckusick case 'u': 10341411Smckusick uflag++; 10441411Smckusick break; 10541411Smckusick case 'v': 10641411Smckusick vflag++; 10741411Smckusick break; 10841411Smckusick case 'l': 10941411Smckusick maxrun = atoi(optarg); 11041411Smckusick break; 11141411Smckusick default: 11241411Smckusick usage(); 11341411Smckusick } 11412660Smckusick } 11541411Smckusick argc -= optind; 11641411Smckusick argv += optind; 11741411Smckusick if ((argc == 0 && !aflag) || (argc > 0 && aflag)) 11841411Smckusick usage(); 11941411Smckusick if (!gflag && !uflag) { 12041411Smckusick gflag++; 12141411Smckusick uflag++; 12212703Smckusick } 12341411Smckusick if (gflag) { 12441411Smckusick setgrent(); 12541411Smckusick while ((gr = getgrent()) != 0) 12641411Smckusick (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name); 12741411Smckusick endgrent(); 12824758Sserge } 12941411Smckusick if (uflag) { 13041411Smckusick setpwent(); 13141411Smckusick while ((pw = getpwent()) != 0) 13241411Smckusick (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name); 13341411Smckusick endpwent(); 13412660Smckusick } 13541411Smckusick if (aflag) 13641411Smckusick exit(checkfstab(1, maxrun, needchk, chkquota)); 13741411Smckusick if (setfsent() == 0) { 13841411Smckusick fprintf(stderr, "Can't open "); 13941411Smckusick perror(FSTAB); 14041411Smckusick exit(8); 14112802Smckusick } 14241411Smckusick while ((fs = getfsent()) != NULL) { 14341411Smckusick if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || 14441411Smckusick (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) && 14541411Smckusick (auxdata = needchk(fs)) && 14641411Smckusick (name = blockcheck(fs->fs_spec))) { 14741411Smckusick done |= 1 << argnum; 14841411Smckusick errs += chkquota(name, fs->fs_file, auxdata); 14924758Sserge } 15012660Smckusick } 15141411Smckusick endfsent(); 15212703Smckusick for (i = 0; i < argc; i++) 15312703Smckusick if ((done & (1 << i)) == 0) 15424782Sserge fprintf(stderr, "%s not found in %s\n", 15524782Sserge argv[i], FSTAB); 15612703Smckusick exit(errs); 15712703Smckusick } 15812660Smckusick 15941411Smckusick usage() 16024758Sserge { 161*46783Sbostic (void) fprintf(stderr, "usage:\t%s\n\t%s\n", 162*46783Sbostic "quotacheck -a [-guv]", 163*46783Sbostic "quotacheck [-guv] filesys ..."); 16441411Smckusick exit(1); 16541411Smckusick } 16624758Sserge 16741411Smckusick needchk(fs) 16841411Smckusick register struct fstab *fs; 16941411Smckusick { 17041443Smckusick register struct quotaname *qnp; 17141443Smckusick char *qfnp; 17224758Sserge 17341443Smckusick if (strcmp(fs->fs_vfstype, "ufs") || 17441443Smckusick strcmp(fs->fs_type, FSTAB_RW)) 17541443Smckusick return (0); 17641443Smckusick if ((qnp = (struct quotaname *)malloc(sizeof *qnp)) == 0) { 17741443Smckusick fprintf(stderr, "out of memory for quota structures\n"); 17841443Smckusick exit(1); 17941443Smckusick } 18041443Smckusick qnp->flags = 0; 18141443Smckusick if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) { 18241443Smckusick strcpy(qnp->grpqfname, qfnp); 18341443Smckusick qnp->flags |= HASGRP; 18441443Smckusick } 18541443Smckusick if (uflag && hasquota(fs, USRQUOTA, &qfnp)) { 18641443Smckusick strcpy(qnp->usrqfname, qfnp); 18741443Smckusick qnp->flags |= HASUSR; 18841443Smckusick } 18941443Smckusick if (qnp->flags) 19041443Smckusick return ((int)qnp); 19141443Smckusick free((char *)qnp); 19241443Smckusick return (0); 19341411Smckusick } 19424758Sserge 19541411Smckusick /* 19641411Smckusick * Scan the specified filesystem to check quota(s) present on it. 19741411Smckusick */ 19841443Smckusick chkquota(fsname, mntpt, qnp) 19941411Smckusick char *fsname, *mntpt; 20041443Smckusick register struct quotaname *qnp; 20141411Smckusick { 20241411Smckusick register struct fileusage *fup; 20341411Smckusick register struct dinode *dp; 20441411Smckusick int cg, i, mode, errs = 0; 20541411Smckusick ino_t ino; 20624758Sserge 20741411Smckusick if ((fi = open(fsname, 0)) < 0) { 20841411Smckusick perror(fsname); 20941411Smckusick return (1); 21041411Smckusick } 21141411Smckusick if (vflag) { 21241411Smckusick fprintf(stdout, "*** Checking "); 21341443Smckusick if (qnp->flags & HASUSR) 21441411Smckusick fprintf(stdout, "%s%s", qfextension[USRQUOTA], 21541443Smckusick (qnp->flags & HASGRP) ? " and " : ""); 21641443Smckusick if (qnp->flags & HASGRP) 21741411Smckusick fprintf(stdout, "%s", qfextension[GRPQUOTA]); 21841411Smckusick fprintf(stdout, " quotas for %s (%s)\n", fsname, mntpt); 21941411Smckusick } 22041411Smckusick sync(); 22141411Smckusick bread(SBOFF, (char *)&sblock, (long)SBSIZE); 22241411Smckusick dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1); 22341411Smckusick maxino = sblock.fs_ncg * sblock.fs_ipg; 22441411Smckusick resetinodebuf(); 22541411Smckusick for (ino = 0, cg = 0; cg < sblock.fs_ncg; cg++) { 22641411Smckusick for (i = 0; i < sblock.fs_ipg; i++, ino++) { 22741411Smckusick if (ino < ROOTINO) 22824758Sserge continue; 22941411Smckusick if ((dp = getnextinode(ino)) == NULL) 23024758Sserge continue; 23141411Smckusick if ((mode = dp->di_mode & IFMT) == 0) 23241411Smckusick continue; 23341443Smckusick if (qnp->flags & HASGRP) { 23441411Smckusick fup = addid((u_long)dp->di_gid, GRPQUOTA, 23541411Smckusick (char *)0); 23641411Smckusick fup->fu_curinodes++; 23741411Smckusick if (mode == IFREG || mode == IFDIR || 23841411Smckusick mode == IFLNK) 23941411Smckusick fup->fu_curblocks += dp->di_blocks; 24024758Sserge } 24141443Smckusick if (qnp->flags & HASUSR) { 24241411Smckusick fup = addid((u_long)dp->di_uid, USRQUOTA, 24341411Smckusick (char *)0); 24441411Smckusick fup->fu_curinodes++; 24541411Smckusick if (mode == IFREG || mode == IFDIR || 24641411Smckusick mode == IFLNK) 24741411Smckusick fup->fu_curblocks += dp->di_blocks; 24841411Smckusick } 24924758Sserge } 25041411Smckusick } 25141411Smckusick freeinodebuf(); 25241443Smckusick if (qnp->flags & HASUSR) 25341443Smckusick errs += update(mntpt, qnp->usrqfname, USRQUOTA); 25441443Smckusick if (qnp->flags & HASGRP) 25541443Smckusick errs += update(mntpt, qnp->grpqfname, GRPQUOTA); 25641411Smckusick close(fi); 25724758Sserge return (errs); 25824758Sserge } 25924758Sserge 26041411Smckusick /* 26141411Smckusick * Update a specified quota file. 26241411Smckusick */ 26341443Smckusick update(fsname, quotafile, type) 26441443Smckusick char *fsname, *quotafile; 26541411Smckusick register int type; 26612703Smckusick { 26712703Smckusick register struct fileusage *fup; 26825377Sserge register FILE *qfi, *qfo; 26941411Smckusick register u_long id, lastid; 27012703Smckusick struct dqblk dqbuf; 27121085Smckusick static int warned = 0; 27241411Smckusick static struct dqblk zerodqbuf; 27341411Smckusick static struct fileusage zerofileusage; 27412660Smckusick 27541411Smckusick if ((qfo = fopen(quotafile, "r+")) == NULL) { 276*46783Sbostic if (errno == ENOENT) 277*46783Sbostic qfo = fopen(quotafile, "w+"); 278*46783Sbostic if (qfo) { 279*46783Sbostic (void) fprintf(stderr, 280*46783Sbostic "quotacheck: creating quota file %s\n", quotafile); 281*46783Sbostic #define MODE (S_IRUSR|S_IWUSR|S_IRGRP) 282*46783Sbostic (void) fchown(fileno(qfo), getuid(), getquotagid()); 283*46783Sbostic (void) fchmod(fileno(qfo), MODE); 284*46783Sbostic } else { 285*46783Sbostic (void) fprintf(stderr, 286*46783Sbostic "quotacheck: %s: %s\n", quotafile, strerror(errno)); 28741411Smckusick return (1); 28841411Smckusick } 28912660Smckusick } 29041411Smckusick if ((qfi = fopen(quotafile, "r")) == NULL) { 291*46783Sbostic (void) fprintf(stderr, 292*46783Sbostic "quotacheck: %s: %s\n", quotafile, strerror(errno)); 293*46783Sbostic (void) fclose(qfo); 29412703Smckusick return (1); 29512660Smckusick } 29641411Smckusick if (quotactl(fsname, QCMD(Q_SYNC, type), (u_long)0, (caddr_t)0) < 0 && 29741411Smckusick errno == EOPNOTSUPP && !warned && vflag) { 29821085Smckusick warned++; 29941411Smckusick fprintf(stdout, "*** Warning: %s\n", 30041411Smckusick "Quotas are not compiled into this kernel"); 30121085Smckusick } 30241411Smckusick for (lastid = highid[type], id = 0; id <= lastid; id++) { 30341411Smckusick if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0) 30412802Smckusick dqbuf = zerodqbuf; 30541411Smckusick if ((fup = lookup(id, type)) == 0) 30624758Sserge fup = &zerofileusage; 30741411Smckusick if (dqbuf.dqb_curinodes == fup->fu_curinodes && 30841411Smckusick dqbuf.dqb_curblocks == fup->fu_curblocks) { 30941411Smckusick fup->fu_curinodes = 0; 31041411Smckusick fup->fu_curblocks = 0; 31125377Sserge fseek(qfo, (long)sizeof(struct dqblk), 1); 31212703Smckusick continue; 31312802Smckusick } 31412703Smckusick if (vflag) { 31541411Smckusick if (aflag) 31641411Smckusick printf("%s: ", fsname); 31741411Smckusick printf("%-8s fixed:", fup->fu_name); 31841411Smckusick if (dqbuf.dqb_curinodes != fup->fu_curinodes) 31925377Sserge fprintf(stdout, "\tinodes %d -> %d", 32041411Smckusick dqbuf.dqb_curinodes, fup->fu_curinodes); 32141411Smckusick if (dqbuf.dqb_curblocks != fup->fu_curblocks) 32225377Sserge fprintf(stdout, "\tblocks %d -> %d", 32341411Smckusick dqbuf.dqb_curblocks, fup->fu_curblocks); 32424758Sserge fprintf(stdout, "\n"); 32512660Smckusick } 32641411Smckusick /* 32741411Smckusick * Reset time limit if have a soft limit and were 32841411Smckusick * previously under it, but are now over it. 32941411Smckusick */ 33041411Smckusick if (dqbuf.dqb_bsoftlimit && 33141411Smckusick dqbuf.dqb_curblocks < dqbuf.dqb_bsoftlimit && 33241411Smckusick fup->fu_curblocks >= dqbuf.dqb_bsoftlimit) 33341411Smckusick dqbuf.dqb_btime = 0; 33441411Smckusick if (dqbuf.dqb_isoftlimit && 33541411Smckusick dqbuf.dqb_curblocks < dqbuf.dqb_isoftlimit && 33641411Smckusick fup->fu_curblocks >= dqbuf.dqb_isoftlimit) 33741411Smckusick dqbuf.dqb_itime = 0; 33841411Smckusick dqbuf.dqb_curinodes = fup->fu_curinodes; 33941411Smckusick dqbuf.dqb_curblocks = fup->fu_curblocks; 34041411Smckusick fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo); 34141411Smckusick (void) quotactl(fsname, QCMD(Q_SETUSE, type), id, 34241411Smckusick (caddr_t)&dqbuf); 34341411Smckusick fup->fu_curinodes = 0; 34441411Smckusick fup->fu_curblocks = 0; 34512660Smckusick } 34641411Smckusick fclose(qfi); 34725377Sserge fflush(qfo); 34841411Smckusick ftruncate(fileno(qfo), 34941411Smckusick (off_t)((highid[type] + 1) * sizeof(struct dqblk))); 35025377Sserge fclose(qfo); 35112703Smckusick return (0); 35212660Smckusick } 35312660Smckusick 35441411Smckusick /* 35541411Smckusick * Check to see if target appears in list of size cnt. 35641411Smckusick */ 35741411Smckusick oneof(target, list, cnt) 35841411Smckusick register char *target, *list[]; 35941411Smckusick int cnt; 36012660Smckusick { 36112703Smckusick register int i; 36212660Smckusick 36341411Smckusick for (i = 0; i < cnt; i++) 36441411Smckusick if (strcmp(target, list[i]) == 0) 36541411Smckusick return (i); 36641411Smckusick return (-1); 36712660Smckusick } 36812660Smckusick 36941411Smckusick /* 37041443Smckusick * Determine the group identifier for quota files. 37141443Smckusick */ 37241443Smckusick getquotagid() 37341443Smckusick { 37441443Smckusick struct group *gr; 37541443Smckusick 37641443Smckusick if (gr = getgrnam(quotagroup)) 37741443Smckusick return (gr->gr_gid); 37841443Smckusick return (-1); 37941443Smckusick } 38041443Smckusick 38141443Smckusick /* 38241411Smckusick * Check to see if a particular quota is to be enabled. 38341411Smckusick */ 38441443Smckusick hasquota(fs, type, qfnamep) 38541443Smckusick register struct fstab *fs; 38641411Smckusick int type; 38741443Smckusick char **qfnamep; 38812660Smckusick { 38941411Smckusick register char *opt; 39041443Smckusick char *cp, *index(), *strtok(); 39141411Smckusick static char initname, usrname[100], grpname[100]; 39241443Smckusick static char buf[BUFSIZ]; 39312660Smckusick 39441411Smckusick if (!initname) { 39541411Smckusick sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname); 39641411Smckusick sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname); 39741411Smckusick initname = 1; 39812660Smckusick } 39941443Smckusick strcpy(buf, fs->fs_mntops); 40041411Smckusick for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { 40141443Smckusick if (cp = index(opt, '=')) 40241443Smckusick *cp++ = '\0'; 40341411Smckusick if (type == USRQUOTA && strcmp(opt, usrname) == 0) 40441443Smckusick break; 40541411Smckusick if (type == GRPQUOTA && strcmp(opt, grpname) == 0) 40641443Smckusick break; 40725377Sserge } 40841443Smckusick if (!opt) 40941443Smckusick return (0); 41041443Smckusick if (cp) { 41141443Smckusick *qfnamep = cp; 41241443Smckusick return (1); 41341443Smckusick } 41441443Smckusick (void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]); 41541443Smckusick *qfnamep = buf; 41641443Smckusick return (1); 41712660Smckusick } 41812660Smckusick 41941411Smckusick /* 42041411Smckusick * Routines to manage the file usage table. 42141411Smckusick * 42241411Smckusick * Lookup an id of a specific type. 42341411Smckusick */ 42412703Smckusick struct fileusage * 42541411Smckusick lookup(id, type) 42641411Smckusick u_long id; 42741411Smckusick int type; 42812660Smckusick { 42912703Smckusick register struct fileusage *fup; 43012660Smckusick 43141411Smckusick for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next) 43241411Smckusick if (fup->fu_id == id) 43312703Smckusick return (fup); 43412703Smckusick return ((struct fileusage *)0); 43512660Smckusick } 43612660Smckusick 43741411Smckusick /* 43841411Smckusick * Add a new file usage id if it does not already exist. 43941411Smckusick */ 44012703Smckusick struct fileusage * 44141411Smckusick addid(id, type, name) 44241411Smckusick u_long id; 44341411Smckusick int type; 44441411Smckusick char *name; 44512660Smckusick { 44612703Smckusick struct fileusage *fup, **fhp; 44741411Smckusick int len; 44812660Smckusick 44941411Smckusick if (fup = lookup(id, type)) 45012703Smckusick return (fup); 45141411Smckusick if (name) 45241411Smckusick len = strlen(name); 45341411Smckusick else 45441411Smckusick len = 10; 45541411Smckusick if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) { 45612703Smckusick fprintf(stderr, "out of memory for fileusage structures\n"); 45712703Smckusick exit(1); 45812703Smckusick } 45941411Smckusick fhp = &fuhead[type][id & (FUHASH - 1)]; 46012703Smckusick fup->fu_next = *fhp; 46112703Smckusick *fhp = fup; 46241411Smckusick fup->fu_id = id; 46341411Smckusick if (id > highid[type]) 46441411Smckusick highid[type] = id; 46541411Smckusick if (name) { 46641411Smckusick bcopy(name, fup->fu_name, len + 1); 46741411Smckusick } else { 46841411Smckusick sprintf(fup->fu_name, "%u", id); 46941411Smckusick } 47012703Smckusick return (fup); 47112660Smckusick } 47212660Smckusick 47341411Smckusick /* 47441411Smckusick * Special purpose version of ginode used to optimize pass 47541411Smckusick * over all the inodes in numerical order. 47641411Smckusick */ 47741411Smckusick ino_t nextino, lastinum; 47841411Smckusick long readcnt, readpercg, fullcnt, inobufsize, partialcnt, partialsize; 47941411Smckusick struct dinode *inodebuf; 48041411Smckusick #define INOBUFSIZE 56*1024 /* size of buffer to read inodes */ 48141411Smckusick 48241411Smckusick struct dinode * 48341411Smckusick getnextinode(inumber) 48441411Smckusick ino_t inumber; 48512660Smckusick { 48641411Smckusick long size; 48741411Smckusick daddr_t dblk; 48841411Smckusick static struct dinode *dp; 48912660Smckusick 49041411Smckusick if (inumber != nextino++ || inumber > maxino) { 49141411Smckusick fprintf(stderr, "bad inode number %d to nextinode\n", inumber); 49241411Smckusick exit(1); 49312703Smckusick } 49441411Smckusick if (inumber >= lastinum) { 49541411Smckusick readcnt++; 49641411Smckusick dblk = fsbtodb(&sblock, itod(&sblock, lastinum)); 49741411Smckusick if (readcnt % readpercg == 0) { 49841411Smckusick size = partialsize; 49941411Smckusick lastinum += partialcnt; 50041411Smckusick } else { 50141411Smckusick size = inobufsize; 50241411Smckusick lastinum += fullcnt; 50341411Smckusick } 50441411Smckusick bread(dblk, (char *)inodebuf, size); 50541411Smckusick dp = inodebuf; 50641411Smckusick } 50741411Smckusick return (dp++); 50812660Smckusick } 50941411Smckusick 51041411Smckusick /* 51141411Smckusick * Prepare to scan a set of inodes. 51241411Smckusick */ 51341411Smckusick resetinodebuf() 51441411Smckusick { 51541411Smckusick 51641411Smckusick nextino = 0; 51741411Smckusick lastinum = 0; 51841411Smckusick readcnt = 0; 51941411Smckusick inobufsize = blkroundup(&sblock, INOBUFSIZE); 52041411Smckusick fullcnt = inobufsize / sizeof(struct dinode); 52141411Smckusick readpercg = sblock.fs_ipg / fullcnt; 52241411Smckusick partialcnt = sblock.fs_ipg % fullcnt; 52341411Smckusick partialsize = partialcnt * sizeof(struct dinode); 52441411Smckusick if (partialcnt != 0) { 52541411Smckusick readpercg++; 52641411Smckusick } else { 52741411Smckusick partialcnt = fullcnt; 52841411Smckusick partialsize = inobufsize; 52941411Smckusick } 53041411Smckusick if (inodebuf == NULL && 53141411Smckusick (inodebuf = (struct dinode *)malloc((unsigned)inobufsize)) == NULL) { 53241411Smckusick fprintf(stderr, "Cannot allocate space for inode buffer\n"); 53341411Smckusick exit(1); 53441411Smckusick } 53541411Smckusick while (nextino < ROOTINO) 53641411Smckusick getnextinode(nextino); 53741411Smckusick } 53841411Smckusick 53941411Smckusick /* 54041411Smckusick * Free up data structures used to scan inodes. 54141411Smckusick */ 54241411Smckusick freeinodebuf() 54341411Smckusick { 54441411Smckusick 54541411Smckusick if (inodebuf != NULL) 54641411Smckusick free((char *)inodebuf); 54741411Smckusick inodebuf = NULL; 54841411Smckusick } 54941411Smckusick 55041411Smckusick /* 55141411Smckusick * Read specified disk blocks. 55241411Smckusick */ 55341411Smckusick bread(bno, buf, cnt) 55441411Smckusick daddr_t bno; 55541411Smckusick char *buf; 55641411Smckusick long cnt; 55741411Smckusick { 55841411Smckusick 55941411Smckusick if (lseek(fi, bno * dev_bsize, 0) < 0) { 56041411Smckusick perror("lseek"); 56141411Smckusick exit(1); 56241411Smckusick } 56341411Smckusick 56441411Smckusick if (read(fi, buf, cnt) != cnt) { 56541411Smckusick perror("read"); 56641411Smckusick exit(1); 56741411Smckusick } 56841411Smckusick } 569