View | Details | Raw Unified | Return to bug 216450
Collapse All | Expand All

(-)Sysctl.xs (-125 / +153 lines)
Lines 14-19 Link Here
14
14
15
#include <stdio.h>
15
#include <stdio.h>
16
#include <sys/types.h>
16
#include <sys/types.h>
17
#include <sys/cdefs.h>
17
#include <sys/sysctl.h>
18
#include <sys/sysctl.h>
18
19
19
#include <sys/time.h>       /* struct clockinfo */
20
#include <sys/time.h>       /* struct clockinfo */
Lines 48-125 Link Here
48
#include <netinet6/raw_ip6.h>
49
#include <netinet6/raw_ip6.h>
49
#include "bsd-sysctl.h"
50
#include "bsd-sysctl.h"
50
51
52
void
53
_iterator_first(HV *self)
54
{
55
	SV **headp;
56
	int name[CTL_MAXNAME];
57
	size_t len;
58
59
	headp = hv_fetch(self, "head", 4, 0);
60
	if (headp == NULL || *headp == NULL)
61
		croak( "failed to fetch head in _iterator_first()\n" );
62
63
	if (SvPOK(*headp)) {
64
		/* we were given starting node */
65
		len = sizeof(name);
66
		if (sysctlnametomib(SvPV_nolen(*headp), name, &len) == -1)
67
			croak("sysctlnametomib(head) failed in _iterator_first\n");
68
	} else {
69
		/* start at the top like sysctl -a */
70
		name[0] = 1;
71
		len = 1;
72
	}
73
74
	hv_store(self, "_next", 5, newSVpvn((char const *) name, len * sizeof(int)), 0);
75
	hv_store(self, "_len0", 5, newSViv(len), 0);
76
	hv_store(self, "_name", 5, newSVpvn("", 0), 0);
77
}
78
51
int
79
int
52
_init_iterator(HV *self, int *mib, int *miblenp, int valid) {
80
_iterator_next(HV *self)
53
    SV **headp;
81
{
54
    int qoid[CTL_MAXNAME];
82
	SV *nextp, **len0p, *namep;
55
    u_int qoidlen;
83
	int *next, name1[CTL_MAXNAME + 2], name2[CTL_MAXNAME + 2];
56
    SV *clen;
84
	size_t len0, next_len, len1, len2;
57
    SV **clenp;
85
58
    int cmplen;
86
	if (! hv_exists(self, "_len0", 5))
59
    int j;
87
		_iterator_first(self);
60
88
61
    qoid[0] = 0;
89
	len0p = hv_fetch(self, "_len0", 5, 0);
62
    qoid[1] = 2;
90
	if (len0p == NULL || *len0p == NULL)
63
    if (valid) {
91
		croak("hv_fetch(_len0) failed in _iterator_next\n");
64
        memcpy(qoid+2, mib, (*miblenp) * sizeof(int));
92
	len0 = SvIV(*len0p);
65
        qoidlen = *miblenp + 2;
93
	
66
        *miblenp = (CTL_MAXNAME+2) * sizeof(int);
94
	nextp = hv_delete(self, "_next", 5, 0);
67
        clenp = hv_fetch(self, "_len", 4, 0);
95
	if (nextp == NULL)
68
        cmplen = SvIV(*clenp);
96
		return 0;
69
    }
97
	next = (int *) SvPV(nextp, next_len);
70
    else {
98
	next_len /= sizeof(int);
71
        headp = hv_fetch(self, "head", 4, 0);
99
72
        if (!(headp && *headp)) {
100
	namep = hv_delete(self, "_name", 5, 0);
73
            croak( "failed to get some head in _init_iterator()\n" );
101
	if (namep == NULL)
74
        }
102
		return 0;
75
        if (SvPOK(*headp)) {
103
76
            /* begin where asked */
104
	/*
77
            qoidlen = sizeof(qoid);
105
	 * Get next (after _next): name1 = [ 0, 2, next ]
78
            if (sysctlnametomib( SvPV_nolen(*headp), qoid+2, (size_t*)&qoidlen) == -1) {
106
	 */
79
                warn( "_init_iterator(%s): sysctlnametomib lookup failed\n",
107
80
                    SvPV_nolen(*headp)
108
	name1[0] = 0;
81
                );
109
	name1[1] = 2; /* get next */
82
                return 0;
110
	memcpy((name1 + 2), next, next_len * sizeof(int));
83
            }
111
	len1 = next_len + 2;
84
            cmplen = qoidlen;
112
85
            qoidlen += 2;
113
	len2 = sizeof(name2);
86
        }
114
	if (sysctl(name1, len1, name2, &len2, 0, 0) < 0) {
87
        else {
115
		if (errno == ENOENT)
88
            /* begin at the beginning */
116
			return (0);
89
            qoid[2] = 1;
117
90
            cmplen  = 0;
118
		croak("sysctl(next) failed in _iterator_next()\n");
91
            qoidlen = 3;
119
	}
92
        }
120
	len2 /= sizeof(int);
93
        clen = newSViv(cmplen);
121
94
        SvREFCNT_inc(clen);
122
	if (len2 < len0)
95
        hv_store(self, "_len", 4, clen, 0);
123
		return 0; /* shorter than first */
96
    }
124
	if (memcmp(name2, next, len0 * sizeof(int)) != 0)
97
125
		return 0; /* does not match anymore */
98
    /*
126
99
    printf( "next: " );
127
	/* at this point, name2/len2 has next iterator, update _next here */
100
    for (j = 0; j < qoidlen; ++j) {
128
	hv_store(self, "_next", 5, newSVpvn((char const *) name2, len2 * sizeof(int)), 0);
101
        if (j) printf("."); printf("%d", qoid[j]);
129
102
    }
130
	/* 
103
    printf("\n");
131
	 * Get name (from name2): name1 = [ 0, 1, name2 ]
104
    */
132
	 */
105
133
106
    /* load the mib */
134
	name1[0] = 0;
107
    if (sysctl(qoid, qoidlen, mib, (size_t*)miblenp, 0, 0) == -1) {
135
	name1[1] = 1; /* get name */
108
        return 0;
136
	memcpy((name1 + 2), name2, len2 * sizeof(int));
109
    }
137
	len1 = len2 + 2;
110
    *miblenp /= sizeof(int);
138
111
    if (*miblenp < cmplen) {
139
	len2 = sizeof(name2);
112
        return 0 ;
140
	if (sysctl(name1, len1, name2, &len2, 0, 0) < 0) {
113
    }
141
		if (errno == ENOENT)
114
142
			return (0);
115
    for (j = 0; j < cmplen; ++j) {
143
116
        if (mib[j] != qoid[j+2]) {
144
		croak("sysctl(name) failed in _iterator_next()\n");
117
            return 0;
145
	}
118
        }
146
119
    }
147
	/* at this point, name2/len2 has name, update _name here */
120
    return 1;
148
	hv_store(self, "_name", 5, newSVpvn((char const *) name2, len2 - 1), 0);
149
150
	return 1;
121
}
151
}
122
152
153
/*
154
 * The below two comparisons must be true for the 64-bit setting code to
155
 * work correctly.
156
 */
