util: check for trailing characters in partition names
[openafs.git] / src / util / volparse.c
index 1b69509..79004fe 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
+#include <roken.h>
+
+#include "afsutil.h"
 
-#include <string.h>
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+/* maximum number of partitions - must match vol/voldefs.h */
+#define VOLMAXPARTS 255
 
 /**
  * map a partition id from any partition-style name.
@@ -33,7 +32,7 @@ RCSID
 afs_int32
 volutil_GetPartitionID(char *aname)
 {
-    register char tc;
+    char tc;
     afs_int32 temp;
     char ascii[3];
 
@@ -44,11 +43,11 @@ volutil_GetPartitionID(char *aname)
     if (tc >= '0' && tc <= '9') {
        temp = atoi(aname);
        /* this next check is to make the syntax less ambiguous when discriminating
-        * between volume numbers and partition IDs.  This less things like
-        * bos salvage do some reasonability checks its input w/o checking
+        * between volume numbers and partition IDs.  This lets things like
+        * bos salvage do some reasonability checks on its input w/o checking
         * to see if the partition is really on the server.
         */
-       if (temp < 0 || temp > 25)
+       if (temp < 0 || temp >= VOLMAXPARTS)
            return -1;
        else
            return temp;
@@ -58,9 +57,11 @@ volutil_GetPartitionID(char *aname)
     if (strlen(aname) <= 2) {
        strcpy(ascii, aname);
     } else if (!strncmp(aname, "/vicep", 6)) {
-       strncpy(ascii, aname + 6, 2);
+       if(strlcpy(ascii, aname + 6, sizeof(ascii)) >= sizeof(ascii))
+           return -1;  /* bad partition name: trailing characters */
     } else if (!strncmp(aname, "vicep", 5)) {
-       strncpy(ascii, aname + 5, 2);
+       if(strlcpy(ascii, aname + 5, sizeof(ascii)) >= sizeof(ascii))
+           return -1;  /* bad partition name: trailing characters */
     } else
        return -1;              /* bad partition name */
     /* now partitions are named /vicepa ... /vicepz, /vicepaa, /vicepab, .../vicepzz,
@@ -76,7 +77,8 @@ volutil_GetPartitionID(char *aname)
            return -1;          /* wrongo */
        if (ascii[1] < 'a' || ascii[1] > 'z')
            return -1;          /* just as bad */
-       return (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
+       temp = (ascii[0] - 'a') * 26 + (ascii[1] - 'a') + 26;
+        return (temp >= VOLMAXPARTS ? -1 : temp);
     }
 }
 
@@ -100,9 +102,9 @@ afs_int32
 volutil_PartitionName2_r(afs_int32 part, char *tbuffer, size_t buflen)
 {
     char tempString[3];
-    register int i;
+    int i;
 
-    if (part < 0 || part >= (26 * 26 + 26)) {
+    if (part < 0 || part >= VOLMAXPARTS) {
        return -2;
     }
 
@@ -186,7 +188,7 @@ volutil_PartitionName(int avalue)
 
 /* is this a digit or a digit-like thing? */
 static int
-ismeta(register int ac, register int abase)
+ismeta(int ac, int abase)
 {
 /*    if (ac == '-' || ac == 'x' || ac == 'X') return 1; */
     if (ac >= '0' && ac <= '7')
@@ -206,7 +208,7 @@ ismeta(register int ac, register int abase)
 
 /* given that this is a digit or a digit-like thing, compute its value */
 static int
-getmeta(register int ac)
+getmeta(int ac)
 {
     if (ac >= '0' && ac <= '9')
        return ac - '0';
@@ -218,10 +220,10 @@ getmeta(register int ac)
 }
 
 afs_int32
-util_GetInt32(register char *as, afs_int32 * aval)
+util_GetInt32(char *as, afs_int32 * aval)
 {
-    register afs_int32 total;
-    register int tc;
+    afs_int32 total;
+    int tc;
     int base;
     int negative;
 
@@ -229,7 +231,7 @@ util_GetInt32(register char *as, afs_int32 * aval)
     negative = 0;
 
     /* skip over leading spaces */
-    while ((tc = *as)) {
+    for (tc = *as; tc !='\0'; as++, tc = *as) {
        if (tc != ' ' && tc != '\t')
            break;
     }
@@ -252,6 +254,127 @@ util_GetInt32(register char *as, afs_int32 * aval)
        base = 10;
 
     /* compute the # itself */
+    for (tc = *as; tc !='\0'; as++, tc = *as) {
+       if (!ismeta(tc, base))
+           return -1;
+       total *= base;
+       total += getmeta(tc);
+    }
+
+    if (negative)
+       *aval = -total;
+    else
+       *aval = total;
+    return 0;
+}
+
+afs_uint32
+util_GetUInt32(char *as, afs_uint32 * aval)
+{
+    afs_uint32 total;
+    int tc;
+    int base;
+
+    total = 0;                 /* initialize things */
+
+    /* skip over leading spaces */
+    for (tc = *as; tc !='\0'; as++, tc = *as) {
+       if (tc != ' ' && tc != '\t')
+           break;
+    }
+
+    /* compute the base */
+    if (*as == '0') {
+       as++;
+       if (*as == 'x' || *as == 'X') {
+           base = 16;
+           as++;
+       } else
+           base = 8;
+    } else
+       base = 10;
+
+    /* compute the # itself */
+    for (tc = *as; tc !='\0'; as++, tc = *as) {
+       if (!ismeta(tc, base))
+           return -1;
+       total *= base;
+       total += getmeta(tc);
+    }
+
+    *aval = total;
+    return 0;
+}
+
+static const char power_letter[] = {
+    'K',  /* kibi */
+    'M',  /* mebi */
+    'G',  /* gibi */
+    'T',  /* tebi */
+};
+
+afs_int32
+util_GetHumanInt32(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;
+}
+
+afs_int32
+util_GetInt64(char *as, afs_int64 * aval)
+{
+    afs_int64 total;
+    int tc;
+    int base;
+    int negative;
+
+    total = 0; /* initialize things */
+    negative = 0;
+
+    /* skip over leading spaces */
+    while ((tc = *as)) {
+       if (tc != ' ' && tc != '\t')
+           break;
+    }
+
+    /* compute sign */
+    if (*as == '-') {
+       negative = 1;
+       as++; /* skip over character */
+    }
+
+    /* compute the base */
+    if (*as == '0') {
+       as++;
+       if (*as == 'x' || *as == 'X') {
+           base = 16;
+           as++;
+       } else
+           base = 8;
+    } else
+       base = 10;
+
+    /* compute the # itself */
     while ((tc = *as)) {
        if (!ismeta(tc, base))
            return -1;
@@ -268,13 +391,13 @@ util_GetInt32(register char *as, afs_int32 * aval)
 }
 
 afs_uint32
-util_GetUInt32(register char *as, afs_uint32 * aval)
+util_GetUInt64(char *as, afs_uint64 * aval)
 {
-    register afs_uint32 total;
-    register int tc;
+    afs_uint64 total;
+    int tc;
     int base;
 
-    total = 0;                 /* initialize things */
+    total = 0; /* initialize things */
 
     /* skip over leading spaces */
     while ((tc = *as)) {