Module Name: src Committed By: bouyer Date: Sun Jan 30 22:49:32 UTC 2011
Modified Files: src/usr.bin/quota [bouyer-quota2]: printquota.c printquota.h src/usr.sbin/edquota [bouyer-quota2]: edquota.c Log Message: Allow edquota to edit per-user grace times on quota2 (or the default, global grace times on quota1). Use re-use -t to specify the grace time on command line; editing the grace time on quota1 is done with -d now. To generate a diff of this commit: cvs rdiff -u -r1.1.2.6 -r1.1.2.7 src/usr.bin/quota/printquota.c \ src/usr.bin/quota/printquota.h cvs rdiff -u -r1.29.16.4 -r1.29.16.5 src/usr.sbin/edquota/edquota.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/quota/printquota.c diff -u src/usr.bin/quota/printquota.c:1.1.2.6 src/usr.bin/quota/printquota.c:1.1.2.7 --- src/usr.bin/quota/printquota.c:1.1.2.6 Sun Jan 30 21:37:39 2011 +++ src/usr.bin/quota/printquota.c Sun Jan 30 22:49:31 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: printquota.c,v 1.1.2.6 2011/01/30 21:37:39 bouyer Exp $ */ +/* $NetBSD: printquota.c,v 1.1.2.7 2011/01/30 22:49:31 bouyer Exp $ */ /* * Copyright (c) 1980, 1990, 1993 @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "@(#)quota.c 8.4 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: printquota.c,v 1.1.2.6 2011/01/30 21:37:39 bouyer Exp $"); +__RCSID("$NetBSD: printquota.c,v 1.1.2.7 2011/01/30 22:49:31 bouyer Exp $"); #endif #endif /* not lint */ @@ -148,17 +148,19 @@ } /* - * Calculate the grace period and return a precise string for it. + * Calculate the grace period and return a precise string for it, + * either in seconds or in format xWyDzHtMuS */ const char * -timepprt(time_t now, time_t seconds, int space) +timepprt(time_t seconds, int hflag, int space) { static char buf[20], *append; int i, remain = space + 1; - if (now > seconds) - return ("none"); - seconds -= now; + if (hflag == 0) { + snprintf(buf, remain, "%" PRId64, seconds); + return buf; + } append = &buf[0]; if ((seconds / WEEK) > 0) { @@ -199,6 +201,55 @@ } /* + * convert a string of the form xWyDzHtMuS, or plain decimal, to + * a time in seconds + */ +int +timeprd(const char *str, time_t *valp) +{ + char buf[20]; + char *cur, *next, *end; + time_t val= 0; + + strncpy(buf, str, sizeof(buf)); + next = buf; + cur = strsep(&next, "Ww"); + if (next != NULL) { + val = strtoumax(cur, &end, 10) * WEEK; + if (end[0] != '\0') + return EINVAL; + } else + next = cur; + cur = strsep(&next, "Dd"); + if (next != NULL) { + val += strtoumax(cur, &end, 10) * DAY; + if (end[0] != '\0') + return EINVAL; + } else + next = cur; + cur = strsep(&next, "Hh"); + if (next != NULL) { + val += strtoumax(cur, &end, 10) * HOUR; + if (end[0] != '\0') + return EINVAL; + } else + next = cur; + cur = strsep(&next, "Mm"); + if (next != NULL) { + val += strtoumax(cur, &end, 10) * MINUTE; + if (end[0] != '\0') + return EINVAL; + } else + next = cur; + cur = strsep(&next, "Ss"); + val += strtoumax(cur, &end, 10); + if (end[0] != '\0') + return EINVAL; + *valp = val; + return 0; +} + +/* * convert a string to a uint64 value */ int Index: src/usr.bin/quota/printquota.h diff -u src/usr.bin/quota/printquota.h:1.1.2.6 src/usr.bin/quota/printquota.h:1.1.2.7 --- src/usr.bin/quota/printquota.h:1.1.2.6 Sun Jan 30 21:37:39 2011 +++ src/usr.bin/quota/printquota.h Sun Jan 30 22:49:32 2011 @@ -1,7 +1,8 @@ -/* $NetBSD: printquota.h,v 1.1.2.6 2011/01/30 21:37:39 bouyer Exp $ */ +/* $NetBSD: printquota.h,v 1.1.2.7 2011/01/30 22:49:32 bouyer Exp $ */ const char *intprt(uint64_t, u_int, int, int); -const char *timeprt(time_t, time_t, int space); -const char *timepprt(time_t, time_t, int space); +const char *timeprt(time_t, time_t, int); +const char *timepprt(time_t, int, int); +int timeprd(const char *, time_t *); int intrd(char *str, uint64_t *val, u_int); Index: src/usr.sbin/edquota/edquota.c diff -u src/usr.sbin/edquota/edquota.c:1.29.16.4 src/usr.sbin/edquota/edquota.c:1.29.16.5 --- src/usr.sbin/edquota/edquota.c:1.29.16.4 Sun Jan 30 20:54:22 2011 +++ src/usr.sbin/edquota/edquota.c Sun Jan 30 22:49:32 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: edquota.c,v 1.29.16.4 2011/01/30 20:54:22 bouyer Exp $ */ +/* $NetBSD: edquota.c,v 1.29.16.5 2011/01/30 22:49:32 bouyer Exp $ */ /* * Copyright (c) 1980, 1990, 1993 @@ -42,7 +42,7 @@ #if 0 static char sccsid[] = "from: @(#)edquota.c 8.3 (Berkeley) 4/27/95"; #else -__RCSID("$NetBSD: edquota.c,v 1.29.16.4 2011/01/30 20:54:22 bouyer Exp $"); +__RCSID("$NetBSD: edquota.c,v 1.29.16.5 2011/01/30 22:49:32 bouyer Exp $"); #endif #endif /* not lint */ @@ -130,10 +130,10 @@ long id, protoid; int quotatype, tmpfd; char *protoname; - char *soft = NULL, *hard = NULL; + char *soft = NULL, *hard = NULL, *grace = NULL; char *fs = NULL; int ch; - int tflag = 0, pflag = 0; + int pflag = 0; if (argc < 2) usage(); @@ -141,7 +141,7 @@ errx(1, "permission denied"); protoname = NULL; quotatype = USRQUOTA; - while ((ch = getopt(argc, argv, "DHdugtp:s:h:f:")) != -1) { + while ((ch = getopt(argc, argv, "DHdugp:s:h:t:f:")) != -1) { switch(ch) { case 'D': Dflag++; @@ -162,15 +162,15 @@ case 'u': quotatype = USRQUOTA; break; - case 't': - tflag++; - break; case 's': soft = optarg; break; case 'h': hard = optarg; break; + case 't': + grace = optarg; + break; case 'f': fs = optarg; break; @@ -182,7 +182,7 @@ argv += optind; if (pflag) { - if (soft || hard || dflag) + if (soft || hard || grace || dflag) usage(); if ((protoid = getentry(protoname, quotatype)) == -1) exit(1); @@ -198,12 +198,11 @@ } exit(0); } - if (soft || hard) { + if (soft || hard || grace) { struct quotause *lqup; u_int64_t softb, hardb, softi, hardi; + time_t graceb, gracei; char *str; - if (tflag) - usage(); if (soft) { str = strsep(&soft, "/"); if (str[0] == '\0' || soft == NULL || soft[0] == '\0') @@ -224,6 +223,16 @@ if (intrd(hard, &hardi, 0) != 0) errx(1, "%s: bad number", hard); } + if (grace) { + str = strsep(&grace, "/"); + if (str[0] == '\0' || grace == NULL || grace[0] == '\0') + usage(); + + if (timeprd(str, &graceb) != 0) + errx(1, "%s: bad number", str); + if (timeprd(grace, &gracei) != 0) + errx(1, "%s: bad number", grace); + } if (dflag) { curprivs = getprivs(0, quotatype, fs, 1); for (lqup = curprivs; lqup; lqup = lqup->next) { @@ -235,6 +244,10 @@ lqup->q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit = hardb; lqup->q2e.q2e_val[Q2V_FILE].q2v_hardlimit = hardi; } + if (grace) { + lqup->q2e.q2e_val[Q2V_BLOCK].q2v_grace = graceb; + lqup->q2e.q2e_val[Q2V_FILE].q2v_grace = gracei; + } } putprivs(0, quotatype, curprivs); freeprivs(curprivs); @@ -263,6 +276,10 @@ lqup->q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit = hardb; lqup->q2e.q2e_val[Q2V_FILE].q2v_hardlimit = hardi; } + if (grace) { + lqup->q2e.q2e_val[Q2V_BLOCK].q2v_grace = graceb; + lqup->q2e.q2e_val[Q2V_FILE].q2v_grace = gracei; + } } putprivs(id, quotatype, curprivs); freeprivs(curprivs); @@ -271,7 +288,7 @@ } tmpfd = mkstemp(tmpfil); fchown(tmpfd, getuid(), getgid()); - if (tflag) { + if (0 /* XXX */) { if (soft || hard) usage(); protoprivs = getprivs(0, quotatype, fs, 0); @@ -311,10 +328,8 @@ "usage:\n" " edquota [-D] [-H] [-u] [-p username] [-f filesystem] [-d] username ...\n" " edquota [-D] [-H] -g [-p groupname] [-f filesystem] [-d] groupname ...\n" - " edquota [-D] [-H] [-u] [-f filesystem] [-s b#/i#] [-h b#/i#] [-d] username ...\n" - " edquota [-D] [-H] -g [-f filesystem] [-s b#/i#] [-h b#/i#] [-d] groupname ...\n" - " edquota [-D] [-H] [-u] [-f filesystem] -t\n" - " edquota [-D] [-H] -g [-f filesystem] -t\n" + " edquota [-D] [-u] [-f filesystem] [-s b#/i#] [-h b#/i#] [-t t#/t#] \\\n\t[-d] username ...\n" + " edquota [-D] -g [-f filesystem] [-s b#/i#] [-h b#/i#] [-t t#/t#] \\\n\t[-d] groupname ...\n" ); exit(1); } @@ -679,7 +694,7 @@ qfextension[quotatype], name); } for (qup = quplist; qup; qup = qup->next) { - fprintf(fd, "%s: %s %s, limits (soft = %s, hard = %s)\n", + fprintf(fd, "%s: %s %s, limits (soft = %s, hard = %s", qup->fsname, "blocks in use:", intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_cur, HN_NOSPACE | HN_B, Hflag, 20), @@ -687,7 +702,13 @@ HN_NOSPACE | HN_B, Hflag, 20), intprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit, HN_NOSPACE | HN_B, Hflag, 20)); - fprintf(fd, "%s %s, limits (soft = %s, hard = %s)\n", + if (qup->flags & (QUOTA2|DEFAULT)) { + fprintf(fd, ", grace = %s", + timepprt(qup->q2e.q2e_val[Q2V_BLOCK].q2v_grace, + Hflag, 20)); + } + fprintf(fd, ")\n"); + fprintf(fd, "%s %s, limits (soft = %s, hard = %s", "\tinodes in use:", intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_cur, HN_NOSPACE, Hflag, 20), @@ -695,6 +716,12 @@ HN_NOSPACE, Hflag, 20), intprt(qup->q2e.q2e_val[Q2V_FILE].q2v_hardlimit, HN_NOSPACE, Hflag, 20)); + if (qup->flags & (QUOTA2|DEFAULT)) { + fprintf(fd, ", grace = %s", + timepprt(qup->q2e.q2e_val[Q2V_FILE].q2v_grace, + Hflag, 20)); + } + fprintf(fd, ")\n"); } fclose(fd); return (1); @@ -715,7 +742,9 @@ char *fsp; static char line1[BUFSIZ], line2[BUFSIZ]; static char scurb[BUFSIZ], scuri[BUFSIZ], ssoft[BUFSIZ], shard[BUFSIZ]; + static char stime[BUFSIZ]; uint64_t softb, hardb, softi, hardi; + time_t graceb = -1, gracei = -1; (void)lseek(infd, (off_t)0, SEEK_SET); fd = fdopen(dup(infd), "r"); @@ -730,31 +759,43 @@ while (fgets(line1, sizeof (line1), fd) != NULL && fgets(line2, sizeof (line2), fd) != NULL) { if ((fsp = strtok(line1, " \t:")) == NULL) { - warnx("%s: 4 bad format", line1); + warnx("%s: bad format", line1); goto out; } if ((cp = strtok((char *)0, "\n")) == NULL) { - warnx("%s: %s: 5 bad format", fsp, + warnx("%s: %s: bad format", fsp, &fsp[strlen(fsp) + 1]); goto out; } #define last_char(str) ((str)[strlen(str) - 1]) cnt = sscanf(cp, - " blocks in use: %s limits (soft = %s hard = %s\n", - scurb, ssoft, shard); - if (cnt != 3) { - warnx("%s:%s: 6 bad format %d", fsp, cp, cnt); + " blocks in use: %s limits (soft = %s hard = %s " + "grace = %s\n", scurb, ssoft, shard, stime); + if (cnt == 3) { + if (last_char(scurb) != ',' || + last_char(ssoft) != ',' || + last_char(shard) != ')') { + warnx("%s:%s: bad format %d", fsp, cp, cnt); + goto out; + } + stime[0] = '\0'; + } else if (cnt == 4) { + if (last_char(scurb) != ',' || + last_char(ssoft) != ',' || + last_char(shard) != ',' || + last_char(stime) != ')') { + warnx("%s:%s: bad format %d", fsp, cp, cnt); + goto out; + } + } else { + warnx("%s: %s: bad format", fsp, line2); goto out; } /* drop last char which is ',' or ')' */ - if (last_char(scurb) != ',' || last_char(ssoft) != ',' || - last_char(shard) != ')') { - warnx("%s:%s: 61 bad format %d", fsp, cp, cnt); - goto out; - } last_char(scurb) = '\0'; last_char(ssoft) = '\0'; last_char(shard) = '\0'; + last_char(stime) = '\0'; if (intrd(ssoft, &softb, HN_B) != 0) { warnx("%s:%s: bad number", fsp, ssoft); @@ -764,26 +805,45 @@ warnx("%s:%s: bad number", fsp, shard); goto out; } + if (cnt == 4) { + if (timeprd(stime, &graceb) != 0) { + warnx("%s:%s: bad number", fsp, shard); + goto out; + } + } + if ((cp = strtok(line2, "\n")) == NULL) { - warnx("%s: %s: 7 bad format", fsp, line2); + warnx("%s: %s: bad format", fsp, line2); goto out; } cnt = sscanf(cp, - "\tinodes in use: %s limits (soft = %s hard = %s\n", - scuri, ssoft, shard); - if (cnt != 3) { - warnx("%s: %s: 8 bad format", fsp, line2); + "\tinodes in use: %s limits (soft = %s hard = %s " + "grace = %s\n", scuri, ssoft, shard, stime); + if (cnt == 3) { + if (last_char(scuri) != ',' || + last_char(ssoft) != ',' || + last_char(shard) != ')') { + warnx("%s:%s: bad format %d", fsp, cp, cnt); + goto out; + } + stime[0] = '\0'; + } else if (cnt == 4) { + if (last_char(scuri) != ',' || + last_char(ssoft) != ',' || + last_char(shard) != ',' || + last_char(stime) != ')') { + warnx("%s:%s: bad format %d", fsp, cp, cnt); + goto out; + } + } else { + warnx("%s: %s: bad format", fsp, line2); goto out; } /* drop last char which is ',' or ')' */ - if (last_char(scuri) != ',' || last_char(ssoft) != ',' || - last_char(shard) != ')') { - warnx("%s:%s: 81 bad format %d", fsp, cp, cnt); - goto out; - } last_char(scuri) = '\0'; last_char(ssoft) = '\0'; last_char(shard) = '\0'; + last_char(stime) = '\0'; if (intrd(ssoft, &softi, 0) != 0) { warnx("%s:%s: bad number", fsp, ssoft); goto out; @@ -792,6 +852,12 @@ warnx("%s:%s: bad number", fsp, shard); goto out; } + if (cnt == 4) { + if (timeprd(stime, &gracei) != 0) { + warnx("%s:%s: bad number", fsp, shard); + goto out; + } + } for (qup = quplist; qup; qup = qup->next) { if (strcmp(fsp, qup->fsname)) continue; @@ -825,8 +891,12 @@ qup->q2e.q2e_val[Q2V_FILE].q2v_time = 0; qup->q2e.q2e_val[Q2V_BLOCK].q2v_softlimit = softb; qup->q2e.q2e_val[Q2V_BLOCK].q2v_hardlimit = hardb; + if (graceb >= 0) + qup->q2e.q2e_val[Q2V_BLOCK].q2v_grace = graceb; qup->q2e.q2e_val[Q2V_FILE].q2v_softlimit = softi; qup->q2e.q2e_val[Q2V_FILE].q2v_hardlimit = hardi; + if (gracei >= 0) + qup->q2e.q2e_val[Q2V_FILE].q2v_grace = gracei; qup->flags |= FOUND; } } @@ -906,11 +976,11 @@ (void) fgets(line1, sizeof (line1), fd); while (fgets(line1, sizeof (line1), fd) != NULL) { if ((fsp = strtok(line1, " \t:")) == NULL) { - warnx("%s: 1 bad format", line1); + warnx("%s: bad format", line1); goto bad; } if ((cp = strtok((char *)0, "\n")) == NULL) { - warnx("%s: %s: 2 bad format", fsp, + warnx("%s: %s: bad format", fsp, &fsp[strlen(fsp) + 1]); goto bad; } @@ -918,7 +988,7 @@ " block grace period: %ld %s file grace period: %ld %s", &lbtime, bunits, &litime, iunits); if (cnt != 4) { - warnx("%s:%s: 3 bad format", fsp, cp); + warnx("%s:%s: bad format", fsp, cp); goto bad; } itime = (time_t)litime;