Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Jul 2017 13:45:34 +0000 (UTC)
From:      Steve Wills <swills@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r445326 - in head/sysutils/p5-BSD-Sysctl: . files
Message-ID:  <201707081345.v68DjYBP020296@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: swills
Date: Sat Jul  8 13:45:34 2017
New Revision: 445326
URL: https://svnweb.freebsd.org/changeset/ports/445326

Log:
  sysutils/p5-BSD-Sysctl: Support setting 64-bit sysctl values
  
  PR:		216450
  Submitted by:	jtl
  Approved by:	david@landgren.net (maintainer timeout, 5 months)

Added:
  head/sysutils/p5-BSD-Sysctl/files/
  head/sysutils/p5-BSD-Sysctl/files/patch-Sysctl.xs   (contents, props changed)
Modified:
  head/sysutils/p5-BSD-Sysctl/Makefile

Modified: head/sysutils/p5-BSD-Sysctl/Makefile
==============================================================================
--- head/sysutils/p5-BSD-Sysctl/Makefile	Sat Jul  8 13:10:42 2017	(r445325)
+++ head/sysutils/p5-BSD-Sysctl/Makefile	Sat Jul  8 13:45:34 2017	(r445326)
@@ -3,7 +3,7 @@
 
 PORTNAME=	BSD-Sysctl
 PORTVERSION=	0.11
-PORTREVISION=	1
+PORTREVISION=	2
 CATEGORIES=	sysutils perl5
 MASTER_SITES=	CPAN
 PKGNAMEPREFIX=	p5-

