From 54c0a3f3e6575fa5af39ddd797d5381c36b48001 Mon Sep 17 00:00:00 2001 From: Evan Broder Date: Wed, 25 Mar 2009 18:18:09 -0500 Subject: [PATCH] Allow passing in human-readable units for specifying amounts of space Add a util_GetHumanInt32 function for parsing numbers human-readable units using single-character, uppercase suffixes for indicating orders of magnitude (e.g. 'M', 'G'). Use this function to parse human readable values for all arguments that previously accepted a value in kilobytes: fs setquota, fs setcachesize, vos setfields, and vos create. Reviewed-on: http://gerrit.openafs.org/66 Verified-by: Marc Dionne Reviewed-by: Russ Allbery Verified-by: Jeffrey Altman Reviewed-by: Jeffrey Altman --- src/WINNT/afsd/fs.c | 4 ++-- src/config/stds.h | 2 ++ src/util/afsutil_prototypes.h | 1 + src/util/volparse.c | 35 +++++++++++++++++++++++++++++++++++ src/venus/fs.c | 4 ++-- src/volser/vos.c | 10 ++-------- 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index 790a455fc..3058a0b4c 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -1521,7 +1521,7 @@ SetVolCmd(struct cmd_syndesc *as, void *arock) { status->MinQuota = status->MaxQuota = -1; motd = offmsg = NULL; if (as->parms[1].items) { - code = util_GetInt32(as->parms[1].items->data, &status->MaxQuota); + code = util_GetHumanInt32(as->parms[1].items->data, &status->MaxQuota); if (code) { fprintf(stderr,"%s: bad integer specified for quota.\n", pn); error = 1; @@ -2444,7 +2444,7 @@ SetCacheSizeCmd(struct cmd_syndesc *as, void *arock) return 1; } if (as->parms[0].items) { - code = util_GetInt32(as->parms[0].items->data, &temp); + code = util_GetHumanInt32(as->parms[0].items->data, &temp); if (code) { fprintf(stderr,"%s: bad integer specified for cache size.\n", pn); return 1; diff --git a/src/config/stds.h b/src/config/stds.h index 5995aae3d..f451b16a1 100644 --- a/src/config/stds.h +++ b/src/config/stds.h @@ -45,8 +45,10 @@ pragma Off(Prototype_override_warnings); #endif */ #define MAX_AFS_INT32 0x7FFFFFFF +#define MIN_AFS_INT32 (-MAX_AFS_INT32 - 1) #define MAX_AFS_UINT32 0xFFFFFFFF #define MAX_AFS_INT64 0x7FFFFFFFFFFFFFFFL +#define MIN_AFS_INT64 (-MAX_AFS_INT64 - 1) #define MAX_AFS_UINT64 0xFFFFFFFFFFFFFFFFL typedef short afs_int16; diff --git a/src/util/afsutil_prototypes.h b/src/util/afsutil_prototypes.h index 589da526c..9d0645d01 100644 --- a/src/util/afsutil_prototypes.h +++ b/src/util/afsutil_prototypes.h @@ -201,6 +201,7 @@ extern afs_int32 volutil_PartitionName2_r(afs_int32 part, char *tbuffer, size_t extern char *volutil_PartitionName(int avalue); extern afs_int32 util_GetInt32(register char *as, afs_int32 * aval); extern afs_uint32 util_GetUInt32(register char *as, afs_uint32 * aval); +extern afs_int32 util_GetHumanInt32(register char *as, afs_int32 * aval); /* winsock_nt.c */ diff --git a/src/util/volparse.c b/src/util/volparse.c index 72bee5ee4..6ba18927c 100644 --- a/src/util/volparse.c +++ b/src/util/volparse.c @@ -11,6 +11,7 @@ #include #include +#include #ifdef HAVE_STDLIB_H #include #endif @@ -306,3 +307,37 @@ util_GetUInt32(register char *as, afs_uint32 * aval) *aval = total; return 0; } + +static const char power_letter[] = { + 'K', /* kibi */ + 'M', /* mebi */ + 'G', /* gibi */ + 'T', /* tebi */ +}; + +afs_int32 +util_GetHumanInt32(register char *as, afs_int32 * aval) +{ + long value; + char * unit; + long mult = 1; + int exponent = 0; + + errno = 0; + value = strtol(as, &unit, 0); + if (errno) + return -1; + if (unit[0] != 0) { + for (exponent = 0; exponent < sizeof(power_letter) && power_letter[exponent] != unit[0]; exponent++) { + mult *= 1024; + } + if (exponent == sizeof(power_letter)) + return -1; + } + if (value > MAX_AFS_INT32 / mult || value < MIN_AFS_INT32 / mult) + return -1; + + *aval = value * mult; + + return 0; +} diff --git a/src/venus/fs.c b/src/venus/fs.c index 8a93420c3..115c694ed 100644 --- a/src/venus/fs.c +++ b/src/venus/fs.c @@ -1399,7 +1399,7 @@ SetVolCmd(struct cmd_syndesc *as, void *arock) status->MinQuota = status->MaxQuota = -1; offmsg = NULL; if (as->parms[1].items) { - code = util_GetInt32(as->parms[1].items->data, &status->MaxQuota); + code = util_GetHumanInt32(as->parms[1].items->data, &status->MaxQuota); if (code) { fprintf(stderr, "%s: bad integer specified for quota.\n", pn); error = 1; @@ -2106,7 +2106,7 @@ SetCacheSizeCmd(struct cmd_syndesc *as, void *arock) return 1; } if (as->parms[0].items) { - code = util_GetInt32(as->parms[0].items->data, &temp); + code = util_GetHumanInt32(as->parms[0].items->data, &temp); if (code) { fprintf(stderr, "%s: bad integer specified for cache size.\n", pn); diff --git a/src/volser/vos.c b/src/volser/vos.c index 1be394e8d..2078e1989 100644 --- a/src/volser/vos.c +++ b/src/volser/vos.c @@ -1691,7 +1691,7 @@ SetFields(register struct cmd_syndesc *as, void *arock) if (as->parms[1].items) { /* -max */ - code = util_GetInt32(as->parms[1].items->data, &info.maxquota); + code = util_GetHumanInt32(as->parms[1].items->data, &info.maxquota); if (code) { fprintf(STDERR, "invalid quota value\n"); return code; @@ -1902,13 +1902,7 @@ CreateVolume(register struct cmd_syndesc *as, void *arock) } if (as->parms[3].items) { - if (!IsNumeric(as->parms[3].items->data)) { - fprintf(STDERR, "Initial quota %s should be numeric.\n", - as->parms[3].items->data); - return EINVAL; - } - - code = util_GetInt32(as->parms[3].items->data, "a); + code = util_GetHumanInt32(as->parms[3].items->data, "a); if (code) { fprintf(STDERR, "vos: bad integer specified for quota.\n"); return code; -- 2.39.5