More updates to edquota based on feedback from Dag-Erling Smorgrav.

This commit is contained in:
Kirk McKusick 2009-02-10 08:09:03 +00:00
parent b83b5d3b79
commit cdab8b664d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/quota64/; revision=188432

View File

@ -101,9 +101,11 @@ struct quotause {
int alldigits(const char *s); int alldigits(const char *s);
int cvtatos(u_int64_t, char *, u_int64_t *); int cvtatos(u_int64_t, char *, u_int64_t *);
char *cvtstoa(u_int64_t); char *cvtstoa(u_int64_t);
u_int64_t cvtval(u_int64_t, char); u_int64_t cvtblkval(u_int64_t, char, const char *);
u_int64_t cvtinoval(u_int64_t, char, const char *);
int editit(char *); int editit(char *);
char *fmthumanval(int64_t); char *fmthumanvalblks(int64_t);
char *fmthumanvalinos(int64_t);
void freeprivs(struct quotause *); void freeprivs(struct quotause *);
int getentry(const char *, int); int getentry(const char *, int);
struct quotause *getprivs(long, int, char *); struct quotause *getprivs(long, int, char *);
@ -165,6 +167,12 @@ main(int argc, char *argv[])
(cp = strsep(&optarg, ":")) != NULL; i++) { (cp = strsep(&optarg, ":")) != NULL; i++) {
if (cp != oldoptarg) if (cp != oldoptarg)
*(cp - 1) = ':'; *(cp - 1) = ':';
if (i > 0 && !isdigit(*cp)) {
warnx("incorrect quota specification: "
"%s", oldoptarg);
usage();
/* Not Reached */
}
switch (i) { switch (i) {
case 0: case 0:
strlcpy(qup->fsname, cp, strlcpy(qup->fsname, cp,
@ -173,34 +181,34 @@ main(int argc, char *argv[])
case 1: case 1:
lim = strtoll(cp, &endpt, 10); lim = strtoll(cp, &endpt, 10);
qup->dqblk.dqb_bsoftlimit = qup->dqblk.dqb_bsoftlimit =
cvtval(lim, *endpt); cvtblkval(lim, *endpt,
"block soft limit");
continue; continue;
case 2: case 2:
lim = strtoll(cp, &endpt, 10); lim = strtoll(cp, &endpt, 10);
qup->dqblk.dqb_bhardlimit = qup->dqblk.dqb_bhardlimit =
cvtval(lim, *endpt); cvtblkval(lim, *endpt,
"block hard limit");
continue; continue;
case 3: case 3:
lim = strtoll(cp, &endpt, 10); lim = strtoll(cp, &endpt, 10);
qup->dqblk.dqb_isoftlimit = qup->dqblk.dqb_isoftlimit =
cvtval(lim, *endpt); cvtinoval(lim, *endpt,
"inode soft limit");
continue; continue;
case 4: case 4:
lim = strtoll(cp, &endpt, 10); lim = strtoll(cp, &endpt, 10);
qup->dqblk.dqb_ihardlimit = qup->dqblk.dqb_ihardlimit =
cvtval(lim, *endpt); cvtinoval(lim, *endpt,
"inode hard limit");
continue; continue;
default: default:
warnx("incorrect quota specification: " warnx("incorrect quota specification: "
"%s", oldoptarg); "%s", oldoptarg);
usage(); usage();
break; /* XXX: report an error */ /* Not Reached */
} }
} }
qup->dqblk.dqb_bsoftlimit =
btodb((off_t)qup->dqblk.dqb_bsoftlimit * 1024);
qup->dqblk.dqb_bhardlimit =
btodb((off_t)qup->dqblk.dqb_bhardlimit * 1024);
if (protoprivs == NULL) { if (protoprivs == NULL) {
protoprivs = curprivs = qup; protoprivs = curprivs = qup;
} else { } else {
@ -212,6 +220,7 @@ main(int argc, char *argv[])
break; break;
default: default:
usage(); usage();
/* Not Reached */
} }
} }
argc -= optind; argc -= optind;
@ -518,28 +527,29 @@ writeprivs(struct quotause *quplist, int outfd, char *name, int quotatype)
fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name); fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name);
for (qup = quplist; qup; qup = qup->next) { for (qup = quplist; qup; qup = qup->next) {
fprintf(fd, "%s: in use: %s, ", qup->fsname, fprintf(fd, "%s: in use: %s, ", qup->fsname,
fmthumanval(qup->dqblk.dqb_curblocks)); fmthumanvalblks(qup->dqblk.dqb_curblocks));
fprintf(fd, "limits (soft = %s, ", fprintf(fd, "limits (soft = %s, ",
fmthumanval(qup->dqblk.dqb_bsoftlimit)); fmthumanvalblks(qup->dqblk.dqb_bsoftlimit));
fprintf(fd, "hard = %s)\n", fprintf(fd, "hard = %s)\n",
fmthumanval(qup->dqblk.dqb_bhardlimit)); fmthumanvalblks(qup->dqblk.dqb_bhardlimit));
fprintf(fd, "%s %llu, limits (soft = %llu, hard = %llu)\n", fprintf(fd, "\tinodes in use: %s, ",
"\tinodes in use:", fmthumanvalinos(qup->dqblk.dqb_curinodes));
qup->dqblk.dqb_curinodes, fprintf(fd, "limits (soft = %s, ",
qup->dqblk.dqb_isoftlimit, fmthumanvalinos(qup->dqblk.dqb_isoftlimit));
qup->dqblk.dqb_ihardlimit); fprintf(fd, "hard = %s)\n",
fmthumanvalinos(qup->dqblk.dqb_ihardlimit));
} }
fclose(fd); fclose(fd);
return (1); return (1);
} }
char * char *
fmthumanval(int64_t blocks) fmthumanvalblks(int64_t blocks)
{ {
static char numbuf[20]; static char numbuf[20];
if (hflag) { if (hflag) {
humanize_number(numbuf, sizeof(numbuf) - (blocks < 0 ? 0 : 1), humanize_number(numbuf, blocks < 0 ? 7 : 6,
dbtob(blocks), "", HN_AUTOSCALE, HN_NOSPACE); dbtob(blocks), "", HN_AUTOSCALE, HN_NOSPACE);
return (numbuf); return (numbuf);
} }
@ -547,6 +557,20 @@ fmthumanval(int64_t blocks)
return(numbuf); return(numbuf);
} }
char *
fmthumanvalinos(int64_t inos)
{
static char numbuf[20];
if (hflag) {
humanize_number(numbuf, inos < 0 ? 7 : 6,
inos, "", HN_AUTOSCALE, HN_NOSPACE | HN_DIVISOR_1000);
return (numbuf);
}
snprintf(numbuf, sizeof(numbuf), "%llu", inos);
return(numbuf);
}
/* /*
* Merge changes to an ASCII file into a quotause list. * Merge changes to an ASCII file into a quotause list.
*/ */
@ -607,42 +631,48 @@ readprivs(struct quotause *quplist, char *inname)
warnx("%s:%s: bad format", fsp, cp); warnx("%s:%s: bad format", fsp, cp);
return (0); return (0);
} }
dqblk.dqb_curblocks = cvtval(curitems, curitemunits); dqblk.dqb_curblocks = cvtblkval(curitems, curitemunits,
dqblk.dqb_bsoftlimit = cvtval(softlimit, softunits); "current block count");
dqblk.dqb_bhardlimit = cvtval(hardlimit, hardunits); dqblk.dqb_bsoftlimit = cvtblkval(softlimit, softunits,
"block soft limit");
dqblk.dqb_bhardlimit = cvtblkval(hardlimit, hardunits,
"block hard limit");
if ((cp = strtok(line2, "\n")) == NULL) { if ((cp = strtok(line2, "\n")) == NULL) {
warnx("%s: %s: bad format", fsp, line2); warnx("%s: %s: bad format", fsp, line2);
return (0); return (0);
} }
cnt = sscanf(cp, cnt = sscanf(&cp[7],
" in use: %llu%c, limits (soft = %llu%c, hard = %llu%c)", " in use: %llu%c limits (soft = %llu%c, hard = %llu%c)",
&curitems, &curitemunits, &softlimit, &curitems, &curitemunits, &softlimit,
&softunits, &hardlimit, &hardunits); &softunits, &hardlimit, &hardunits);
/* /*
* The next three check for old-style input formats. * The next three check for old-style input formats.
*/ */
if (cnt != 6) if (cnt != 6)
cnt = sscanf(cp, cnt = sscanf(&cp[7],
" in use: %llu%c, limits (soft = %llu%c hard = %llu%c", " in use: %llu%c limits (soft = %llu%c hard = %llu%c",
&curitems, &curitemunits, &softlimit, &curitems, &curitemunits, &softlimit,
&softunits, &hardlimit, &hardunits); &softunits, &hardlimit, &hardunits);
if (cnt != 6) if (cnt != 6)
cnt = sscanf(cp, cnt = sscanf(&cp[7],
" in use: %llu%c, limits (soft = %llu%c hard = %llu%c)", " in use: %llu%c limits (soft = %llu%c hard = %llu%c)",
&curitems, &curitemunits, &softlimit, &curitems, &curitemunits, &softlimit,
&softunits, &hardlimit, &hardunits); &softunits, &hardlimit, &hardunits);
if (cnt != 6) if (cnt != 6)
cnt = sscanf(cp, cnt = sscanf(&cp[7],
" in use: %llu%c, limits (soft = %llu%c, hard = %llu%c", " in use: %llu%c limits (soft = %llu%c, hard = %llu%c",
&curitems, &curitemunits, &softlimit, &curitems, &curitemunits, &softlimit,
&softunits, &hardlimit, &hardunits); &softunits, &hardlimit, &hardunits);
if (cnt != 3) { if (cnt != 6) {
warnx("%s: %s: bad format", fsp, line2); warnx("%s: %s: bad format cnt %d", fsp, &cp[7], cnt);
return (0); return (0);
} }
dqblk.dqb_curinodes = cvtval(curitems, curitemunits); dqblk.dqb_curinodes = cvtinoval(curitems, curitemunits,
dqblk.dqb_isoftlimit = cvtval(softlimit, softunits); "current inode count");
dqblk.dqb_ihardlimit = cvtval(hardlimit, hardunits); dqblk.dqb_isoftlimit = cvtinoval(softlimit, softunits,
"inode soft limit");
dqblk.dqb_ihardlimit = cvtinoval(hardlimit, hardunits,
"inode hard limit");
for (qup = quplist; qup; qup = qup->next) { for (qup = quplist; qup; qup = qup->next) {
if (strcmp(fsp, qup->fsname)) if (strcmp(fsp, qup->fsname))
continue; continue;
@ -669,8 +699,10 @@ readprivs(struct quotause *quplist, char *inname)
qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit; qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit;
qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit; qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit;
qup->flags |= FOUND; qup->flags |= FOUND;
if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks && /* Humanized input returns only approximate counts */
dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes) if (hflag ||
(dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks &&
dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes))
break; break;
warnx("%s: cannot change current allocation", fsp); warnx("%s: cannot change current allocation", fsp);
break; break;
@ -836,7 +868,7 @@ cvtatos(u_int64_t period, char *units, u_int64_t *seconds)
* Convert a limit to number of disk blocks. * Convert a limit to number of disk blocks.
*/ */
u_int64_t u_int64_t
cvtval(u_int64_t limit, char units) cvtblkval(u_int64_t limit, char units, const char *itemname)
{ {
switch(units) { switch(units) {
@ -872,11 +904,62 @@ cvtval(u_int64_t limit, char units)
limit *= btodb(1152921504606846976); limit *= btodb(1152921504606846976);
break; break;
case ' ': case ' ':
errx(2, "No space permitted between value and units\n"); errx(2, "No space permitted between value and units for %s\n",
itemname);
break; break;
default: default:
errx(2, "%llu%c: unknown units, specify K, M, G, T, P, or E\n", errx(2, "%llu%c: unknown units for %s, specify none, K, M, G, T, P, or E\n",
limit, units); limit, units, itemname);
break;
}
return (limit);
}
/*
* Convert a limit to number of inodes.
*/
u_int64_t
cvtinoval(u_int64_t limit, char units, const char *itemname)
{
switch(units) {
case 'B':
case 'b':
case '\0': /* historic behavior */
case ',': /* historic behavior */
case ')': /* historic behavior */
break;
case 'K':
case 'k':
limit *= 1000;
break;
case 'M':
case 'm':
limit *= 1000000;
break;
case 'G':
case 'g':
limit *= 1000000000;
break;
case 'T':
case 't':
limit *= 1000000000000;
break;
case 'P':
case 'p':
limit *= 1000000000000000;
break;
case 'E':
case 'e':
limit *= 1000000000000000000;
break;
case ' ':
errx(2, "No space permitted between value and units for %s\n",
itemname);
break;
default:
errx(2, "%llu%c: unknown units for %s, specify none, K, M, G, T, P, or E\n",
limit, units, itemname);
break; break;
} }
return (limit); return (limit);