summaryrefslogtreecommitdiff
path: root/quot.c
diff options
context:
space:
mode:
Diffstat (limited to 'quot.c')
-rw-r--r--quot.c210
1 files changed, 124 insertions, 86 deletions
diff --git a/quot.c b/quot.c
index 162511d..fff2812 100644
--- a/quot.c
+++ b/quot.c
@@ -48,6 +48,7 @@
#include <time.h>
#include <utmp.h>
#include <pwd.h>
+#include <grp.h>
#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));