157
_Static_assert(LLONG_MAX >= INT64_MAX, "compile-time assertion failed");
158
_Static_assert(ULLONG_MAX >= UINT64_MAX, "compile-time assertion failed");
159
123
MODULE = BSD::Sysctl   PACKAGE = BSD::Sysctl
160
MODULE = BSD::Sysctl   PACKAGE = BSD::Sysctl
124
161
125
PROTOTYPES: ENABLE
162
PROTOTYPES: ENABLE
Lines 127-193 Link Here
127
SV *
164
SV *
128
next (SV *refself)
165
next (SV *refself)
129
    INIT:
166
    INIT:
130
        int mib[CTL_MAXNAME+2];
131
        size_t miblen;
132
        int qoid[CTL_MAXNAME+2];
133
        size_t qoidlen;
134
        char name[BUFSIZ];
135
        size_t namelen;
136
        HV *self;
167
        HV *self;
137
        SV **ctxp;
168
        SV **namep;
138
        SV *ctx;
139
        SV *cname;
140
        int j;
141
        int *p;
142
169
143
    CODE:
170
    CODE:
144
        self = (HV *)SvRV(refself);
171
        self = (HV *)SvRV(refself);
145
        if ((ctxp = hv_fetch(self, "_ctx", 4, 0))) {
146
            p = (int *)SvPVX(*ctxp);
147
            miblen = *p++;
148
            memcpy(mib, p, miblen * sizeof(int));
149
150
            if (!_init_iterator(self, mib, (int*)&miblen, 1)) {
151
                XSRETURN_UNDEF;
152
            }
153
        }
