Update to work with quotafile functions in -libutil.

Add -h flag to provide humanized output.
This commit is contained in:
Kirk McKusick 2009-10-20 05:40:51 +00:00
parent 6197731d81
commit 0cf50fd7dc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/quota64/; revision=198266
2 changed files with 84 additions and 119 deletions

View file

@ -39,12 +39,14 @@
.Nd summarize quotas for a file system
.Sh SYNOPSIS
.Nm
.Op Fl h
.Op Fl g
.Op Fl n
.Op Fl u
.Op Fl v
.Ar filesystem Ar ...
.Nm
.Op Fl h
.Op Fl g
.Op Fl n
.Op Fl u
@ -64,6 +66,9 @@ Print the quotas of all the file systems listed in
.It Fl g
Print only group quotas (the default is to print both
group and user quotas if they exist).
.It Fl h
Display information in a more human readable format
rather than in historic kilobyte format.
.It Fl n
Display user and group IDs numerically rather than converting to
a user or group name.
@ -75,7 +80,7 @@ Print a header line before printing each file system quotas.
.El
.Pp
For each user or group, the current
number files and amount of space (in kilobytes) is
number files and amount of space is
printed, along with any quotas created with
.Xr edquota 8 .
.Pp

View file

@ -52,8 +52,10 @@ __FBSDID("$FreeBSD$");
#include <ufs/ufs/quota.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <fstab.h>
#include <grp.h>
#include <libutil.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
@ -80,7 +82,6 @@ const char *qfextension[] = INITQFNAMES;
struct fileusage {
struct fileusage *fu_next;
struct dqblk fu_dqblk;
u_long fu_id;
char fu_name[1];
/* actually bigger */
@ -94,11 +95,12 @@ u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
int vflag; /* verbose */
int aflag; /* all filesystems */
int nflag; /* display user/group by id */
int hflag; /* display in human readable format */
int hasquota(struct fstab *, int, char **);
int oneof(char *, char *[], int);
int repquota(struct fstab *, int, char *);
int repquota(struct fstab *, int);
char *timeprt(time_t);
static void prthumanval(int64_t bytes);
static void usage(void);
int
@ -109,9 +111,8 @@ main(int argc, char *argv[])
struct group *gr;
int ch, gflag = 0, uflag = 0, errs = 0;
long i, argnum, done = 0;
char *qfnp;
while ((ch = getopt(argc, argv, "agnuv")) != -1) {
while ((ch = getopt(argc, argv, "aghnuv")) != -1) {
switch(ch) {
case 'a':
aflag++;
@ -119,6 +120,9 @@ main(int argc, char *argv[])
case 'g':
gflag++;
break;
case 'h':
hflag++;
break;
case 'n':
nflag++;
break;
@ -158,19 +162,19 @@ main(int argc, char *argv[])
if (strcmp(fs->fs_vfstype, "ufs"))
continue;
if (aflag) {
if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
errs += repquota(fs, GRPQUOTA, qfnp);
if (uflag && hasquota(fs, USRQUOTA, &qfnp))
errs += repquota(fs, USRQUOTA, qfnp);
if (gflag)
errs += repquota(fs, GRPQUOTA);
if (uflag)
errs += repquota(fs, USRQUOTA);
continue;
}
if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
(argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
done |= 1 << argnum;
if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
errs += repquota(fs, GRPQUOTA, qfnp);
if (uflag && hasquota(fs, USRQUOTA, &qfnp))
errs += repquota(fs, USRQUOTA, qfnp);
if (gflag)
errs += repquota(fs, GRPQUOTA);
if (uflag)
errs += repquota(fs, USRQUOTA);
}
}
endfsent();
@ -184,87 +188,92 @@ static void
usage(void)
{
fprintf(stderr, "%s\n%s\n",
"usage: repquota [-v] [-g] [-n] [-u] -a",
" repquota [-v] [-g] [-n] [-u] filesystem ...");
"usage: repquota [-h] [-v] [-g] [-n] [-u] -a",
" repquota [-h] [-v] [-g] [-n] [-u] filesystem ...");
exit(1);
}
int
repquota(struct fstab *fs, int type, char *qfpathname)
repquota(struct fstab *fs, int type)
{
struct fileusage *fup;
FILE *qf;
u_long id;
struct quotafile *qf;
u_long id, maxid;
struct dqblk dqbuf;
static struct dqblk zerodqblk;
static int warned = 0;
static int multiple = 0;
if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 &&
errno == EOPNOTSUPP && !warned && vflag) {
warned++;
fprintf(stdout,
"*** Warning: Quotas are not compiled into this kernel\n");
if ((qf = quota_open(fs, type, O_RDONLY)) == NULL) {
if (vflag && !aflag) {
if (multiple++)
printf("\n");
fprintf(stdout, "*** No %s quotas on %s (%s)\n",
qfextension[type], fs->fs_file, fs->fs_spec);
}
return(0);
}
if (multiple++)
printf("\n");
if (vflag)
fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
qfextension[type], fs->fs_file, fs->fs_spec);
if ((qf = fopen(qfpathname, "r")) == NULL) {
warn("%s", qfpathname);
return (1);
}
for (id = 0; ; id++) {
fread(&dqbuf, sizeof(struct dqblk), 1, qf);
if (feof(qf))
printf("%*s Block limits File limits\n",
max(UT_NAMESIZE,10), " ");
printf("User%*s used soft hard grace used soft hard grace\n",
max(UT_NAMESIZE,10), " ");
maxid = quota_maxid(qf);
for (id = 0; id <= maxid; id++) {
if (quota_read(qf, &dqbuf, id) != 0)
break;
if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)
continue;
if ((fup = lookup(id, type)) == 0)
fup = addid(id, type, (char *)0);
fup->fu_dqblk = dqbuf;
}
fclose(qf);
printf("%*s Block limits File limits\n",
max(UT_NAMESIZE,10), " ");
printf("%s%*s used soft hard grace used soft hard grace\n",
type == USRQUOTA ? "User " : "Group", max(UT_NAMESIZE,10), " ");
for (id = 0; id <= highid[type]; id++) {
fup = lookup(id, type);
if (fup == 0)
continue;
if (fup->fu_dqblk.dqb_curinodes == 0 &&
fup->fu_dqblk.dqb_curblocks == 0)
continue;
printf("%-*s ", max(UT_NAMESIZE,10), fup->fu_name);
printf("%c%c %8lu %8lu %8lu %6s",
fup->fu_dqblk.dqb_bsoftlimit &&
fup->fu_dqblk.dqb_curblocks >=
fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-',
fup->fu_dqblk.dqb_isoftlimit &&
fup->fu_dqblk.dqb_curinodes >=
fup->fu_dqblk.dqb_isoftlimit ? '+' : '-',
(u_long)(dbtokb(fup->fu_dqblk.dqb_curblocks)),
(u_long)(dbtokb(fup->fu_dqblk.dqb_bsoftlimit)),
(u_long)(dbtokb(fup->fu_dqblk.dqb_bhardlimit)),
fup->fu_dqblk.dqb_bsoftlimit &&
fup->fu_dqblk.dqb_curblocks >=
fup->fu_dqblk.dqb_bsoftlimit ?
timeprt(fup->fu_dqblk.dqb_btime) : "-");
printf(" %7lu %7lu %7lu %6s\n",
(u_long)fup->fu_dqblk.dqb_curinodes,
(u_long)fup->fu_dqblk.dqb_isoftlimit,
(u_long)fup->fu_dqblk.dqb_ihardlimit,
fup->fu_dqblk.dqb_isoftlimit &&
fup->fu_dqblk.dqb_curinodes >=
fup->fu_dqblk.dqb_isoftlimit ?
timeprt(fup->fu_dqblk.dqb_itime) : "-");
fup->fu_dqblk = zerodqblk;
printf("%c%c",
dqbuf.dqb_bsoftlimit &&
dqbuf.dqb_curblocks >=
dqbuf.dqb_bsoftlimit ? '+' : '-',
dqbuf.dqb_isoftlimit &&
dqbuf.dqb_curinodes >=
dqbuf.dqb_isoftlimit ? '+' : '-');
prthumanval(dqbuf.dqb_curblocks);
prthumanval(dqbuf.dqb_bsoftlimit);
prthumanval(dqbuf.dqb_bhardlimit);
printf(" %6s",
dqbuf.dqb_bsoftlimit &&
dqbuf.dqb_curblocks >=
dqbuf.dqb_bsoftlimit ?
timeprt(dqbuf.dqb_btime) : "-");
printf(" %7llu %7llu %7llu %6s\n",
dqbuf.dqb_curinodes,
dqbuf.dqb_isoftlimit,
dqbuf.dqb_ihardlimit,
dqbuf.dqb_isoftlimit &&
dqbuf.dqb_curinodes >=
dqbuf.dqb_isoftlimit ?
timeprt(dqbuf.dqb_itime) : "-");
}
return (0);
}
static void
prthumanval(int64_t blocks)
{
char buf[7];
int flags;
if (!hflag) {
printf("%7llu", dbtokb(blocks));
return;
}
flags = HN_NOSPACE | HN_DECIMAL;
if (blocks != 0)
flags |= HN_B;
humanize_number(buf, sizeof(buf) - (blocks < 0 ? 0 : 1),
dbtob(blocks), "", HN_AUTOSCALE, flags);
(void)printf("%7s", buf);
}
/*
* Check to see if target appears in list of size cnt.
*/
@ -279,55 +288,6 @@ oneof(char *target, char *list[], int cnt)
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, '=')))
*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.
*