From bc47c58ac28bea3666ae128f9493f58195baee64 Mon Sep 17 00:00:00 2001 From: jkar8572 Date: Wed, 11 Apr 2001 10:12:36 +0000 Subject: Updated manpages. Fixed small bug in repquota (User vs Group). Some XFS updates. Fixed problems with devfs and relative paths. --- Makefile.in | 3 +- common.c | 29 ++++++++ common.h | 6 ++ convertquota.c | 2 +- edquota.8 | 2 +- edquota.c | 4 +- quot.8 | 21 ++++-- quot.c | 210 ++++++++++++++++++++++++++++++++++----------------------- quot.h | 16 ++--- quotacheck.c | 6 +- quotaio.c | 2 + quotaio.h | 2 + quotaio_xfs.c | 14 ++-- quotaon.c | 9 ++- quotaops.c | 6 +- quotasys.c | 36 ++++++++-- quotasys.h | 6 ++ repquota.c | 6 +- setquota.8 | 59 +++++++++++++--- 19 files changed, 298 insertions(+), 141 deletions(-) diff --git a/Makefile.in b/Makefile.in index 7033965..3f7772f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -78,7 +78,8 @@ install: all inst_mo $(LN) quotaon $(ROOTDIR)$(root_sbindir)/quotaoff chown -h $(BIN_OWNER):$(BIN_GROUP) $(ROOTDIR)$(root_sbindir)/quotaoff -$(INSTALL) -m $(DEF_SBIN_MODE) \ - edquota repquota warnquota quotastats setquota quot $(ROOTDIR)$(sbindir) + edquota repquota warnquota quotastats setquota quot xqmstats \ + $(ROOTDIR)$(sbindir) -$(INSTALL) -m 755 -d $(ROOTDIR)$(includedir)/rpcsvc -$(INSTALL) -m 644 rquota.h rquota.x $(ROOTDIR)$(includedir)/rpcsvc -$(INSTALL) -s -m $(DEF_SBIN_MODE) quota $(ROOTDIR)$(bindir) diff --git a/common.c b/common.c index 754c7ac..96f1747 100644 --- a/common.c +++ b/common.c @@ -11,6 +11,7 @@ #include #include +#include #include "pot.h" #include "common.h" @@ -59,6 +60,34 @@ char *sstrdup(const char *s) return r; } +int devcmp(const char *mtab_dev, char *user_dev) +{ + struct stat mtab_stat, user_stat; + + if (stat(mtab_dev, &mtab_stat) < 0 || stat(user_dev, &user_stat) < 0) + return (strcmp(mtab_dev, user_dev) == 0); + if (!S_ISBLK(mtab_stat.st_mode) || !S_ISBLK(user_stat.st_mode)) + return 0; + if (mtab_stat.st_rdev != user_stat.st_rdev) + return 0; + return 1; +} + +int dircmp(char *mtab_dir, char *user_dir) +{ + struct stat mtab_stat, user_stat; + + if (stat(mtab_dir, &mtab_stat) < 0 || stat(user_dir, &user_stat) < 0) + return (strcmp(mtab_dir, user_dir) == 0); + if (!S_ISDIR(mtab_stat.st_mode) || !S_ISDIR(user_stat.st_mode)) + return 0; + if (mtab_stat.st_dev != user_stat.st_dev) + return 0; + if (mtab_stat.st_ino != user_stat.st_ino) + return 0; + return 1; +} + void version(void) { printf(_("Quota utilities version %s.\n"), QUOTA_VERSION); diff --git a/common.h b/common.h index 58119a6..3b779a5 100644 --- a/common.h +++ b/common.h @@ -24,6 +24,12 @@ void sstrncat(char *, const char *, int); /* Safe version of strdup() */ char *sstrdup(const char *s); +/* Test whether two file names are for the same device */ +int devcmp(const char *mtab_dev, char *user_dev); + +/* Test whether two file names are for the same directory */ +int dircmp(char *mtab_dir, char *user_dir); + /* Print version string */ void version(void); diff --git a/convertquota.c b/convertquota.c index 73696d8..5422081 100644 --- a/convertquota.c +++ b/convertquota.c @@ -98,7 +98,7 @@ void convert_file(int type) while ((mnt = getmntent(mntf))) { if (!(dev = get_device_name(mnt->mnt_fsname))) continue; - if (!strcmp(dev, mntpoint) || !strcmp(mnt->mnt_dir, mntpoint)) + if (devcmp(dev, mntpoint) || dircmp(mnt->mnt_dir, mntpoint)) break; } if (!mnt) diff --git a/edquota.8 b/edquota.8 index 69f56d1..6b1085c 100644 --- a/edquota.8 +++ b/edquota.8 @@ -39,7 +39,7 @@ Users are permitted to exceed their soft limits for a grace period that may be specified per filesystem. Once the grace period has expired, the soft limit is enforced as a hard limit. .PP -The current usage information in the file is for imformational purposes; +The current usage information in the file is for informational purposes; only the hard and soft limits can be changed. .PP Upon leaving the editor, diff --git a/edquota.c b/edquota.c index 7817750..1910e7f 100644 --- a/edquota.c +++ b/edquota.c @@ -34,7 +34,7 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: edquota.c,v 1.1 2001/03/23 12:03:26 jkar8572 Exp $" +#ident "$Id: edquota.c,v 1.2 2001/04/11 10:12:36 jkar8572 Exp $" /* * Disk quota editor. @@ -153,7 +153,7 @@ int main(int argc, char **argv) for (pprivs = protoprivs, cprivs = curprivs; pprivs && cprivs; pprivs = pprivs->dq_next, cprivs = cprivs->dq_next) { - if (strcmp(pprivs->dq_h->qh_quotadev, cprivs->dq_h->qh_quotadev)) + if (!devcmp_handles(pprivs->dq_h, cprivs->dq_h)) fprintf(stderr, _("fsname mismatch\n")); else { cprivs->dq_dqb.dqb_bsoftlimit = diff --git a/quot.8 b/quot.8 index f72973d..5b96267 100644 --- a/quot.8 +++ b/quot.8 @@ -3,18 +3,18 @@ quot \- summarize filesystem ownership .SH SYNOPSIS .nf -\f3quot\f1 [ \f3\-acfv\f1 ] [ filesystem... ] +\f3quot\f1 [ \f3\-acfguv\f1 ] [ filesystem... ] .fi .SH DESCRIPTION .IR quot displays the number of kilobytes in the named .I filesystem -currently owned by each user. +currently owned by each user or group. .SH OPTIONS .TP .B \-a Generate a report for all mounted filesystems giving the number of -kilobytes used by each user. +kilobytes used by each user or group. .TP .B \-c Display three columns giving file size in kilobytes, number of @@ -24,7 +24,13 @@ The last row is used as an overflow bucket and is the total of all files greater than 500 kilobytes. .TP .B \-f -Display count of kilobytes and number of files owned by each user. +Display count of kilobytes and number of files owned by each user or group. +.TP +.B \-g +Report on groups. +.TP +.B \-u +Report on users (the default). .TP .B \-v Display three columns containing the number of kilobytes not accessed in @@ -33,10 +39,13 @@ the last 30, 60, and 90 days. .PD 0 .TP 20 /etc/mtab -mounted filesystems +mounted filesystem table .TP /etc/passwd -to get user names +default set of users +.TP +/etc/group +default set of groups .PD .SH "SEE ALSO" du(1), diff --git a/quot.c b/quot.c index 162511d..fff2812 100644 --- a/quot.c +++ b/quot.c @@ -48,6 +48,7 @@ #include #include #include +#include #include "pot.h" #include "quot.h" @@ -59,20 +60,23 @@ __uint64_t sizes[TSIZE]; __uint64_t overflow; -static int fflag; +static int aflag; static int cflag; +static int fflag; +static int gflag; +static int uflag; static int vflag; -static int aflag; static char *progname; static time_t now; static void mounttable(char *); -static char *username(uid_t); -static void report(void); +static char *idname(__uint32_t, int); +static void report(const char *, char *, int); +static void creport(const char *, char *); static void usage(void) { - fprintf(stderr, _("Usage: %s [-acfvV] [filesystem...]\n"), progname); + fprintf(stderr, _("Usage: %s [-acfugvV] [filesystem...]\n"), progname); exit(1); } @@ -83,7 +87,7 @@ int main(int argc, char **argv) now = time(0); progname = basename(argv[0]); - while ((c = getopt(argc, argv, "acfvV")) != EOF) { + while ((c = getopt(argc, argv, "acfguvV")) != EOF) { switch (c) { case 'a': aflag++; @@ -94,6 +98,12 @@ int main(int argc, char **argv) case 'f': fflag++; break; + case 'g': + gflag++; + break; + case 'u': + uflag++; + break; case 'v': vflag++; break; @@ -106,6 +116,8 @@ int main(int argc, char **argv) } if ((aflag && optind != argc) || (!aflag && optind == argc)) usage(); + if (!uflag && !gflag) + uflag++; if (aflag) mounttable(NULL); else { @@ -129,8 +141,7 @@ static void mounttable(char *entry) while ((mntp = getmntent(mtab)) != NULL) { doit = 0; dev = get_device_name(mntp->mnt_fsname); - if ((entry != NULL) && - (strcmp(entry, mntp->mnt_dir) != 0) && (strcmp(entry, dev) != 0)) { + if (entry && !dircmp(mntp->mnt_dir, entry) && !devcmp(dev, entry)) { free((char *)dev); continue; } @@ -141,10 +152,13 @@ static void mounttable(char *entry) doit = 1; } /* ...additional filesystems types here. */ - free((char *)dev); - if (doit) - report(); + if (doit) { + if (cflag) creport(dev, mntp->mnt_dir); + if (!cflag && uflag) report(dev, mntp->mnt_dir, 0); + if (!cflag && gflag) report(dev, mntp->mnt_dir, 1); + } + free((char *)dev); if (entry != NULL) { entry = NULL; /* found, bail out */ break; @@ -161,31 +175,34 @@ static int qcmp(du_t * p1, du_t * p2) return -1; if (p1->blocks < p2->blocks) return 1; - if (p1->uid > p2->uid) + if (p1->id > p2->id) return 1; - else if (p1->uid < p2->uid) + else if (p1->id < p2->id) return -1; return 0; } -static void report(void) +static void creport(const char *file, char *fsdir) { int i; + __uint64_t t = 0; + + printf(_("%s (%s):\n"), file, fsdir); + for (i = 0; i < TSIZE - 1; i++) + if (sizes[i] > 0) { + t += sizes[i] * i; + printf(_("%d\t%llu\t%llu\n"), i, sizes[i], t); + } + printf(_("%d\t%llu\t%llu\n"), TSIZE - 1, sizes[TSIZE - 1], overflow + t); +} + +static void report(const char *file, char *fsdir, int type) +{ du_t *dp; - if (cflag) { - __uint64_t t = 0; - - for (i = 0; i < TSIZE - 1; i++) - if (sizes[i] > 0) { - t += sizes[i] * i; - printf(_("%d\t%llu\t%llu\n"), i, sizes[i], t); - } - printf(_("%d\t%llu\t%llu\n"), TSIZE - 1, sizes[TSIZE - 1], overflow + t); - return; - } - qsort(du, ndu, sizeof(du[0]), (int (*)(const void *, const void *))qcmp); - for (dp = du; dp < &du[ndu]; dp++) { + printf(_("%s (%s) %s:\n"), file, fsdir, type? "groups" : "users"); + qsort(du[type], ndu[type], sizeof(du[type][0]), (int (*)(const void *, const void *))qcmp); + for (dp = du[type]; dp < &du[type][ndu[type]]; dp++) { char *cp; if (dp->blocks == 0) @@ -193,10 +210,10 @@ static void report(void) printf(_("%8llu "), dp->blocks); if (fflag) printf(_("%8llu "), dp->nfiles); - if ((cp = username(dp->uid)) != NULL) + if ((cp = idname(dp->id, type)) != NULL) printf(_("%-8.8s"), cp); else - printf(_("#%-7d"), dp->uid); + printf(_("#%-7d"), dp->id); if (vflag) printf(_(" %8llu %8llu %8llu"), dp->blocks30, dp->blocks60, dp->blocks90); @@ -204,45 +221,62 @@ static void report(void) } } -static char *username(uid_t uid) +static idcache_t *getnextent(int type, __uint32_t id, int byid) { - register struct passwd *pw; - register uidcache_t *ncp; - static uidcache_t nc[NUID]; - static int entriesleft = NUID; + struct passwd *pw; + struct group *gr; + static idcache_t idc; + + if (type) { /* /etc/group */ + if ((gr = byid? getgrgid(id) : getgrent()) == NULL) + return NULL; + idc.id = gr->gr_gid; + strncpy(idc.name, gr->gr_name, UT_NAMESIZE); + return &idc; + } + /* /etc/passwd */ + if ((pw = byid? getpwuid(id) : getpwent()) == NULL) + return NULL; + idc.id = pw->pw_uid; + strncpy(idc.name, pw->pw_name, UT_NAMESIZE); + return &idc; +} + +static char *idname(__uint32_t id, int type) +{ + idcache_t *ncp, *idp; + static idcache_t nc[2][NID]; + static int entriesleft[2] = { NID, NID }; /* check cache for name first */ - ncp = &nc[uid & UIDMASK]; - if (ncp->uid == uid && ncp->name[0]) + ncp = &nc[type][id & IDMASK]; + if (ncp->id == id && ncp->name[0]) return ncp->name; - if (entriesleft) { + if (entriesleft[type]) { /* - * If we haven't gone through the passwd file then - * fill the cache while seaching for name. - * This lets us run through passwd serially. + * If we haven't gone through the passwd/group file + * then fill the cache while seaching for name. + * This lets us run through passwd/group serially. */ - if (entriesleft == NUID) - setpwent(); - while (((pw = getpwent()) != NULL) && entriesleft) { - entriesleft--; - ncp = &nc[pw->pw_uid & UIDMASK]; - if (ncp->name[0] == '\0' || pw->pw_uid == uid) { - strncpy(ncp->name, pw->pw_name, UT_NAMESIZE); - ncp->uid = uid; - } - if (pw->pw_uid == uid) + if (entriesleft[type] == NID) + type? setgrent() : setpwent(); + while (((idp = getnextent(type, id, 0)) != NULL) && entriesleft[type]) { + entriesleft[type]--; + ncp = &nc[type][idp->id & IDMASK]; + if (ncp->name[0] == '\0' || idp->id == id) + memcpy(ncp, idp, sizeof(idcache_t)); + if (idp->id == id) return ncp->name; } - endpwent(); - entriesleft = 0; - ncp = &nc[uid & UIDMASK]; + type? endgrent() : endpwent(); + entriesleft[type] = 0; + ncp = &nc[type][id & IDMASK]; } /* Not cached - do it the slow way & insert into cache */ - if ((pw = getpwuid(uid)) == NULL) + if ((idp = getnextent(type, id, 1)) == NULL) return NULL; - strncpy(ncp->name, pw->pw_name, UT_NAMESIZE); - ncp->uid = uid; + memcpy(ncp, idp, sizeof(idcache_t)); return ncp->name; } @@ -250,11 +284,12 @@ static char *username(uid_t uid) * === XFS specific code follows === */ -static void acctXFS(xfs_bstat_t * p) +static void acctXFS(xfs_bstat_t *p) { register du_t *dp; du_t **hp; __uint64_t size; + __uint32_t i, id; if ((p->bs_mode & S_IFMT) == 0) return; @@ -270,32 +305,35 @@ static void acctXFS(xfs_bstat_t * p) sizes[(int)size]++; return; } - hp = &duhash[p->bs_uid % DUHASH]; - for (dp = *hp; dp; dp = dp->next) - if (dp->uid == p->bs_uid) - break; - if (dp == 0) { - if (ndu >= NDU) - return; - dp = &du[ndu++]; - dp->next = *hp; - *hp = dp; - dp->uid = p->bs_uid; - dp->nfiles = 0; - dp->blocks = 0; - dp->blocks30 = 0; - dp->blocks60 = 0; - dp->blocks90 = 0; + for (i = 0; i < 2; i++) { + id = (i == 0)? p->bs_uid : p->bs_gid; + hp = &duhash[i][id % DUHASH]; + for (dp = *hp; dp; dp = dp->next) + if (dp->id == id) + break; + if (dp == 0) { + if (ndu[i] >= NDU) + return; + dp = &du[i][(ndu[i]++)]; + dp->next = *hp; + *hp = dp; + dp->id = id; + dp->nfiles = 0; + dp->blocks = 0; + dp->blocks30 = 0; + dp->blocks60 = 0; + dp->blocks90 = 0; + } + dp->blocks += size; + + if (now - p->bs_atime.tv_sec > 30 * SEC24HR) + dp->blocks30 += size; + if (now - p->bs_atime.tv_sec > 60 * SEC24HR) + dp->blocks60 += size; + if (now - p->bs_atime.tv_sec > 90 * SEC24HR) + dp->blocks90 += size; + dp->nfiles++; } - dp->blocks += size; - - if (now - p->bs_atime.tv_sec > 30 * SEC24HR) - dp->blocks30 += size; - if (now - p->bs_atime.tv_sec > 60 * SEC24HR) - dp->blocks60 += size; - if (now - p->bs_atime.tv_sec > 90 * SEC24HR) - dp->blocks90 += size; - dp->nfiles++; } static void checkXFS(const char *file, char *fsdir) @@ -316,16 +354,16 @@ static void checkXFS(const char *file, char *fsdir) for (sts = 0; sts < TSIZE; sts++) sizes[sts] = 0; overflow = 0; - for (dp = duhash; dp < &duhash[DUHASH]; dp++) - *dp = 0; - ndu = 0; + for (i = 0; i < 2; i++) + for (dp = duhash[i]; dp < &duhash[i][DUHASH]; dp++) + *dp = 0; + ndu[0] = ndu[1] = 0; fsfd = open(fsdir, O_RDONLY); if (fsfd < 0) { fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, fsdir, strerror(errno)); exit(1); } - printf(_("%s (%s):\n"), file, fsdir); sync(); buf = (xfs_bstat_t *) smalloc(NBSTAT * sizeof(xfs_bstat_t)); diff --git a/quot.h b/quot.h index 2ba44fc..a77a3f1 100644 --- a/quot.h +++ b/quot.h @@ -35,9 +35,9 @@ #define SEC24HR (60*60*24) /* seconds per day */ typedef struct { - uid_t uid; + __uint32_t id; char name[UT_NAMESIZE + 1]; -} uidcache_t; +} idcache_t; typedef struct du { struct du *next; @@ -46,17 +46,17 @@ typedef struct du { __uint64_t blocks60; __uint64_t blocks90; __uint64_t nfiles; - uid_t uid; + __uint32_t id; } du_t; #define NDU 60000 #define DUHASH 8209 -static du_t du[NDU]; -static du_t *duhash[DUHASH]; -static int ndu; +static du_t du[2][NDU]; +static du_t *duhash[2][DUHASH]; +static int ndu[2]; -#define NUID 256 -#define UIDMASK (NUID-1) +#define NID 256 +#define IDMASK (NID-1) /* * === Start XFS specific types and definitions === diff --git a/quotacheck.c b/quotacheck.c index 0e7ba70..3377298 100644 --- a/quotacheck.c +++ b/quotacheck.c @@ -8,7 +8,7 @@ * New quota format implementation - Jan Kara - Sponsored by SuSE CR */ -#ident "$Id: quotacheck.c,v 1.3 2001/04/05 08:26:56 jkar8572 Exp $" +#ident "$Id: quotacheck.c,v 1.4 2001/04/11 10:12:36 jkar8572 Exp $" #include #include @@ -814,7 +814,7 @@ static void check_all(void) die(3, _("Too many mountpoints. Please report to: %s\n"), MY_EMAIL); if (!(devlist[gotmnt] = (char *)get_device_name(mnt->mnt_fsname))) continue; - for (i = 0; i < gotmnt && strcmp(devlist[i], devlist[gotmnt]); i++); + for (i = 0; i < gotmnt && !devcmp(devlist[i], devlist[gotmnt]); i++); /* We already have this mountpoint? */ if (i < gotmnt) continue; @@ -824,7 +824,7 @@ static void check_all(void) else mnt_fslabel = devlist[gotmnt - 1]; if ((flags & FL_ALL && (!(flags & FL_NOROOT) || strcmp(mnt->mnt_dir, "/"))) || - !strcmp(mntpoint, devlist[gotmnt - 1]) || !strcmp(mntpoint, mnt->mnt_dir)) { + devcmp(mntpoint, devlist[gotmnt - 1]) || dircmp(mntpoint, mnt->mnt_dir)) { if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) { debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt_fslabel, mnt->mnt_dir); diff --git a/quotaio.c b/quotaio.c index f1b36c7..5d227af 100644 --- a/quotaio.c +++ b/quotaio.c @@ -65,6 +65,8 @@ struct quota_handle *init_io(struct mntent *mnt, int type, int fmt) goto out_handle; if (!(mnt_fsname = get_device_name(mnt->mnt_fsname))) goto out_handle; + if (stat(mnt_fsname, &h->qh_stat) < 0) + memset(&h->qh_stat, 0, sizeof(struct stat)); h->qh_io_flags = 0; h->qh_type = type; sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev)); diff --git a/quotaio.h b/quotaio.h index e9f88d5..edfbda3 100644 --- a/quotaio.h +++ b/quotaio.h @@ -9,6 +9,7 @@ #include #include +#include #include "quota.h" #include "mntopt.h" @@ -81,6 +82,7 @@ struct quota_handle { char qh_quotadev[PATH_MAX]; /* Device file is for */ int qh_type; /* Type of quotafile */ int qh_fmt; /* Quotafile format */ + struct stat qh_stat; /* stat(2) for qh_quotadev */ struct quotafile_ops *qh_ops; /* Operations on quotafile */ struct util_dqinfo qh_info; /* Generic quotafile info */ }; diff --git a/quotaio_xfs.c b/quotaio_xfs.c index 11a6320..653ce53 100644 --- a/quotaio_xfs.c +++ b/quotaio_xfs.c @@ -132,10 +132,8 @@ static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id) } else { xfs_kern2utildqblk(&dquot->dq_dqb, &xdqblk); - return dquot; } - free(dquot); - return NULL; + return dquot; } /* @@ -242,11 +240,11 @@ static int xfs_report(struct quota_handle *h, int verbose) #define XQM_ON(flag) ((info->qs_flags & (flag)) ? _("ON") : _("OFF")) if (h->qh_type == USRQUOTA) { - printf(_("Accounting: %s Enforcement: %s\n"), + printf(_("Accounting: %s; Enforcement: %s\n"), XQM_ON(XFS_QUOTA_UDQ_ACCT), XQM_ON(XFS_QUOTA_UDQ_ENFD)); } else { /* qh_type == USRQUOTA */ - printf(_("Accounting: %s Enforcement: %s\n"), + printf(_("Accounting: %s; Enforcement: %s\n"), XQM_ON(XFS_QUOTA_GDQ_ACCT), XQM_ON(XFS_QUOTA_GDQ_ENFD)); } #undef XQM_ON @@ -258,13 +256,11 @@ static int xfs_report(struct quota_handle *h, int verbose) #define XQM_ONDISK(flag) ((sbflags & (flag)) ? _("ON") : _("OFF")) if ((sbflags = (info->qs_flags & 0xff00) >> 8) != 0) { if (h->qh_type == USRQUOTA) { - printf(_("Accounting [ondisk]: %s " - "Enforcement [ondisk]: %s\n"), + printf(_("Accounting [ondisk]: %s; Enforcement [ondisk]: %s\n"), XQM_ONDISK(XFS_QUOTA_UDQ_ACCT), XQM_ONDISK(XFS_QUOTA_UDQ_ENFD)); } else { /* qh_type == USRQUOTA */ - printf(_("Accounting [ondisk]: %s " - "Enforcement [ondisk]: %s\n"), + printf(_("Accounting [ondisk]: %s; Enforcement [ondisk]: %s\n"), XQM_ONDISK(XFS_QUOTA_GDQ_ACCT), XQM_ONDISK(XFS_QUOTA_GDQ_ENFD)); } #undef XQM_ONDISK diff --git a/quotaon.c b/quotaon.c index 6e8d17b..12cce13 100644 --- a/quotaon.c +++ b/quotaon.c @@ -34,7 +34,7 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: quotaon.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $" +#ident "$Id: quotaon.c,v 1.2 2001/04/11 10:12:36 jkar8572 Exp $" /* * Turn quota on/off for a filesystem. @@ -62,12 +62,12 @@ static void usage(char *whoami) /* * Check to see if target appears in list of size cnt. */ -static int oneof(char *target, char *list[], int cnt) +static int oneof(char *dir, char *dev, char *list[], int cnt) { int i; for (i = 0; i < cnt; i++) - if (strcmp(target, list[i]) == 0) + if (devcmp(dev, list[i]) || dircmp(dir, list[i])) return (i); return (-1); } @@ -169,8 +169,7 @@ int main(int argc, char **argv) continue; } else { - if ((argnum = oneof(mnt->mnt_dir, argv, argc)) >= 0 || - (argnum = oneof(mnt->mnt_fsname, argv, argc)) >= 0) + if ((argnum = oneof(mnt->mnt_dir, mnt->mnt_fsname, argv, argc)) >= 0) done |= 1 << argnum; else continue; diff --git a/quotaops.c b/quotaops.c index 82bfb43..fed0168 100644 --- a/quotaops.c +++ b/quotaops.c @@ -34,7 +34,7 @@ #ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $" #ident "$Copyright: All rights reserved. $" -#ident "$Id: quotaops.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $" +#ident "$Id: quotaops.c,v 1.2 2001/04/11 10:12:36 jkar8572 Exp $" #include #include @@ -208,7 +208,7 @@ static void merge_to_list(struct dquot *qlist, char *dev, u_int64_t blocks, u_in struct dquot *q; for (q = qlist; q; q = q->dq_next) { - if (strcmp(dev, q->dq_h->qh_quotadev)) + if (devcmp_handle(dev, q->dq_h)) continue; /* @@ -449,7 +449,7 @@ int readtimes(struct quota_handle **handles, int infd) if (cvtatos(itime, iunits, &iseconds) < 0) return -1; for (i = 0; handles[i]; i++) { - if (strcmp(fsp, handles[i]->qh_quotadev)) + if (!devcmp_handle(fsp, handles[i])) continue; handles[i]->qh_info.dqi_bgrace = bseconds; handles[i]->qh_info.dqi_igrace = iseconds; diff --git a/quotasys.c b/quotasys.c index ab05d50..b2dd507 100644 --- a/quotasys.c +++ b/quotasys.c @@ -351,13 +351,13 @@ struct quota_handle **create_handle_list(int count, char **mntpoints, int type, while ((mnt = getmntent(mntf))) { if (!(dev = get_device_name(mnt->mnt_fsname))) continue; - for (i = 0; i < gotmnt && strcmp(dev, hlist[i]->qh_quotadev); i++); - /* We already have this device? (can happen when filesystem is mounted multiple times */ + /* Do we already have this device? (filesystem may be mounted multiple times) */ + for (i = 0; i < gotmnt && !devcmp_handle(dev, hlist[i]); i++); if (i < gotmnt) continue; for (i = 0; i < count; i++) - /* Is this what we want? */ - if (!strcmp(dev, mntpoints[i]) || !strcmp(mnt->mnt_dir, mntpoints[i])) + /* Is this the filesystem we want? */ + if (devcmp(dev, mntpoints[i]) || dircmp(mnt->mnt_dir, mntpoints[i])) break; free((char *)dev); if (!count || i < count) { @@ -402,6 +402,34 @@ int dispose_handle_list(struct quota_handle **hlist) return 0; } +/* + * Check whether given device name matches this quota handle + */ +int devcmp_handle(const char *dev, struct quota_handle *h) +{ + struct stat sbuf; + + if (stat(dev, &sbuf) < 0) + return (strcmp(dev, h->qh_quotadev) == 0); + if (!S_ISBLK(sbuf.st_mode)) + return (strcmp(dev, h->qh_quotadev) == 0); + if (sbuf.st_rdev != h->qh_stat.st_rdev) + return 0; + return 1; +} + +/* + * Check whether two quota handles are for the same device + */ +int devcmp_handles(struct quota_handle *a, struct quota_handle *b) +{ + if (!S_ISBLK(a->qh_stat.st_mode) || !S_ISBLK(b->qh_stat.st_mode)) + return (strcmp(a->qh_quotadev, b->qh_quotadev) == 0); + if (a->qh_stat.st_rdev != b->qh_stat.st_rdev) + return 0; + return 1; +} + /* * Check kernel quota version */ diff --git a/quotasys.h b/quotasys.h index f5db080..daeaeee 100644 --- a/quotasys.h +++ b/quotasys.h @@ -66,6 +66,12 @@ struct quota_handle **create_handle_list(int count, char **mntpoints, int type, /* Dispose given list of handles */ int dispose_handle_list(struct quota_handle **hlist); +/* Check whether given device name matches quota handle device */ +int devcmp_handle(const char *dev, struct quota_handle *h); + +/* Check whether two quota handles have same device */ +int devcmp_handles(struct quota_handle *a, struct quota_handle *b); + /* Warn about too new kernel */ void warn_new_kernel(int fmt); diff --git a/repquota.c b/repquota.c index 87cc6b7..4f78251 100644 --- a/repquota.c +++ b/repquota.c @@ -122,9 +122,9 @@ static void report_it(struct quota_handle *h, int type) printf(_("*** Report for %s quotas on device %s\n"), type2name(type), h->qh_quotadev); time2str(h->qh_info.dqi_bgrace, bgbuf, TF_ROUND); time2str(h->qh_info.dqi_igrace, igbuf, TF_ROUND); - printf("Block grace time: %s; Inode grace time: %s\n", bgbuf, igbuf); - printf(" Block limits File limits\n"); - printf("User used soft hard grace used soft hard grace\n"); + printf(_("Block grace time: %s; Inode grace time: %s\n"), bgbuf, igbuf); + printf(_(" Block limits File limits\n")); + printf(_("%-10s used soft hard grace used soft hard grace\n"), (type == USRQUOTA)?_("User"):_("Group")); printf("----------------------------------------------------------------------\n"); if (h->qh_ops->scan_dquots(h, print) < 0) diff --git a/setquota.8 b/setquota.8 index c4f9fcb..6f65dbd 100644 --- a/setquota.8 +++ b/setquota.8 @@ -4,23 +4,29 @@ setquota \- set disk quotas .SH SYNOPSIS .B /usr/sbin/setquota [ -.B \-nr +.B \-r ] [ .B \-u | .B \-g ] +[ +.B \-F +.I quotaformat +] .I name -.I filesystem .I block-softlimit .I block-hardlimit .I inode-softlimit .I inode-hardlimit +.B \-a +| +.I filesystem .LP .B /usr/sbin/setquota [ -.B \-nr +.B \-r ] [ .B \-u @@ -28,9 +34,33 @@ setquota \- set disk quotas .B \-g ] [ -.B \-p protoname +.B \-F +.I quotaformat +] +[ +.B \-p +.I protoname ] .I name +.B \-a +| +.I filesystem +.LP +.B /usr/sbin/setquota +.B \-t +[ +.B \-u +| +.B \-g +] +[ +.B \-F +.I quotaformat +] +.I block-grace +.I inode-grace +.B \-a +| .I filesystem .SH DESCRIPTION .IX "setquota command" "" "\fLsetquota\fP \(em set disk quotas" @@ -44,14 +74,13 @@ is a command line quota editor. The filesystem, user/group name and new quotas for this filesystem can be specified on the command line. .TP -.B -n -Consider -.I name -to be a numeric ID (don't lookup user/group names). -.TP .B -r Edit also remote quota use rpc.rquotad on remote server to set quota. .TP +.B -F \f2quotaformat\f1 +Perform setting for specified quota format. If this option isn't specified +newest option found is used. +.TP .B -u Set user quotas for named user. This is the default. .TP @@ -62,6 +91,18 @@ Set group quotas for named group. Use quota settings of user or group .I protoname to set the quota for the named user or group. +.TP +.B -t +Set grace times for users/groups. Times +.B block-grace +and +.B inode-grace +are specified in seconds. +.TP +.B -a +Go through all filesystems with quota in +.B /etc/mtab +and perform setting. .PP To disable a quota, set the coresponding parameter to 0. To change quotas for several filesystems, invoke once for each filesystem. -- cgit v1.2.3