154
        else {
155
            miblen = sizeof(mib)/sizeof(mib[0]);
156
            if (!_init_iterator(self, mib, (int*)&miblen, 0)) {
157
                XSRETURN_UNDEF;
158
            }
159
        }
160
161
        qoid[0] = 0;
162
        qoid[1] = 1;
163
        memcpy(qoid+2, mib, miblen * sizeof(int));
164
        qoidlen = miblen + 2;
165
166
        bzero(name, BUFSIZ);
167
        namelen = sizeof(name);
168
        j = sysctl(qoid, qoidlen, name, &namelen, 0, 0);
169
        if (j || !namelen) {
170
            warn("next(): sysctl name failure %d %zu %d", j, namelen, errno);
171
            XSRETURN_UNDEF;
172
        }
173
        cname = newSVpvn(name, namelen-1);
174
        SvREFCNT_inc(cname);
175
        hv_store(self, "_name", 5, cname, 0);
176
        RETVAL = cname;
177
178
        /* reuse qoid to build context store
179
         *  - the length of the mib
180
         *  - followed by the mib values
181
         * and copy to an SV to save in the self hash
182
         */
183
        p = qoid;
184
        memcpy(p++, (const void *)&miblen, sizeof(int));
185
        memcpy(p, (const void *)mib, miblen * sizeof(int));
186
187
        ctx = newSVpvn((const char *)qoid, (miblen+1) * sizeof(int));
188
        SvREFCNT_inc(ctx);
189
        hv_store(self, "_ctx", 4, ctx, 0);
190
172
173
	if (_iterator_next(self) == 0)
174
		XSRETURN_UNDEF;
175
	
176
	namep = hv_fetch(self, "_name", 5, 0);
177
	SvREFCNT_inc(*namep);
178
	RETVAL = *namep;
191
    OUTPUT:
179
    OUTPUT:
192
        RETVAL
180
        RETVAL
193
181
Lines 878-883 Link Here
878
        SV **oidp;
866
        SV **oidp;
879
        SV *oid;
867
        SV *oid;
880
        char *oid_data;
868
        char *oid_data;
869
        int64_t int64val;
870
        long long llval;
871
        uint64_t uint64val;
872
        unsigned long long ullval;
881
        int oid_fmt;
873
        int oid_fmt;
882
        int oid_len;
874
        int oid_len;
883
        int intval;
875
        int intval;
Lines 955-960 Link Here
955
            newval  = &ulongval;
947
            newval  = &ulongval;
956
            newsize = sizeof(ulongval);
948
            newsize = sizeof(ulongval);
957
            break;
949
            break;
950
951
        case FMT_64:
952
            llval = strtoll(value, &endconvptr, 0);
953
            if (endconvptr == value || *endconvptr != '\0' ||
954
                (llval == 0 && errno == EINVAL)) {
955
                warn("invalid 64-bit integer: '%s'", value);
956
                XSRETURN_UNDEF;
957
            }
958
#if (LLONG_MAX > INT64_MAX)
959
            if (llval < INT64_MIN)
960
                int64val = INT64_MIN;
961
            else if (llval > INT64_MAX)
962
                int64val = INT64_MAX;
963
            else
964
#endif
965
                int64val = (int64_t)llval;
966
            newval  = &int64val;
967
            newsize = sizeof(int64val);
968
            break;
969
970
        case FMT_U64:
971
            ullval = strtoull(value, &endconvptr, 0);
972
            if (endconvptr == value || *endconvptr != '\0' ||
973
                (ullval == 0 && errno == EINVAL)) {
974
                warn("invalid unsigned 64-bit integer: '%s'", value);
975
                XSRETURN_UNDEF;
976
            }
977
#if (ULLONG_MAX > UINT64_MAX)
978
            if (ullval > UINT64_MAX)
979
                uint64val = UINT64_MAX;
980
            else
981
#endif
982
                uint64val = (uint64_t)ullval;
983
            newval  = &uint64val;
984
            newsize = sizeof(uint64val);
985
            break;
958
        }
986
        }
959
        
987
        
960
        if (sysctl((int *)oid_data, oid_len, 0, 0, newval, newsize) == -1) {
988
        if (sysctl((int *)oid_data, oid_len, 0, 0, newval, newsize) == -1) {

Return to bug 216450