summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjkar8572 <jkar8572>2002-11-21 18:37:57 +0000
committerjkar8572 <jkar8572>2002-11-21 18:37:57 +0000
commitad868a7b3e1c2cdaeddcf93b8ccf55434b0d1c21 (patch)
treee4df55fd3aa0496bee0fa3f9f1265eeae38cac2c
parent9bdd6236879ea379758f82ad5cec7033f0a751ac (diff)
downloadlinuxquota-ad868a7b3e1c2cdaeddcf93b8ccf55434b0d1c21.tar.gz
Updated edquota(8) and setquota(8) to allow setting of individual grace time (Jan Kara)
-rw-r--r--Changelog1
-rw-r--r--edquota.823
-rw-r--r--edquota.c39
-rw-r--r--quotaio.h3
-rw-r--r--quotaio_v1.c6
-rw-r--r--quotaio_v2.c4
-rw-r--r--quotaops.c163
-rw-r--r--quotaops.h4
-rw-r--r--quotasys.c18
-rw-r--r--quotasys.h3
-rw-r--r--setquota.831
-rw-r--r--setquota.c59
12 files changed, 299 insertions, 55 deletions
diff --git a/Changelog b/Changelog
index d43a756..4bcac48 100644
--- a/Changelog
+++ b/Changelog
@@ -1,4 +1,5 @@
Changes in quota-tools from 3.07 to 3.08
+* Updated edquota(8) and setquota(8) to allow setting of individual grace time (Jan Kara)
* Fixed bug in convertquota(8) when quota was turned on during converting (Jan Kara)
* Add support for XFS filesystems without root special casing (Christoph Hellwig)
* XFS documentation updates (Nathan Scott)
diff --git a/edquota.8 b/edquota.8
index 5a8e21b..9863752 100644
--- a/edquota.8
+++ b/edquota.8
@@ -32,6 +32,21 @@ edquota \- edit user quotas
.I filesystem
]
.B \-t
+.LP
+.B edquota
+[
+.BR \-u \ |
+.B \-g
+] [
+.B \-F
+.I format-name
+] [
+.B \-f
+.I filesystem
+]
+.B \-T
+.IR username \ |
+.IR groupname .\|.\|.
.SH DESCRIPTION
.IX "edquota command" "" "\fLedquota\fP \(em edit user quotas"
.IX edit "user quotas \(em \fLedquota\fP"
@@ -109,9 +124,15 @@ Edit the soft time limits for each filesystem.
In old quota format if the time limits are zero, the default time limits in
.B <linux/quota.h>
are used. In new quota format time limits must be specified (there is no default
-value set in kernel). Time units of seconds, minutes, hours, days, weeks, and months
+value set in kernel). Time units of 'seconds', 'minutes', 'hours', 'days', 'weeks', and 'months'
are understood. Time limits are printed in the greatest possible time unit such that
the value is greater than or equal to one.
+.TP
+.B \-T
+Edit time for the user/group when softlimit is enforced. Possible values
+are 'unset' or number and unit. Units are same as used in
+.B \-t
+option.
.SH FILES
.PD 0
.TP 20
diff --git a/edquota.c b/edquota.c
index 337a69e..82833fc 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.9 2002/07/23 15:59:27 jkar8572 Exp $"
+#ident "$Id: edquota.c,v 1.10 2002/11/21 18:37:58 jkar8572 Exp $"
/*
* Disk quota editor.
@@ -67,12 +67,14 @@ void usage(void)
errstr("%s%s%s",
_("Usage:\tedquota [-r] [-u] [-F formatname] [-p username] [-f filesystem] username ...\n"),
_("\tedquota [-r] -g [-F formatname] [-p groupname] [-f filesystem] groupname ...\n"),
- _("\tedquota [-r] [-u|g] [-F formatname] [-f filesystem] -t\n"));
+ _("\tedquota [-r] [-u|g] [-F formatname] [-f filesystem] -t\n"),
+ _("\tedquota [-r] [-u|g] [-F formatname] [-f filesystem] -T username|groupname ...\n"));
#else
errstr("%s%s%s",
_("Usage:\tedquota [-u] [-F formatname] [-p username] [-f filesystem] username ...\n"),
_("\tedquota -g [-F formatname] [-p groupname] [-f filesystem] groupname ...\n"),
- _("\tedquota [-u|g] [-F formatname] [-f filesystem] -t\n"));
+ _("\tedquota [-u|g] [-F formatname] [-f filesystem] -t\n"),
+ _("\tedquota [-u|g] [-F formatname] [-f filesystem] -T username|groupname ...\n"));
#endif
fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
exit(1);
@@ -84,7 +86,7 @@ int main(int argc, char **argv)
long id, protoid;
int quotatype, tmpfd, ret;
char *protoname = NULL;
- int tflag = 0, pflag = 0, rflag = 0, fmt = -1;
+ int tflag = 0, Tflag = 0, pflag = 0, rflag = 0, fmt = -1;
struct quota_handle **handles;
char *tmpfil, *tmpdir = NULL;
@@ -97,9 +99,9 @@ int main(int argc, char **argv)
dirname = NULL;
quotatype = USRQUOTA;
#if defined(RPC_SETQUOTA)
- while ((ret = getopt(argc, argv, "ugrntVp:F:f:")) != -1) {
+ while ((ret = getopt(argc, argv, "ugrntTVp:F:f:")) != -1) {
#else
- while ((ret = getopt(argc, argv, "ugtVp:F:f:")) != -1) {
+ while ((ret = getopt(argc, argv, "ugtTVp:F:f:")) != -1) {
#endif
switch (ret) {
case 'p':
@@ -121,6 +123,9 @@ int main(int argc, char **argv)
case 't':
tflag++;
break;
+ case 'T':
+ Tflag++;
+ break;
case 'F':
if ((fmt = name2fmt(optarg)) == QF_ERROR) /* Error? */
exit(1);
@@ -138,7 +143,7 @@ int main(int argc, char **argv)
argc -= optind;
argv += optind;
- if (tflag && argc != 0)
+ if ((tflag && argc != 0) || (Tflag && argc < 1))
usage();
init_kernel_interface();
@@ -203,6 +208,26 @@ int main(int argc, char **argv)
die(1, _("Failed to parse grace times file.\n"));
}
}
+ else if (Tflag) {
+ for (; argc > 0; argc--, argv++) {
+ id = name2id(*argv, quotatype);
+ curprivs = getprivs(id, handles, 0);
+ if (writeindividualtimes(curprivs, tmpfd, *argv, quotatype) < 0) {
+ errstr(_("Can't write individual grace times to file.\n"));
+ continue;
+ }
+ if (editprivs(tmpfil) < 0) {
+ errstr(_("Error while editting individual grace times.\n"));
+ continue;
+ }
+ if (readindividualtimes(curprivs, tmpfd) < 0) {
+ errstr(_("Can't read individual grace times from file.\n"));
+ continue;
+ }
+ putprivs(curprivs, COMMIT_TIMES);
+ freeprivs(curprivs);
+ }
+ }
else {
for (; argc > 0; argc--, argv++) {
id = name2id(*argv, quotatype);
diff --git a/quotaio.h b/quotaio.h
index 74150b9..24ad2f7 100644
--- a/quotaio.h
+++ b/quotaio.h
@@ -132,7 +132,8 @@ struct dquot {
/* Flags for commit function (have effect only when quota in kernel is turned on) */
#define COMMIT_USAGE QIF_USAGE
#define COMMIT_LIMITS QIF_LIMITS
-#define COMMIT_ALL (COMMIT_USAGE | COMMIT_LIMITS)
+#define COMMIT_TIMES QIF_TIMES
+#define COMMIT_ALL (COMMIT_USAGE | COMMIT_LIMITS | COMMIT_TIMES)
/* Structure of quotafile operations */
struct quotafile_ops {
diff --git a/quotaio_v1.c b/quotaio_v1.c
index d565e01..40b2ad0 100644
--- a/quotaio_v1.c
+++ b/quotaio_v1.c
@@ -34,7 +34,7 @@
#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
#ident "$Copyright: All rights reserved. $"
-#ident "$Id: quotaio_v1.c,v 1.12 2002/03/27 16:21:26 jkar8572 Exp $"
+#ident "$Id: quotaio_v1.c,v 1.13 2002/11/21 18:37:58 jkar8572 Exp $"
#include <unistd.h>
#include <errno.h>
@@ -316,6 +316,10 @@ static int v1_commit_dquot(struct dquot *dquot, int flags)
cmd = Q_V1_SETUSE;
else if (flags == COMMIT_LIMITS)
cmd = Q_V1_SETQLIM;
+ else if (flags & COMMIT_TIMES) {
+ errno = EINVAL;
+ return -1;
+ }
else
cmd = Q_V1_SETQUOTA;
v1_util2kerndqblk(&kdqblk, &dquot->dq_dqb);
diff --git a/quotaio_v2.c b/quotaio_v2.c
index 9fc7e43..095c39c 100644
--- a/quotaio_v2.c
+++ b/quotaio_v2.c
@@ -692,6 +692,10 @@ static int v2_commit_dquot(struct dquot *dquot, int flags)
cmd = Q_V2_SETUSE;
else if (flags == COMMIT_LIMITS)
cmd = Q_V2_SETQLIM;
+ else if (flags & COMMIT_TIMES) {
+ errno = EINVAL;
+ return -1;
+ }
else
cmd = Q_V2_SETQUOTA;
v2_util2kerndqblk(&kdqblk, &dquot->dq_dqb);
diff --git a/quotaops.c b/quotaops.c
index 2dc6972..b9be23b 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.8 2002/07/23 15:59:27 jkar8572 Exp $"
+#ident "$Id: quotaops.c,v 1.9 2002/11/21 18:37:58 jkar8572 Exp $"
#include <rpc/rpc.h>
#include <sys/types.h>
@@ -50,6 +50,7 @@
#include <paths.h>
#include <unistd.h>
#include <time.h>
+#include <ctype.h>
#if defined(RPC)
#include "rquota.h"
@@ -64,27 +65,6 @@
#include "quotaio.h"
/*
- * Convert ASCII input times to seconds.
- */
-static int cvtatos(time_t time, char *units, time_t * seconds)
-{
- if (memcmp(units, "second", 6) == 0)
- *seconds = time;
- else if (memcmp(units, "minute", 6) == 0)
- *seconds = time * 60;
- else if (memcmp(units, "hour", 4) == 0)
- *seconds = time * 60 * 60;
- else if (memcmp(units, "day", 3) == 0)
- *seconds = time * 24 * 60 * 60;
- else {
- errstr(_("bad units, specify:\n %s, %s, %s, or %s"), units,
- "days", "hours", "minutes", "seconds");
- return -1;
- }
- return 0;
-}
-
-/*
* Set grace time if needed
*/
void update_grace_times(struct dquot *q)
@@ -173,18 +153,20 @@ struct dquot *getprivs(qid_t id, struct quota_handle **handles, int quiet)
/*
* Store the requested quota information.
*/
-int putprivs(struct dquot *qlist)
+int putprivs(struct dquot *qlist, int flags)
{
struct dquot *q;
+ int ret = 0;
for (q = qlist; q; q = q->dq_next) {
- if (q->dq_h->qh_ops->commit_dquot(q, COMMIT_LIMITS) == -1) {
+ if (q->dq_h->qh_ops->commit_dquot(q, flags) == -1) {
errstr(_("Can't write quota for %u on %s: %s\n"),
q->dq_id, q->dq_h->qh_quotadev, strerror(errno));
+ ret = -1;
continue;
}
}
- return 0;
+ return ret;
}
/*
@@ -241,8 +223,7 @@ int writeprivs(struct dquot *qlist, int outfd, char *name, int quotatype)
type2name(quotatype), name, *type2name(quotatype), name2id(name, quotatype));
fprintf(fd,
- _
- (" Filesystem blocks soft hard inodes soft hard\n"));
+ _(" Filesystem blocks soft hard inodes soft hard\n"));
for (q = qlist; q; q = q->dq_next) {
fprintf(fd, " %-24s %10Lu %10Lu %10Lu %10Lu %8Lu %8Lu\n",
@@ -270,7 +251,7 @@ int writeprivs(struct dquot *qlist, int outfd, char *name, int quotatype)
}
/* Merge changes on one dev to proper structure in the list */
-static void merge_to_list(struct dquot *qlist, char *dev, u_int64_t blocks, u_int64_t bsoft,
+static void merge_limits_to_list(struct dquot *qlist, char *dev, u_int64_t blocks, u_int64_t bsoft,
u_int64_t bhard, u_int64_t inodes, u_int64_t isoft, u_int64_t ihard)
{
struct dquot *q;
@@ -331,7 +312,7 @@ int readprivs(struct dquot *qlist, int infd)
return -1;
}
- merge_to_list(qlist, fsp, blocks, bsoft, bhard, inodes, isoft, ihard);
+ merge_limits_to_list(qlist, fsp, blocks, bsoft, bhard, inodes, isoft, ihard);
}
#else
/*
@@ -371,7 +352,7 @@ int readprivs(struct dquot *qlist, int infd)
return -1;
}
- merge_to_list(qlist, fsp, blocks, bsoft, bhard, inodes, isoft, ihard);
+ merge_limits_to_list(qlist, fsp, blocks, bsoft, bhard, inodes, isoft, ihard);
}
#endif
fclose(fd);
@@ -392,6 +373,121 @@ int readprivs(struct dquot *qlist, int infd)
return 0;
}
+/* Merge changes on one dev to proper structure in the list */
+static void merge_times_to_list(struct dquot *qlist, char *dev, time_t btime, time_t itime)
+{
+ struct dquot *q;
+
+ for (q = qlist; q; q = q->dq_next) {
+ if (!devcmp_handle(dev, q->dq_h))
+ continue;
+
+ q->dq_dqb.dqb_btime = btime;
+ q->dq_dqb.dqb_itime = itime;
+ q->dq_flags |= DQ_FOUND;
+ }
+}
+
+/*
+ * Write grace times of user to file
+ */
+int writeindividualtimes(struct dquot *qlist, int outfd, char *name, int quotatype)
+{
+ struct dquot *q;
+ FILE *fd;
+ time_t now;
+ char btimestr[MAXTIMELEN], itimestr[MAXTIMELEN];
+
+ ftruncate(outfd, 0);
+ lseek(outfd, 0, SEEK_SET);
+ if (!(fd = fdopen(dup(outfd), "w")))
+ die(1, _("Can't duplicate descriptor of file to write to: %s\n"), strerror(errno));
+
+ fprintf(fd, _("Times to enforce softlimit for %s %s (%cid %d):\n"),
+ type2name(quotatype), name, *type2name(quotatype), name2id(name, quotatype));
+ fprintf(fd, _("Time units may be: days, hours, minutes, or seconds\n"));
+ fprintf(fd,
+ _(" Filesystem block grace inode grace\n"));
+
+ time(&now);
+ for (q = qlist; q; q = q->dq_next) {
+ if (!q->dq_dqb.dqb_btime)
+ strcpy(btimestr, _("unset"));
+ else if (q->dq_dqb.dqb_btime <= now)
+ strcpy(btimestr, _("0seconds"));
+ else
+ sprintf(btimestr, "%useconds", (unsigned)(q->dq_dqb.dqb_btime - now));
+ if (!q->dq_dqb.dqb_itime)
+ strcpy(itimestr, _("unset"));
+ else if (q->dq_dqb.dqb_itime <= now)
+ strcpy(itimestr, _("0seconds"));
+ else
+ sprintf(itimestr, _("%useconds"), (unsigned)(q->dq_dqb.dqb_itime - now));
+
+ fprintf(fd, " %-24s %22s %22s\n", q->dq_h->qh_quotadev, btimestr, itimestr);
+ }
+ fclose(fd);
+ return 0;
+}
+
+/*
+ * Read list of grace times for a user and convert it
+ */
+int readindividualtimes(struct dquot *qlist, int infd)
+{
+ FILE *fd;
+ int cnt, btime, itime;
+ char line[BUFSIZ], fsp[BUFSIZ], btimestr[BUFSIZ], itimestr[BUFSIZ];
+ char iunits[BUFSIZ], bunits[BUFSIZ];
+ time_t now, bseconds, iseconds;
+
+ lseek(infd, 0, SEEK_SET);
+ if (!(fd = fdopen(dup(infd), "r")))
+ die(1, _("Can't duplicate descriptor of temp file: %s\n"), strerror(errno));
+
+ /*
+ * Discard title lines, then read lines to process.
+ */
+ fgets(line, sizeof(line), fd);
+ fgets(line, sizeof(line), fd);
+ fgets(line, sizeof(line), fd);
+
+ time(&now);
+ while (fgets(line, sizeof(line), fd)) {
+ cnt = sscanf(line, "%s %s %s", fsp, btimestr, itimestr);
+ if (cnt != 3) {
+format_err:
+ errstr(_("bad format:\n%s\n"), line);
+ return -1;
+ }
+ if (!strcmp(btimestr, _("unset")))
+ bseconds = 0;
+ else {
+ if (sscanf(btimestr, "%d%s", &btime, bunits) != 2)
+ goto format_err;
+ if (str2timeunits(btime, bunits, &bseconds) < 0) {
+units_err:
+ errstr(_("Bad time units. Units are 'second', 'minute', 'hour' and 'day'.\n"));
+ return -1;
+ }
+ bseconds += now;
+ }
+ if (!strcmp(itimestr, _("unset")))
+ iseconds = 0;
+ else {
+ if (sscanf(itimestr, "%d%s", &itime, iunits) != 2)
+ goto format_err;
+ if (str2timeunits(itime, iunits, &iseconds) < 0)
+ goto units_err;
+ iseconds += now;
+ }
+ merge_times_to_list(qlist, fsp, bseconds, iseconds);
+ }
+ fclose(fd);
+
+ return 0;
+}
+
/*
* Convert a dquot list to an ASCII file of grace times.
*/
@@ -505,10 +601,11 @@ int readtimes(struct quota_handle **handles, int infd)
return -1;
}
#endif
- if (cvtatos(btime, bunits, &bseconds) < 0)
- return -1;
- if (cvtatos(itime, iunits, &iseconds) < 0)
+ if (str2timeunits(btime, bunits, &bseconds) < 0 ||
+ str2timeunits(itime, iunits, &iseconds) < 0) {
+ errstr(_("Bad time units. Units are 'second', 'minute', 'hour' and 'day'.\n"));
return -1;
+ }
for (i = 0; handles[i]; i++) {
if (!devcmp_handle(fsp, handles[i]))
continue;
diff --git a/quotaops.h b/quotaops.h
index b680c74..bde8f13 100644
--- a/quotaops.h
+++ b/quotaops.h
@@ -4,10 +4,12 @@
#include "quotaio.h"
struct dquot *getprivs(qid_t id, struct quota_handle ** handles, int quiet);
-int putprivs(struct dquot * qlist);
+int putprivs(struct dquot * qlist, int flags);
int editprivs(char *tmpfile);
int writeprivs(struct dquot * qlist, int outfd, char *name, int quotatype);
int readprivs(struct dquot * qlist, int infd);
+int writeindividualtimes(struct dquot * qlist, int outfd, char *name, int quotatype);
+int readindividualtimes(struct dquot * qlist, int infd);
int writetimes(struct quota_handle ** handles, int outfd);
int readtimes(struct quota_handle ** handles, int infd);
void freeprivs(struct dquot * qlist);
diff --git a/quotasys.c b/quotasys.c
index 7c51a1e..9a5ccf3 100644
--- a/quotasys.c
+++ b/quotasys.c
@@ -285,6 +285,24 @@ void time2str(time_t seconds, char *buf, int flags)
}
/*
+ * Convert number with unit to time in seconds
+ */
+int str2timeunits(time_t num, char *unit, time_t *res)
+{
+ if (memcmp(unit, "second", 6) == 0)
+ *res = num;
+ else if (memcmp(unit, "minute", 6) == 0)
+ *res = num * 60;
+ else if (memcmp(unit, "hour", 4) == 0)
+ *res = num * 60 * 60;
+ else if (memcmp(unit, "day", 3) == 0)
+ *res = num * 24 * 60 * 60;
+ else
+ return -1;
+ return 0;
+}
+
+/*
* Convert number in quota blocks to some nice short form for printing
*/
void space2str(qsize_t space, char *buf, int format)
diff --git a/quotasys.h b/quotasys.h
index 38f4da6..3569bad 100644
--- a/quotasys.h
+++ b/quotasys.h
@@ -82,6 +82,9 @@ void difftime2str(time_t, char *);
/* Convert time to printable form */
void time2str(time_t, char *, int);
+/* Convert number and units to time in seconds */
+int str2timeunits(time_t, char *, time_t *);
+
/* Convert number in quota blocks to short printable form */
void space2str(qsize_t, char *, int);
diff --git a/setquota.8 b/setquota.8
index 5177da1..fd10909 100644
--- a/setquota.8
+++ b/setquota.8
@@ -2,7 +2,7 @@
.SH NAME
setquota \- set disk quotas
.SH SYNOPSIS
-.B /usr/sbin/setquota
+.B setquota
[
.B \-r
]
@@ -24,7 +24,7 @@ setquota \- set disk quotas
|
.I filesystem...
.LP
-.B /usr/sbin/setquota
+.B setquota
[
.B \-r
]
@@ -46,7 +46,7 @@ setquota \- set disk quotas
|
.I filesystem...
.LP
-.B /usr/sbin/setquota
+.B setquota
.B \-t
[
.B \-u
@@ -62,6 +62,24 @@ setquota \- set disk quotas
.B \-a
|
.I filesystem...
+.LP
+.B setquota
+.B \-T
+[
+.B \-u
+|
+.B \-g
+]
+[
+.B \-F
+.I quotaformat
+]
+.I name
+.I block-grace
+.I inode-grace
+.B \-a
+|
+.I filesystem...
.SH DESCRIPTION
.IX "setquota command" "" "\fLsetquota\fP \(em set disk quotas"
.IX set "disk quotas \(em \fLsetquota\fP"
@@ -107,6 +125,13 @@ and
.B inode-grace
are specified in seconds.
.TP
+.B -T
+Alter times for individual user/group when softlimit is enforced. Times
+.B block-grace
+and
+.B inode-grace
+are specified in seconds or can be string 'unset'.
+.TP
.B -a
Go through all filesystems with quota in
.B /etc/mtab
diff --git a/setquota.c b/setquota.c
index 25cd14c..fee07a0 100644
--- a/setquota.c
+++ b/setquota.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <string.h>
#include <getopt.h>
+#include <time.h>
#if defined(RPC)
#include "rquota.h"
@@ -26,6 +27,7 @@
#define FL_ALL 8
#define FL_PROTO 16
#define FL_GRACE 32
+#define FL_INDIVIDUAL_GRACE 64
int flags, fmt = -1;
char **mnt;
@@ -42,13 +44,15 @@ static void usage(void)
" setquota [-u|-g] [-r] [-F quotaformat] <user|group>\n"
"\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> -a|<filesystem>...\n"
" setquota [-u|-g] [-r] [-F quotaformat] <-p protouser|protogroup> <user|group> -a|<filesystem>...\n"
- " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n"));
+ " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n"
+ " setquota [-u|-g] [-F quotaformat] <user|group> -T <blockgrace> <inodegrace> -a|<filesystem>...\n"));
#else
errstr(_("Usage:\n"
" setquota [-u|-g] [-F quotaformat] <user|group>\n"
"\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> -a|<filesystem>...\n"
" setquota [-u|-g] [-F quotaformat] <-p protouser|protogroup> <user|group> -a|<filesystem>...\n"
- " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n"));
+ " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n"
+ " setquota [-u|-g] [-F quotaformat] <user|group> -T <blockgrace> <inodegrace> -a|<filesystem>...\n"));
#endif
fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
exit(1);
@@ -84,9 +88,9 @@ static void parse_options(int argcnt, char **argstr)
char *protoname = NULL;
#ifdef RPC_SETQUOTA
- char *opts = "igp:urVF:ta";
+ char *opts = "igp:urVF:taT";
#else
- char *opts = "igp:uVF:ta";
+ char *opts = "igp:uVF:taT";
#endif
while ((ret = getopt(argcnt, argstr, opts)) != -1) {
@@ -113,6 +117,9 @@ static void parse_options(int argcnt, char **argstr)
case 't':
flags |= FL_GRACE;
break;
+ case 'T':
+ flags |= FL_INDIVIDUAL_GRACE;
+ break;
case 'F':
if ((fmt = name2fmt(optarg)) == QF_ERROR)
exit(1);
@@ -132,6 +139,8 @@ static void parse_options(int argcnt, char **argstr)
}
if (flags & FL_GRACE)
otherargs = 2;
+ else if (flags & FL_INDIVIDUAL_GRACE)
+ otherargs = 3;
else {
otherargs = 1;
if (!(flags & FL_PROTO))
@@ -145,19 +154,36 @@ static void parse_options(int argcnt, char **argstr)
flags |= FL_USER;
if (!(flags & FL_GRACE)) {
id = name2id(argstr[optind++], flag2type(flags));
- if (!(flags & FL_PROTO)) {
+ if (!(flags & (FL_GRACE | FL_INDIVIDUAL_GRACE | FL_PROTO))) {
toset.dqb_bsoftlimit = parse_num(argstr[optind++], _("block softlimit"));
toset.dqb_bhardlimit = parse_num(argstr[optind++], _("block hardlimit"));
toset.dqb_isoftlimit = parse_num(argstr[optind++], _("inode softlimit"));
toset.dqb_ihardlimit = parse_num(argstr[optind++], _("inode hardlimit"));
}
- else
+ else if (flags & FL_PROTO)
protoid = name2id(protoname, flag2type(flags));
}
- else {
+ if (flags & FL_GRACE) {
toset.dqb_btime = parse_num(argstr[optind++], _("block grace time"));
toset.dqb_itime = parse_num(argstr[optind++], _("inode grace time"));
}
+ else if (flags & FL_INDIVIDUAL_GRACE) {
+ time_t now;
+
+ time(&now);
+ if (!strcmp(argstr[optind], _("unset"))) {
+ toset.dqb_btime = 0;
+ optind++;
+ }
+ else
+ toset.dqb_btime = now + parse_num(argstr[optind++], _("block grace time"));
+ if (!strcmp(argstr[optind], _("unset"))) {
+ toset.dqb_itime = 0;
+ optind++;
+ }
+ else
+ toset.dqb_itime = now + parse_num(argstr[optind++], _("inode grace time"));
+ }
if (!(flags & FL_ALL)) {
mntcnt = argcnt - optind;
mnt = argstr + optind;
@@ -194,7 +220,7 @@ static void setlimits(struct quota_handle **handles)
update_grace_times(q);
}
}
- putprivs(curprivs);
+ putprivs(curprivs, COMMIT_LIMITS);
freeprivs(curprivs);
}
@@ -210,6 +236,21 @@ static void setgraces(struct quota_handle **handles)
}
}
+/* Set grace times for individual user */
+static void setindivgraces(struct quota_handle **handles)
+{
+ struct dquot *q, *curprivs;
+
+ curprivs = getprivs(id, handles, 0);
+ for (q = curprivs; q; q = q->dq_next) {
+ q->dq_dqb.dqb_btime = toset.dqb_btime;
+ q->dq_dqb.dqb_itime = toset.dqb_itime;
+ }
+ if (putprivs(curprivs, COMMIT_TIMES) == -1)
+ errstr(_("Can't write times for %s. Maybe kernel doesn't support such operation?\n"), type2name(flags & FL_USER ? USRQUOTA : GRPQUOTA));
+ freeprivs(curprivs);
+}
+
int main(int argc, char **argv)
{
struct quota_handle **handles;
@@ -227,6 +268,8 @@ int main(int argc, char **argv)
if (flags & FL_GRACE)
setgraces(handles);
+ else if (flags & FL_INDIVIDUAL_GRACE)
+ setindivgraces(handles);
else
setlimits(handles);