Added: head/sysutils/p5-BSD-Sysctl/files/patch-Sysctl.xs
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sysutils/p5-BSD-Sysctl/files/patch-Sysctl.xs	Sat Jul  8 13:45:34 2017	(r445326)
@@ -0,0 +1,319 @@
+--- Sysctl.xs.orig	2014-01-21 23:02:47 UTC
++++ Sysctl.xs
+@@ -14,6 +14,7 @@
+ 
+ #include <stdio.h>
+ #include <sys/types.h>
++#include <sys/cdefs.h>
+ #include <sys/sysctl.h>
+ 
+ #include <sys/time.h>       /* struct clockinfo */
+@@ -48,78 +49,114 @@
+ #include <netinet6/raw_ip6.h>
+ #include "bsd-sysctl.h"
+ 
++void
++_iterator_first(HV *self)
++{
++	SV **headp;
++	int name[CTL_MAXNAME];
++	size_t len;
++
++	headp = hv_fetch(self, "head", 4, 0);
++	if (headp == NULL || *headp == NULL)
++		croak( "failed to fetch head in _iterator_first()\n" );
++
++	if (SvPOK(*headp)) {
++		/* we were given starting node */
++		len = sizeof(name);
++		if (sysctlnametomib(SvPV_nolen(*headp), name, &len) == -1)
++			croak("sysctlnametomib(head) failed in _iterator_first\n");
++	} else {
++		/* start at the top like sysctl -a */
++		name[0] = 1;
++		len = 1;
++	}
++
++	hv_store(self, "_next", 5, newSVpvn((char const *) name, len * sizeof(int)), 0);
++	hv_store(self, "_len0", 5, newSViv(len), 0);
++	hv_store(self, "_name", 5, newSVpvn("", 0), 0);
++}
++
+ int
+-_init_iterator(HV *self, int *mib, int *miblenp, int valid) {
+-    SV **headp;
+-    int qoid[CTL_MAXNAME];
+-    u_int qoidlen;
+-    SV *clen;
+-    SV **clenp;
+-    int cmplen;
+-    int j;
++_iterator_next(HV *self)
++{
++	SV *nextp, **len0p, *namep;
++	int *next, name1[CTL_MAXNAME + 2], name2[CTL_MAXNAME + 2];
++	size_t len0, next_len, len1, len2;
+ 
+-    qoid[0] = 0;
+-    qoid[1] = 2;
+-    if (valid) {
+-        memcpy(qoid+2, mib, (*miblenp) * sizeof(int));
+-        qoidlen = *miblenp + 2;
+-        *miblenp = (CTL_MAXNAME+2) * sizeof(int);
+-        clenp = hv_fetch(self, "_len", 4, 0);
+-        cmplen = SvIV(*clenp);
+-    }
+-    else {
+-        headp = hv_fetch(self, "head", 4, 0);
+-        if (!(headp && *headp)) {
+-            croak( "failed to get some head in _init_iterator()\n" );
+-        }
+-        if (SvPOK(*headp)) {
+-            /* begin where asked */
+-            qoidlen = sizeof(qoid);
+-            if (sysctlnametomib( SvPV_nolen(*headp), qoid+2, (size_t*)&qoidlen) == -1) {
+-                warn( "_init_iterator(%s): sysctlnametomib lookup failed\n",
+-                    SvPV_nolen(*headp)
+-                );
+-                return 0;
+-            }
+-            cmplen = qoidlen;
+-            qoidlen += 2;
+-        }
+-        else {
+-            /* begin at the beginning */
+-            qoid[2] = 1;
+-            cmplen  = 0;
+-            qoidlen = 3;
+-        }
+-        clen = newSViv(cmplen);
+-        SvREFCNT_inc(clen);
+-        hv_store(self, "_len", 4, clen, 0);
+-    }
++	if (! hv_exists(self, "_len0", 5))
++		_iterator_first(self);
+ 
+-    /*
+-    printf( "next: " );
+-    for (j = 0; j < qoidlen; ++j) {
+-        if (j) printf("."); printf("%d", qoid[j]);
+-    }
+-    printf("\n");
+-    */
++	len0p = hv_fetch(self, "_len0", 5, 0);
++	if (len0p == NULL || *len0p == NULL)
++		croak("hv_fetch(_len0) failed in _iterator_next\n");
++	len0 = SvIV(*len0p);
++	
++	nextp = hv_delete(self, "_next", 5, 0);
++	if (nextp == NULL)
++		return 0;
++	next = (int *) SvPV(nextp, next_len);
++	next_len /= sizeof(int);
+ 
+-    /* load the mib */
+-    if (sysctl(qoid, qoidlen, mib, (size_t*)miblenp, 0, 0) == -1) {
+-        return 0;
+-    }
+-    *miblenp /= sizeof(int);
+-    if (*miblenp < cmplen) {
+-        return 0 ;
+-    }
++	namep = hv_delete(self, "_name", 5, 0);
++	if (namep == NULL)
++		return 0;
+ 
+-    for (j = 0; j < cmplen; ++j) {
+-        if (mib[j] != qoid[j+2]) {
+-            return 0;
+-        }
+-    }
+-    return 1;
++	/*
++	 * Get next (after _next): name1 = [ 0, 2, next ]
++	 */
++
++	name1[0] = 0;
++	name1[1] = 2; /* get next */
++	memcpy((name1 + 2), next, next_len * sizeof(int));
++	len1 = next_len + 2;
++
++	len2 = sizeof(name2);
++	if (sysctl(name1, len1, name2, &len2, 0, 0) < 0) {
++		if (errno == ENOENT)
++			return (0);
++
++		croak("sysctl(next) failed in _iterator_next()\n");
++	}
++	len2 /= sizeof(int);
++
++	if (len2 < len0)
++		return 0; /* shorter than first */
++	if (memcmp(name2, next, len0 * sizeof(int)) != 0)
++		return 0; /* does not match anymore */
++
++	/* at this point, name2/len2 has next iterator, update _next here */
++	hv_store(self, "_next", 5, newSVpvn((char const *) name2, len2 * sizeof(int)), 0);
++
++	/* 
++	 * Get name (from name2): name1 = [ 0, 1, name2 ]
++	 */
++
++	name1[0] = 0;
++	name1[1] = 1; /* get name */
++	memcpy((name1 + 2), name2, len2 * sizeof(int));
++	len1 = len2 + 2;
++
++	len2 = sizeof(name2);
++	if (sysctl(name1, len1, name2, &len2, 0, 0) < 0) {
++		if (errno == ENOENT)
++			return (0);
++
++		croak("sysctl(name) failed in _iterator_next()\n");
++	}
++
++	/* at this point, name2/len2 has name, update _name here */
++	hv_store(self, "_name", 5, newSVpvn((char const *) name2, len2 - 1), 0);
++
++	return 1;
+ }
+ 
++/*
++ * The below two comparisons must be true for the 64-bit setting code to
++ * work correctly.
++ */
++_Static_assert(LLONG_MAX >= INT64_MAX, "compile-time assertion failed");
++_Static_assert(ULLONG_MAX >= UINT64_MAX, "compile-time assertion failed");
++
+ MODULE = BSD::Sysctl   PACKAGE = BSD::Sysctl
+ 
+ PROTOTYPES: ENABLE
+@@ -127,67 +164,18 @@ PROTOTYPES: ENABLE
+ SV *
+ next (SV *refself)
+     INIT:
+-        int mib[CTL_MAXNAME+2];
+-        size_t miblen;
+-        int qoid[CTL_MAXNAME+2];
+-        size_t qoidlen;
+-        char name[BUFSIZ];
+-        size_t namelen;
+         HV *self;
+-        SV **ctxp;
+-        SV *ctx;
+-        SV *cname;
+-        int j;
+-        int *p;
++        SV **namep;
+ 
+     CODE:
+         self = (HV *)SvRV(refself);
+-        if ((ctxp = hv_fetch(self, "_ctx", 4, 0))) {
+-            p = (int *)SvPVX(*ctxp);
+-            miblen = *p++;
+-            memcpy(mib, p, miblen * sizeof(int));
+ 
+-            if (!_init_iterator(self, mib, (int*)&miblen, 1)) {
+-                XSRETURN_UNDEF;
+-            }
+-        }
+-        else {
+-            miblen = sizeof(mib)/sizeof(mib[0]);
+-            if (!_init_iterator(self, mib, (int*)&miblen, 0)) {
+-                XSRETURN_UNDEF;
+-            }
+-        }
+-
+-        qoid[0] = 0;
+-        qoid[1] = 1;
+-        memcpy(qoid+2, mib, miblen * sizeof(int));
+-        qoidlen = miblen + 2;
+-
+-        bzero(name, BUFSIZ);
+-        namelen = sizeof(name);
+-        j = sysctl(qoid, qoidlen, name, &namelen, 0, 0);
+-        if (j || !namelen) {
+-            warn("next(): sysctl name failure %d %zu %d", j, namelen, errno);
+-            XSRETURN_UNDEF;
+-        }
+-        cname = newSVpvn(name, namelen-1);
+-        SvREFCNT_inc(cname);
+-        hv_store(self, "_name", 5, cname, 0);
+-        RETVAL = cname;
+-
+-        /* reuse qoid to build context store
+-         *  - the length of the mib
+-         *  - followed by the mib values
+-         * and copy to an SV to save in the self hash
+-         */
+-        p = qoid;
+-        memcpy(p++, (const void *)&miblen, sizeof(int));
+-        memcpy(p, (const void *)mib, miblen * sizeof(int));
+-
+-        ctx = newSVpvn((const char *)qoid, (miblen+1) * sizeof(int));
+-        SvREFCNT_inc(ctx);
+-        hv_store(self, "_ctx", 4, ctx, 0);
+-
++	if (_iterator_next(self) == 0)
++		XSRETURN_UNDEF;
++	
++	namep = hv_fetch(self, "_name", 5, 0);
++	SvREFCNT_inc(*namep);
++	RETVAL = *namep;
+     OUTPUT:
+         RETVAL
+ 
+@@ -878,6 +866,10 @@ _mib_set(const char *arg, const char *value)
+         SV **oidp;
+         SV *oid;
+         char *oid_data;
++        int64_t int64val;
++        long long llval;
++        uint64_t uint64val;
++        unsigned long long ullval;
+         int oid_fmt;
+         int oid_len;
+         int intval;
+@@ -954,6 +946,42 @@ _mib_set(const char *arg, const char *value)
+             }
+             newval  = &ulongval;
+             newsize = sizeof(ulongval);
++            break;
++
++        case FMT_64:
++            llval = strtoll(value, &endconvptr, 0);
++            if (endconvptr == value || *endconvptr != '\0' ||
++                (llval == 0 && errno == EINVAL)) {
++                warn("invalid 64-bit integer: '%s'", value);
++                XSRETURN_UNDEF;
++            }
++#if (LLONG_MAX > INT64_MAX)
++            if (llval < INT64_MIN)
++                int64val = INT64_MIN;
++            else if (llval > INT64_MAX)
++                int64val = INT64_MAX;
++            else
++#endif
++                int64val = (int64_t)llval;
++            newval  = &int64val;
++            newsize = sizeof(int64val);
++            break;
++
++        case FMT_U64:
++            ullval = strtoull(value, &endconvptr, 0);
++            if (endconvptr == value || *endconvptr != '\0' ||
++                (ullval == 0 && errno == EINVAL)) {
++                warn("invalid unsigned 64-bit integer: '%s'", value);
++                XSRETURN_UNDEF;
++            }
++#if (ULLONG_MAX > UINT64_MAX)
++            if (ullval > UINT64_MAX)
++                uint64val = UINT64_MAX;
++            else
++#endif
++                uint64val = (uint64_t)ullval;
++            newval  = &uint64val;
++            newsize = sizeof(uint64val);
+             break;
+         }
+         



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707081345.v68DjYBP020296>