Allow passing in human-readable units for specifying amounts of space
authorEvan Broder <broder@mit.edu>
Wed, 25 Mar 2009 23:18:09 +0000 (18:18 -0500)
committerJeffrey Altman <jaltman@openafs.org>
Mon, 13 Jul 2009 21:42:34 +0000 (15:42 -0600)
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 <marc.c.dionne@gmail.com>
Reviewed-by: Russ Allbery <rra@stanford.edu>
Verified-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>

src/WINNT/afsd/fs.c
src/config/stds.h
src/util/afsutil_prototypes.h
src/util/volparse.c
src/venus/fs.c
src/volser/vos.c

index 790a455..3058a0b 100644 (file)
@@ -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;
index 5995aae..f451b16 100644 (file)
@@ -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;
index 589da52..9d0645d 100644 (file)
@@ -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 */
 
index 72bee5e..6ba1892 100644 (file)
@@ -11,6 +11,7 @@
 #include <afs/param.h>
 
 #include <string.h>
+#include <errno.h>
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #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;
+}
index 8a93420..115c694 100644 (file)
@@ -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);
index 1be394e..2078e19 100644 (file)
@@ -1691,7 +1691,7 @@ SetFields(register struct cmd_syndesc *as, void *arock)
 
     if (as->parms[1].items) {
        /* -max <quota> */
-       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, &quota);
+       code = util_GetHumanInt32(as->parms[3].items->data, &quota);
        if (code) {
            fprintf(STDERR, "vos: bad integer specified for quota.\n");
            return code;