From 3af26d4abba3ad1858920eedf0710663499167f1 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Sun, 27 Dec 2009 06:28:01 +0000 Subject: [PATCH] Convert quotacheck to use new quotafile functions in libutil. Still to come, conversion between 64-bit and 32-bit quotafile formats. --- sbin/quotacheck/Makefile | 2 + sbin/quotacheck/preen.c | 77 ++++++----- sbin/quotacheck/quotacheck.c | 254 +++++++++-------------------------- sbin/quotacheck/quotacheck.h | 12 +- 4 files changed, 109 insertions(+), 236 deletions(-) diff --git a/sbin/quotacheck/Makefile b/sbin/quotacheck/Makefile index 5184bf261f1e..51a88b7681c7 100644 --- a/sbin/quotacheck/Makefile +++ b/sbin/quotacheck/Makefile @@ -5,6 +5,8 @@ PROG= quotacheck SRCS= quotacheck.c preen.c fsutil.c utilities.c WARNS?= 2 MAN= quotacheck.8 +DPADD= ${LIBUTIL} +LDADD= -lutil .PATH: ${.CURDIR}/../fsck ${.CURDIR}/../fsck_ffs diff --git a/sbin/quotacheck/preen.c b/sbin/quotacheck/preen.c index a6c4169ee55e..1c285ccae9ce 100644 --- a/sbin/quotacheck/preen.c +++ b/sbin/quotacheck/preen.c @@ -45,9 +45,13 @@ __RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $"); #include #include +#include + #include #include +#include #include +#include #include #include #include @@ -58,9 +62,9 @@ __RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $"); struct partentry { TAILQ_ENTRY(partentry) p_entries; char *p_devname; /* device name */ - char *p_mntpt; /* mount point */ - char *p_type; /* file system type */ - struct quotaname *p_quota; /* quota file info ptr */ + const char *p_mntpt; /* mount point */ + struct quotafile *p_qfu; /* user quota file info ptr */ + struct quotafile *p_qfg; /* group quota file info */ }; TAILQ_HEAD(part, partentry) badh; @@ -75,21 +79,19 @@ struct diskentry { TAILQ_HEAD(disk, diskentry) diskh; static struct diskentry *finddisk(const char *); -static void addpart(const char *, const char *, const char *, - struct quotaname *); +static void addpart(struct fstab *, struct quotafile *, struct quotafile *); static int startdisk(struct diskentry *); extern void *emalloc(size_t); extern char *estrdup(const char *); int -checkfstab(void) +checkfstab(int uflag, int gflag) { struct fstab *fs; struct diskentry *d, *nextdisk; struct partentry *p; int ret, pid, retcode, passno, sumstatus, status, nextpass; - char *name; - struct quotaname *qnp; + struct quotafile *qfu, *qfg; TAILQ_INIT(&badh); TAILQ_INIT(&diskh); @@ -104,30 +106,32 @@ checkfstab(void) return (8); } while ((fs = getfsent()) != 0) { - name = fs->fs_spec; if (fs->fs_passno > passno && fs->fs_passno < nextpass) nextpass = fs->fs_passno; if (passno != fs->fs_passno) continue; - if ((qnp = needchk(fs)) == NULL) + qfu = NULL; + if (uflag) + qfu = quota_open(fs, USRQUOTA, O_CREAT|O_RDWR); + qfg = NULL; + if (gflag) + qfg = quota_open(fs, GRPQUOTA, O_CREAT|O_RDWR); + if (qfu == NULL && qfg == NULL) continue; if (passno == 1) { - sumstatus = chkquota(name, fs->fs_file, qnp); - + sumstatus = chkquota(fs->fs_spec, qfu, qfg); + if (qfu) + quota_close(qfu); + if (qfg) + quota_close(qfg); if (sumstatus) return (sumstatus); continue; } - if (name == NULL) { - (void) fprintf(stderr, - "BAD DISK NAME %s\n", fs->fs_spec); - sumstatus |= 8; - continue; - } - addpart(fs->fs_vfstype, name, fs->fs_file, qnp); + addpart(fs, qfu, qfg); } if (passno == 1) @@ -157,8 +161,8 @@ checkfstab(void) if (WIFSIGNALED(status)) { (void) fprintf(stderr, - "%s: %s (%s): EXITED WITH SIGNAL %d\n", - p->p_type, p->p_devname, p->p_mntpt, + "%s: (%s): EXITED WITH SIGNAL %d\n", + p->p_devname, p->p_mntpt, WTERMSIG(status)); retcode = 8; } @@ -169,8 +173,11 @@ checkfstab(void) TAILQ_INSERT_TAIL(&badh, p, p_entries); sumstatus |= retcode; } else { - free(p->p_type); free(p->p_devname); + if (p->p_qfu) + quota_close(p->p_qfu); + if (p->p_qfg) + quota_close(p->p_qfg); free(p); } d->d_pid = 0; @@ -196,8 +203,8 @@ checkfstab(void) for (; p; p = TAILQ_NEXT(p, p_entries)) (void) fprintf(stderr, - "%s: %s (%s)%s", p->p_type, p->p_devname, - p->p_mntpt, TAILQ_NEXT(p, p_entries) ? ", " : "\n"); + "%s: (%s)%s", p->p_devname, p->p_mntpt, + TAILQ_NEXT(p, p_entries) ? ", " : "\n"); return sumstatus; } @@ -242,23 +249,25 @@ finddisk(const char *name) } static void -addpart(const char *type, const char *devname, const char *mntpt, - struct quotaname *qnp) +addpart(struct fstab *fs, struct quotafile *qfu, struct quotafile *qfg) { - struct diskentry *d = finddisk(devname); + struct diskentry *d = finddisk(fs->fs_spec); struct partentry *p; TAILQ_FOREACH(p, &d->d_part, p_entries) - if (strcmp(p->p_devname, devname) == 0) { - warnx("%s in fstab more than once!\n", devname); + if (strcmp(p->p_devname, fs->fs_spec) == 0) { + warnx("%s in fstab more than once!\n", fs->fs_spec); return; } p = emalloc(sizeof(*p)); - p->p_devname = estrdup(devname); - p->p_mntpt = estrdup(mntpt); - p->p_type = estrdup(type); - p->p_quota = qnp; + p->p_devname = estrdup(blockcheck(fs->fs_spec)); + if (qfu != NULL) + p->p_mntpt = quota_fsname(qfu); + else + p->p_mntpt = quota_fsname(qfg); + p->p_qfu = qfu; + p->p_qfg = qfg; TAILQ_INSERT_TAIL(&d->d_part, p, p_entries); } @@ -275,6 +284,6 @@ startdisk(struct diskentry *d) return (8); } if (d->d_pid == 0) - exit(chkquota(p->p_devname, p->p_mntpt, p->p_quota)); + exit(chkquota(p->p_devname, p->p_qfu, p->p_qfg)); return (0); } diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c index 863932a12d2e..026608a419b6 100644 --- a/sbin/quotacheck/quotacheck.c +++ b/sbin/quotacheck/quotacheck.c @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -115,21 +116,19 @@ int vflag; /* verbose */ int fi; /* open disk file descriptor */ struct fileusage * - addid(u_long, int, char *, char *); -char *blockcheck(char *); + addid(u_long, int, char *, const char *); void bread(ufs2_daddr_t, char *, long); void freeinodebuf(void); union dinode * getnextinode(ino_t); int getquotagid(void); -int hasquota(struct fstab *, int, char **); struct fileusage * lookup(u_long, int); -struct quotaname *needchk(struct fstab *); int oneof(char *, char*[], int); -void printchanges(char *, int, struct dqblk *, struct fileusage *, u_long); +void printchanges(const char *, int, struct dqblk *, struct fileusage *, + u_long); void setinodebuf(ino_t); -int update(char *, char *, int); +int update(const char *, struct quotafile *, int); void usage(void); int @@ -138,7 +137,7 @@ main(int argc, char *argv[]) struct fstab *fs; struct passwd *pw; struct group *gr; - struct quotaname *qnp; + struct quotafile *qfu, *qfg; int i, argnum, maxrun, errs, ch; long done = 0; char *name; @@ -193,16 +192,27 @@ main(int argc, char *argv[]) if (maxrun > 0) warnx("the -l option is now deprecated"); if (aflag) - exit(checkfstab()); + exit(checkfstab(uflag, gflag)); if (setfsent() == 0) errx(1, "%s: can't open", FSTAB); while ((fs = getfsent()) != NULL) { if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || - (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) && - (qnp = needchk(fs)) && + (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) && (name = blockcheck(fs->fs_spec))) { done |= 1 << argnum; - errs += chkquota(name, fs->fs_file, qnp); + qfu = NULL; + if (uflag) + qfu = quota_open(fs, USRQUOTA, O_CREAT|O_RDWR); + qfg = NULL; + if (gflag) + qfg = quota_open(fs, GRPQUOTA, O_CREAT|O_RDWR); + if (qfu == NULL && qfg == NULL) + continue; + errs += chkquota(name, qfu, qfg); + if (qfu) + quota_close(qfu); + if (qfg) + quota_close(qfg); } } endfsent(); @@ -222,32 +232,6 @@ usage(void) exit(1); } -struct quotaname * -needchk(struct fstab *fs) -{ - struct quotaname *qnp; - char *qfnp; - - if (strcmp(fs->fs_vfstype, "ufs") || - strcmp(fs->fs_type, FSTAB_RW)) - return (NULL); - if ((qnp = malloc(sizeof(*qnp))) == NULL) - errx(1, "malloc failed"); - qnp->flags = 0; - if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) { - strcpy(qnp->grpqfname, qfnp); - qnp->flags |= HASGRP; - } - if (uflag && hasquota(fs, USRQUOTA, &qfnp)) { - strcpy(qnp->usrqfname, qfnp); - qnp->flags |= HASUSR; - } - if (qnp->flags) - return (qnp); - free(qnp); - return (NULL); -} - /* * Possible superblock locations ordered from most to least likely. */ @@ -257,20 +241,25 @@ static int sblock_try[] = SBLOCKSEARCH; * Scan the specified file system to check quota(s) present on it. */ int -chkquota(char *fsname, char *mntpt, struct quotaname *qnp) +chkquota(char *specname, struct quotafile *qfu, struct quotafile *qfg) { struct fileusage *fup; union dinode *dp; int cg, i, mode, errs = 0; ino_t ino, inosused, userino = 0, groupino = 0; dev_t dev, userdev = 0, groupdev = 0; - char *cp; struct stat sb; + const char *mntpt; + char *cp; - if (qnp == NULL) - err(1, "null quota information passed to chkquota()\n"); - if ((fi = open(fsname, O_RDONLY, 0)) < 0) { - warn("%s", fsname); + if (qfu != NULL) + mntpt = quota_fsname(qfu); + else if (qfg != NULL) + mntpt = quota_fsname(qfg); + else + err(1, "null quotafile information passed to chkquota()\n"); + if ((fi = open(specname, O_RDONLY, 0)) < 0) { + warn("%s", specname); return (1); } if ((stat(mntpt, &sb)) < 0) { @@ -280,21 +269,20 @@ chkquota(char *fsname, char *mntpt, struct quotaname *qnp) dev = sb.st_dev; if (vflag) { (void)printf("*** Checking "); - if (qnp->flags & HASUSR) - (void)printf("%s%s", qfextension[USRQUOTA], - (qnp->flags & HASGRP) ? " and " : ""); - if (qnp->flags & HASGRP) - (void)printf("%s", qfextension[GRPQUOTA]); - (void)printf(" quotas for %s (%s)\n", fsname, mntpt); + if (qfu) + (void)printf("user%s", qfg ? " and " : ""); + if (qfg) + (void)printf("group"); + (void)printf(" quotas for %s (%s)\n", specname, mntpt); } - if (qnp->flags & HASUSR) { - if (stat(qnp->usrqfname, &sb) == 0) { + if (qfu) { + if (stat(quota_qfname(qfu), &sb) == 0) { userino = sb.st_ino; userdev = sb.st_dev; } } - if (qnp->flags & HASGRP) { - if (stat(qnp->grpqfname, &sb) == 0) { + if (qfg) { + if (stat(quota_qfname(qfg), &sb) == 0) { groupino = sb.st_ino; groupdev = sb.st_dev; } @@ -382,7 +370,7 @@ chkquota(char *fsname, char *mntpt, struct quotaname *qnp) if ((ino == userino && dev == userdev) || (ino == groupino && dev == groupdev)) continue; - if (qnp->flags & HASGRP) { + if (qfg) { fup = addid((u_long)DIP(dp, di_gid), GRPQUOTA, (char *)0, mntpt); fup->fu_curinodes++; @@ -390,7 +378,7 @@ chkquota(char *fsname, char *mntpt, struct quotaname *qnp) mode == IFLNK) fup->fu_curblocks += DIP(dp, di_blocks); } - if (qnp->flags & HASUSR) { + if (qfu) { fup = addid((u_long)DIP(dp, di_uid), USRQUOTA, (char *)0, mntpt); fup->fu_curinodes++; @@ -401,10 +389,10 @@ chkquota(char *fsname, char *mntpt, struct quotaname *qnp) } } freeinodebuf(); - if (qnp->flags & HASUSR) - errs += update(mntpt, qnp->usrqfname, USRQUOTA); - if (qnp->flags & HASGRP) - errs += update(mntpt, qnp->grpqfname, GRPQUOTA); + if (qfu) + errs += update(mntpt, qfu, USRQUOTA); + if (qfg) + errs += update(mntpt, qfg, GRPQUOTA); close(fi); (void)fflush(stdout); return (errs); @@ -414,63 +402,20 @@ chkquota(char *fsname, char *mntpt, struct quotaname *qnp) * Update a specified quota file. */ int -update(char *fsname, char *quotafile, int type) +update(const char *fsname, struct quotafile *qf, int type) { struct fileusage *fup; - FILE *qfi, *qfo; u_long id, lastid, highid = 0; - off_t offset; - int i; struct dqblk dqbuf; - struct stat sb; - static int warned = 0; static struct dqblk zerodqbuf; static struct fileusage zerofileusage; - if ((qfo = fopen(quotafile, "r+")) == NULL) { - if (errno == ENOENT) - qfo = fopen(quotafile, "w+"); - if (qfo) { - warnx("creating quota file %s", quotafile); -#define MODE (S_IRUSR|S_IWUSR|S_IRGRP) - (void) fchown(fileno(qfo), getuid(), getquotagid()); - (void) fchmod(fileno(qfo), MODE); - } else { - warn("%s", quotafile); - return (1); - } - } - if ((qfi = fopen(quotafile, "r")) == NULL) { - warn("%s", quotafile); - (void) fclose(qfo); - return (1); - } - if (quotactl(fsname, QCMD(Q_SYNC, type), (u_long)0, (caddr_t)0) < 0 && - errno == EOPNOTSUPP && !warned && vflag) { - warned++; - (void)printf("*** Warning: %s\n", - "Quotas are not compiled into this kernel"); - } - if (fstat(fileno(qfi), &sb) < 0) { - warn("Cannot fstat quota file %s\n", quotafile); - (void) fclose(qfo); - (void) fclose(qfi); - return (1); - } - if ((sb.st_size % sizeof(struct dqblk)) != 0) - warn("%s size is not a multiple of dqblk\n", quotafile); - /* * Scan the on-disk quota file and record any usage changes. */ - - if (sb.st_size != 0) - lastid = (sb.st_size / sizeof(struct dqblk)) - 1; - else - lastid = 0; - for (id = 0, offset = 0; id <= lastid; - id++, offset += sizeof(struct dqblk)) { - if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0) + lastid = quota_maxid(qf); + for (id = 0; id <= lastid; id++) { + if (quota_read(qf, &dqbuf, id) < 0) dqbuf = zerodqbuf; if ((fup = lookup(id, type)) == NULL) fup = &zerofileusage; @@ -485,27 +430,9 @@ update(char *fsname, char *quotafile, int type) continue; } printchanges(fsname, type, &dqbuf, fup, id); - /* - * Reset time limit if have a soft limit and were - * previously under it, but are now over it. - */ - if (dqbuf.dqb_bsoftlimit && id != 0 && - dqbuf.dqb_curblocks < dqbuf.dqb_bsoftlimit && - fup->fu_curblocks >= dqbuf.dqb_bsoftlimit) - dqbuf.dqb_btime = 0; - if (dqbuf.dqb_isoftlimit && id != 0 && - dqbuf.dqb_curinodes < dqbuf.dqb_isoftlimit && - fup->fu_curinodes >= dqbuf.dqb_isoftlimit) - dqbuf.dqb_itime = 0; dqbuf.dqb_curinodes = fup->fu_curinodes; dqbuf.dqb_curblocks = fup->fu_curblocks; - if (fseeko(qfo, offset, SEEK_SET) < 0) { - warn("%s: seek failed", quotafile); - return(1); - } - fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo); - (void) quotactl(fsname, QCMD(Q_SETUSE, type), id, - (caddr_t)&dqbuf); + (void) quota_write_usage(qf, &dqbuf, id); fup->fu_curinodes = 0; fup->fu_curblocks = 0; } @@ -515,9 +442,8 @@ update(char *fsname, char *quotafile, int type) * that are not currently recorded in the quota file. E.g. * ids that are past the end of the current file. */ - - for (i = 0; i < FUHASH; i++) { - for (fup = fuhead[type][i]; fup != NULL; fup = fup->fu_next) { + for (id = 0; id < FUHASH; id++) { + for (fup = fuhead[type][id]; fup != NULL; fup = fup->fu_next) { if (fup->fu_id <= lastid) continue; if (fup->fu_curinodes == 0 && fup->fu_curblocks == 0) @@ -525,26 +451,17 @@ update(char *fsname, char *quotafile, int type) bzero(&dqbuf, sizeof(struct dqblk)); if (fup->fu_id > highid) highid = fup->fu_id; - printchanges(fsname, type, &dqbuf, fup, id); + printchanges(fsname, type, &dqbuf, fup, fup->fu_id); dqbuf.dqb_curinodes = fup->fu_curinodes; dqbuf.dqb_curblocks = fup->fu_curblocks; - offset = (off_t)fup->fu_id * sizeof(struct dqblk); - if (fseeko(qfo, offset, SEEK_SET) < 0) { - warn("%s: seek failed", quotafile); - return(1); - } - fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo); - (void) quotactl(fsname, QCMD(Q_SETUSE, type), id, - (caddr_t)&dqbuf); + (void) quota_write_usage(qf, &dqbuf, fup->fu_id); fup->fu_curinodes = 0; fup->fu_curblocks = 0; } } - fclose(qfi); - fflush(qfo); - ftruncate(fileno(qfo), - (((off_t)highid + 1) * sizeof(struct dqblk))); - fclose(qfo); + if (highid < lastid) + truncate(quota_qfname(qf), + (((off_t)highid + 2) * sizeof(struct dqblk))); return (0); } @@ -575,55 +492,6 @@ getquotagid(void) return (-1); } -/* - * Check to see if a particular quota is to be enabled. - */ -int -hasquota(struct fstab *fs, int type, char **qfnamep) -{ - char *opt; - char *cp; - struct statfs sfb; - static char initname, usrname[100], grpname[100]; - static char buf[BUFSIZ]; - - if (!initname) { - (void)snprintf(usrname, sizeof(usrname), "%s%s", - qfextension[USRQUOTA], qfname); - (void)snprintf(grpname, sizeof(grpname), "%s%s", - qfextension[GRPQUOTA], qfname); - initname = 1; - } - strcpy(buf, fs->fs_mntops); - for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { - if ((cp = index(opt, '=')) != NULL) - *cp++ = '\0'; - if (type == USRQUOTA && strcmp(opt, usrname) == 0) - break; - if (type == GRPQUOTA && strcmp(opt, grpname) == 0) - break; - } - if (!opt) - return (0); - if (cp) - *qfnamep = cp; - else { - (void)snprintf(buf, sizeof(buf), "%s/%s.%s", fs->fs_file, - qfname, qfextension[type]); - *qfnamep = buf; - } - if (statfs(fs->fs_file, &sfb) != 0) { - warn("cannot statfs mount point %s", fs->fs_file); - return (0); - } - if (strcmp(fs->fs_file, sfb.f_mntonname)) { - warnx("%s not mounted for %s quotas", fs->fs_file, - type == USRQUOTA ? "user" : "group"); - return (0); - } - return (1); -} - /* * Routines to manage the file usage table. * @@ -644,7 +512,7 @@ lookup(u_long id, int type) * Add a new file usage id if it does not already exist. */ struct fileusage * -addid(u_long id, int type, char *name, char *fsname) +addid(u_long id, int type, char *name, const char *fsname) { struct fileusage *fup, **fhp; int len; @@ -779,7 +647,7 @@ bread(ufs2_daddr_t bno, char *buf, long cnt) * Display updated block and i-node counts. */ void -printchanges(char *fsname, int type, struct dqblk *dp, +printchanges(const char *fsname, int type, struct dqblk *dp, struct fileusage *fup, u_long id) { if (!vflag) diff --git a/sbin/quotacheck/quotacheck.h b/sbin/quotacheck/quotacheck.h index aad9d30a76a8..dcff75b68a8c 100644 --- a/sbin/quotacheck/quotacheck.h +++ b/sbin/quotacheck/quotacheck.h @@ -32,12 +32,6 @@ * $FreeBSD$ */ -struct quotaname { - long flags; - char grpqfname[PATH_MAX]; - char usrqfname[PATH_MAX]; -}; - -extern int checkfstab(); -extern int chkquota(char *, char *, struct quotaname *); -extern struct quotaname *needchk(struct fstab *); +extern char *blockcheck(char *); +extern int checkfstab(int, int); +extern int chkquota(char *, struct quotafile *, struct quotafile *);