summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Písař <ppisar@redhat.com>2013-01-09 17:00:44 +0100
committerJan Kara <jack@suse.cz>2013-01-21 22:56:54 +0100
commitfdcf21db852bc8d6c1d0b41f2812ba614851e2b4 (patch)
tree76808220c658bb8b9a020e4be14af27fdad1dab4
parentf61d6442cc92a2b2935db6995b8d901235dbd076 (diff)
Recognize units at inode limits by setquota
This patch allows to specify suffixes at inode limits on setquota command line and standard input. Decimal Units k, m, g, t are implemented. Numeric value without suffix is equivatent to single inodes as before. This is complementary functionality to `quota -s'. Signed-off-by: Petr Písař <ppisar@redhat.com> Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r--quotasys.c32
-rw-r--r--quotasys.h3
-rw-r--r--setquota.86
-rw-r--r--setquota.c39
4 files changed, 76 insertions, 4 deletions
diff --git a/quotasys.c b/quotasys.c
index 5c1464f..e583437 100644
--- a/quotasys.c
+++ b/quotasys.c
@@ -416,6 +416,38 @@ void number2str(unsigned long long num, char *buf, int format)
}
/*
+ * Convert inode number with unit from string to quota inodes.
+ * Return NULL on success, static error message otherwise.
+ */
+const char *str2number(const char *string, qsize_t *inodes)
+{
+ char *unit;
+ unsigned long long int number, multiple;
+
+ number = strtoull(string, &unit, 0);
+ if (ULLONG_MAX == number)
+ return _("Integer overflow while parsing number.");
+
+ if (!unit || unit[0] == '\0')
+ multiple = 1;
+ else if (!strcmp(unit, _("k")))
+ multiple = 1000;
+ else if (!strcmp(unit, _("m")))
+ multiple = 1000000;
+ else if (!strcmp(unit, _("g")))
+ multiple = 1000000000;
+ else if (!strcmp(unit, _("t")))
+ multiple = 1000000000000ULL;
+ else
+ return _("Unknown decimal unit. "
+ "Valid units are k, m, g, t.");
+ if (number > QSIZE_MAX / multiple)
+ return _("Integer overflow while interpreting decimal unit.");
+ *inodes = number * multiple;
+ return NULL;
+}
+
+/*
* Wrappers for mount options processing functions
*/
diff --git a/quotasys.h b/quotasys.h
index 0cc2c4c..505ea77 100644
--- a/quotasys.h
+++ b/quotasys.h
@@ -109,6 +109,9 @@ const char *str2space(const char *string, qsize_t *space);
/* Convert number to short printable form */
void number2str(unsigned long long, char *, int);
+/* Convert inode number with unit from string to quota inodes. */
+const char *str2number(const char *string, qsize_t *inodes);
+
/* Return pointer to given mount option in mount option string */
char *str_hasmntopt(const char *optstring, const char *opt);
diff --git a/setquota.8 b/setquota.8
index e4511c4..508309e 100644
--- a/setquota.8
+++ b/setquota.8
@@ -189,6 +189,12 @@ are interpreted as multiples of kibibyte (1024 bytes) blocks by default.
Symbols K, M, G, and T can be appended to numeric value to express kibibytes,
mebibytes, gibibytes, and tebibytes.
.PP
+.I inode-softlimit
+and
+.I inode-hardlimit
+are interpreted literally. Symbols k, m, g, and t can be appended to numeric
+value to express multiples of 10^3, 10^6, 10^9, and 10^12 inodes.
+.PP
To disable a quota, set the corresponding parameter to 0. To change quotas
for several filesystems, invoke once for each filesystem.
.PP
diff --git a/setquota.c b/setquota.c
index e55b79d..19449ad 100644
--- a/setquota.c
+++ b/setquota.c
@@ -106,6 +106,19 @@ static qsize_t parse_blocksize(const char *str, const char *msg)
return ret;
}
+/* Convert inode count to number - print errstr message in case of failure */
+static qsize_t parse_inodecount(const char *str, const char *msg)
+{
+ qsize_t ret;
+ const char *error = str2number(str, &ret);
+
+ if (error) {
+ errstr(_("%s: %s: %s\n"), msg, str, error);
+ usage();
+ }
+ return ret;
+}
+
/* Convert our flags to quota type */
static inline int flag2type(int flags)
{
@@ -241,8 +254,8 @@ static void parse_options(int argcnt, char **argstr)
if (!(flags & (FL_GRACE | FL_INDIVIDUAL_GRACE | FL_PROTO))) {
toset.dqb_bsoftlimit = parse_blocksize(argstr[optind++], _("Bad block softlimit"));
toset.dqb_bhardlimit = parse_blocksize(argstr[optind++], _("Bad block hardlimit"));
- toset.dqb_isoftlimit = parse_unum(argstr[optind++], _("Bad inode softlimit"));
- toset.dqb_ihardlimit = parse_unum(argstr[optind++], _("Bad inode hardlimit"));
+ toset.dqb_isoftlimit = parse_inodecount(argstr[optind++], _("Bad inode softlimit"));
+ toset.dqb_ihardlimit = parse_inodecount(argstr[optind++], _("Bad inode hardlimit"));
}
else if (flags & FL_PROTO)
protoid = name2id(protoname, flag2type(flags), !!(flags & FL_NUMNAMES), NULL);
@@ -319,7 +332,7 @@ static int read_entry(qid_t *id, qsize_t *isoftlimit, qsize_t *ihardlimit, qsize
static int line = 0;
char name[MAXNAMELEN+1];
char linebuf[MAXLINELEN], *chptr;
- unsigned long is, ih;
+ char is[MAXNAMELEN+1], ih[MAXNAMELEN+1];
char bs[MAXNAMELEN+1], bh[MAXNAMELEN+1];
const char *error;
int ret;
@@ -339,7 +352,7 @@ static int read_entry(qid_t *id, qsize_t *isoftlimit, qsize_t *ihardlimit, qsize
chptr++;
if (*chptr == '\n')
continue;
- ret = sscanf(chptr, "%s %s %s %lu %lu", name, bs, bh, &is, &ih);
+ ret = sscanf(chptr, "%s %s %s %s %s", name, bs, bh, is, ih);
if (ret != 5) {
errstr(_("Cannot parse input line %d.\n"), line);
if (!(flags & FL_CONTINUE_BATCH))
@@ -373,6 +386,24 @@ static int read_entry(qid_t *id, qsize_t *isoftlimit, qsize_t *ihardlimit, qsize
errstr(_("Skipping line.\n"));
continue;
}
+ error = str2number(is, isoftlimit);
+ if (error) {
+ errstr(_("Unable to parse inode soft limit '%s' "
+ "on line %d: %s\n"), is, line, error);
+ if (!(flags & FL_CONTINUE_BATCH))
+ die(1, _("Exitting.\n"));
+ errstr(_("Skipping line.\n"));
+ continue;
+ }
+ error = str2number(ih, ihardlimit);
+ if (error) {
+ errstr(_("Unable to parse inode hard limit '%s' "
+ "on line %d: %s\n"), ih, line, error);
+ if (!(flags & FL_CONTINUE_BATCH))
+ die(1, _("Exitting.\n"));
+ errstr(_("Skipping line.\n"));
+ continue;
+ }
break;
}
*isoftlimit = is;