tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: strtonum(3) from OpenBSD?



On Tue, 23 Jun 2009, Marc Balmer wrote:

> Yes, already more than one program apparently use it.

For instance bioctl(8) uses (an internal version of) it but weirdly even
though strtoul() is considered difficult and unsafe, it uses that also..?

(perhaps you can tell, I don't really like this function, patch below to
remove it from bioctl :)

iain

Index: Makefile
===================================================================
RCS file: /cvsroot/src/sbin/bioctl/Makefile,v
retrieving revision 1.4
diff -u -r1.4 Makefile
--- Makefile    11 Apr 2009 07:58:11 -0000      1.4
+++ Makefile    23 Jun 2009 17:21:30 -0000
@@ -1,7 +1,7 @@
 #      $NetBSD: Makefile,v 1.4 2009/04/11 07:58:11 lukem Exp $

 PROG=  bioctl
-SRCS=   bioctl.c strtonum.c
+SRCS=   bioctl.c
 MAN=   bioctl.8

 .include <bsd.prog.mk>
Index: bioctl.c
===================================================================
RCS file: /cvsroot/src/sbin/bioctl/bioctl.c,v
retrieving revision 1.12
diff -u -r1.12 bioctl.c
--- bioctl.c    18 Jan 2009 00:27:59 -0000      1.12
+++ bioctl.c    23 Jun 2009 17:21:30 -0000
@@ -51,7 +51,6 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <util.h>
-#include "strtonum.h"

 struct command {
        const char *cmd_name;
@@ -94,7 +93,7 @@
 #endif
 static void    bio_volops_remove(int, int, char **);

-static const char *str2locator(const char *, struct locator *);
+static int     str2locator(const char *, struct locator *);

 static struct bio_locate bl;
 static struct command commands[] = {
@@ -199,34 +198,44 @@
        /* NOTREACHED */
 }

-static const char *
+/*
+ * locator is "channel:target[.lun]" where each of channel, target
+ * and lun are unsigned values in the range 0-256
+ */
+static int
 str2locator(const char *string, struct locator *location)
 {
-       const char      *errstr;
-       char            parse[80], *targ, *lun;
+       unsigned long   n;
+       char    *ep;

-       strlcpy(parse, string, sizeof parse);
-       targ = strchr(parse, ':');
-       if (targ == NULL)
-               return "target not specified";
-
-       *targ++ = '\0';
-       lun = strchr(targ, '.');
-       if (lun != NULL) {
-               *lun++ = '\0';
-               location->lun = strtonum(lun, 0, 256, &errstr);
-               if (errstr)
-                       return errstr;
-       } else
+       if (string == NULL)
+               return 0;
+
+       n = strtoul(string, &ep, 10);
+       if (string[0] == '\0' || *ep != ':' || n > 256)
+               return 0;
+
+       location->channel = (int)n;
+
+       string = ep + 1;
+       n = strtoul(string, &ep, 10);
+       if (string[0] == '\0' || (*ep != '\0' && *ep != '.') || n > 256)
+               return 0;
+
+       location->target = (int)n;
+
+       if (*ep == '\0') {
                location->lun = 0;
+       } else {
+               string = ep + 1;
+               n = strtoul(string, &ep, 10);
+               if (string[0] == '\0' || *ep != '\0' || n > 256)
+                       return 0;
+
+               location->lun = (int)n;
+       }

-       location->target = strtonum(targ, 0, 256, &errstr);
-       if (errstr)
-               return errstr;
-       location->channel = strtonum(parse, 0, 256, &errstr);
-       if (errstr)
-               return errstr;
-       return NULL;
+       return 1;
 }

 /*
@@ -663,14 +672,12 @@
 bio_setstate_common(int fd, char *arg, struct bioc_setstate *bs,
                    struct locator *location)
 {
-       const char              *errstr;

        if (!arg || !location)
                goto send;

-       errstr = str2locator(arg, location);
-       if (errstr)
-               errx(EXIT_FAILURE, "Target %s: %s", arg, errstr);
+       if (!str2locator(arg, location))
+               errx(EXIT_FAILURE, "Invalid target %s", arg);

        bs->bs_channel = location->channel;
        bs->bs_target = location->target;
@@ -695,7 +702,6 @@
        struct locator          location;
        uint64_t                total_size = 0, disksize = 0;
        int64_t                 volsize = 0;
-       const char              *errstr;
        char                    *endptr, *stripe, levelstr[32];
        char                    *scsiname, *raid_level, size[64];
        int                     disk_first = 0, disk_end = 0;
@@ -745,9 +751,8 @@
        if (*endptr != '\0')
                errx(EXIT_FAILURE, "Invalid RAID_LEVEL value");

-       errstr = str2locator(scsiname, &location);
-       if (errstr)
-               errx(EXIT_FAILURE, "Target %s: %s", scsiname, errstr);
+       if (!str2locator(scsiname, &location))
+               errx(EXIT_FAILURE, "Invalid target %s", scsiname);

        /*
         * Parse the device list that will be used for the volume,
@@ -899,7 +904,6 @@
 {
        struct bioc_volops      bc;
        struct locator          location;
-       const char              *errstr;
        char                    *endptr;

        if (argc != 3 || strcmp(argv[0], "volume") != 0)
@@ -913,9 +917,8 @@
        if (*endptr != '\0')
                errx(EXIT_FAILURE, "Invalid Volume ID value");

-       errstr = str2locator(argv[2], &location);
-       if (errstr)
-               errx(EXIT_FAILURE, "Target %s: %s", argv[2], errstr);
+       if (!str2locator(argv[2], &location))
+               errx(EXIT_FAILURE, "Invalid target %s", argv[2]);

        bc.bc_channel = location.channel;
        bc.bc_target = location.target;
@@ -939,7 +942,6 @@
        struct bioc_vol         bv;
        struct bioc_disk        bd;
        struct bioc_blink       bb;
-       const char              *errstr;
        int                     v, d, rv, blink = 0;

        if (argc != 2)
@@ -952,9 +954,8 @@
        else
                usage();

-       errstr = str2locator(argv[1], &location);
-       if (errstr)
-               errx(EXIT_FAILURE, "Target %s: %s", argv[1], errstr);
+       if (!str2locator(argv[1], &location))
+               errx(EXIT_FAILURE, "Invalid target %s", argv[1]);

        /* try setting blink on the device directly */
        memset(&bb, 0, sizeof(bb));
Index: strtonum.c
===================================================================
RCS file: strtonum.c
diff -N strtonum.c
--- strtonum.c  1 May 2007 17:18:54 -0000       1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,72 +0,0 @@
-/*     $NetBSD: strtonum.c,v 1.1 2007/05/01 17:18:54 bouyer Exp $ */
-/*     $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $    */
-
-/*
- * Copyright (c) 2004 Ted Unangst and Todd Miller
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <sys/cdefs.h>
-
-#ifndef lint
-__RCSID("$NetBSD: strtonum.c,v 1.1 2007/05/01 17:18:54 bouyer Exp $");
-#endif
-
-#include <errno.h>
-#include <limits.h>
-#include <stdlib.h>
-#include "strtonum.h"
-
-#define INVALID        1
-#define TOOSMALL       2
-#define TOOLARGE       3
-
-long long
-strtonum(const char *numstr, long long minval, long long maxval,
-    const char **errstrp)
-{
-       long long ll = 0;
-       char *ep;
-       int error = 0;
-       struct errval {
-               const char *errstr;
-               int err;
-       } ev[4] = {
-               { NULL,         0 },
-               { "invalid",    EINVAL },
-               { "too small",  ERANGE },
-               { "too large",  ERANGE },
-       };
-
-       ev[0].err = errno;
-       errno = 0;
-       if (minval > maxval)
-               error = INVALID;
-       else {
-               ll = strtoll(numstr, &ep, 10);
-               if (numstr == ep || *ep != '\0')
-                       error = INVALID;
-               else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
-                       error = TOOSMALL;
-               else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
-                       error = TOOLARGE;
-       }
-       if (errstrp != NULL)
-               *errstrp = ev[error].errstr;
-       errno = ev[error].err;
-       if (error)
-               ll = 0;
-
-       return (ll);
-}
Index: strtonum.h
===================================================================
RCS file: strtonum.h
diff -N strtonum.h
--- strtonum.h  1 May 2007 17:18:54 -0000       1.1
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,4 +0,0 @@
-/* $NetBSD: strtonum.h,v 1.1 2007/05/01 17:18:54 bouyer Exp $ */
-
-long long strtonum(const char *, long long, long long, const char **);
-


Home | Main Index | Thread Index | Old Index