Skip to content

Commit

Permalink
Fix macOS sysctl size_t parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
dbwiddis committed May 26, 2021
1 parent f89905a commit 83c67e1
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 32 deletions.
56 changes: 40 additions & 16 deletions contrib/platform/src/com/sun/jna/platform/mac/SystemB.java
Original file line number Diff line number Diff line change
Expand Up @@ -623,10 +623,10 @@ class Timezone extends Structure {
* The sysctl() function retrieves system information and allows processes with
* appropriate privileges to set system information. The information available
* from sysctl() consists of integers, strings, and tables.
*
* <p>
* The state is described using a "Management Information Base" (MIB) style
* name, listed in name, which is a namelen length array of integers.
*
* <p>
* The information is copied into the buffer specified by oldp. The size of the
* buffer is given by the location specified by oldlenp before the call, and
* that location gives the amount of data copied after a successful call and
Expand All @@ -635,32 +635,41 @@ class Timezone extends Structure {
* as much data as fits in the buffer provided and returns with the error code
* ENOMEM. If the old value is not desired, oldp and oldlenp should be set to
* NULL.
*
* <p>
* The size of the available data can be determined by calling sysctl() with the
* NULL argument for oldp. The size of the available data will be returned in
* the location pointed to by oldlenp. For some operations, the amount of space
* may change often. For these operations, the system attempts to round up so
* that the returned size is large enough for a call to return the data shortly
* thereafter.
*
* <p>
* To set a new value, newp is set to point to a buffer of length newlen from
* which the requested value is to be taken. If a new value is not to be set,
* newp should be set to NULL and newlen set to 0.
*
* @param name
* MIB array of integers
* a Management Information Base (MIB) array of integers
* @param namelen
* length of the MIB array
* the length of the array in {@code name}
* @param oldp
* Information retrieved
* A buffer to hold the information retrieved
* @param oldlenp
* Size of information retrieved
* Size of the buffer, a pointer to a {@link size_t} value
* @param newp
* Information to be written
* To set a new value, a buffer of information to be written. May be
* null if no value is to be set.
* @param newlen
* Size of information to be written
* Size of the information to be written. May be 0 if no value is to
* be set.
* @return 0 on success; sets errno on failure
*/
int sysctl(int[] name, int namelen, Pointer oldp, Pointer oldlenp, Pointer newp, size_t newlen);

/**
* @deprecated Use
* {@link #sysctl(int[], int, Pointer, Pointer, Pointer, com.sun.jna.platform.unix.LibCAPI.size_t)}
*/
@Deprecated
int sysctl(int[] name, int namelen, Pointer oldp, IntByReference oldlenp, Pointer newp, int newlen);

/**
Expand All @@ -671,15 +680,24 @@ class Timezone extends Structure {
* @param name
* ASCII representation of the MIB name
* @param oldp
* Information retrieved
* A buffer to hold the information retrieved
* @param oldlenp
* Size of information retrieved
* Size of the buffer, a pointer to a {@link size_t} value
* @param newp
* Information to be written
* To set a new value, a buffer of information to be written. May be
* null if no value is to be set.
* @param newlen
* Size of information to be written
* Size of the information to be written. May be 0 if no value is to
* be set.
* @return 0 on success; sets errno on failure
*/
int sysctlbyname(String name, Pointer oldp, Pointer oldlenp, Pointer newp, size_t newlen);

/**
* @deprecated Use
* {@link #sysctlbyname(String, Pointer, Pointer, Pointer, com.sun.jna.platform.unix.LibCAPI.size_t)}
*/
@Deprecated
int sysctlbyname(String name, Pointer oldp, IntByReference oldlenp, Pointer newp, int newlen);

/**
Expand All @@ -705,12 +723,18 @@ class Timezone extends Structure {
* ASCII representation of the name
* @param mibp
* Integer array containing the corresponding name vector.
* @param size
* @param sizep
* On input, number of elements in the returned array; on output, the
* number of entries copied.
* @return 0 on success; sets errno on failure
*/
int sysctlnametomib(String name, Pointer mibp, IntByReference size);
int sysctlnametomib(String name, Pointer mibp, Pointer sizep);

/**
* @deprecated Use {@link #sysctlnametomib(String, Pointer, Pointer)}
*/
@Deprecated
int sysctlnametomib(String name, Pointer mibp, IntByReference sizep);

/**
* The host_processor_info function returns information about processors.
Expand Down
50 changes: 34 additions & 16 deletions contrib/platform/test/com/sun/jna/platform/mac/SystemBTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import com.sun.jna.ptr.PointerByReference;

import junit.framework.TestCase;

import static com.sun.jna.platform.unix.LibCAPI.size_t;
/**
* Exercise the {@link SystemB} class.
*/
Expand All @@ -64,33 +64,51 @@ public void testSysctl() {
final String mibName = "hw.logicalcpu";
final int nCpu = Runtime.getRuntime().availableProcessors();

IntByReference size = new IntByReference(SystemB.INT_SIZE);
Pointer p = new Memory(size.getValue());
int ret = SystemB.INSTANCE.sysctlbyname(mibName, p, size, null, 0);
size_t size = new size_t(Integer.BYTES);
Pointer p = new Memory(size.longValue());
// plen would be easier with a size_tByReference
Pointer plen = new Memory(Native.SIZE_T_SIZE);
if (Native.SIZE_T_SIZE > 4) {
plen.setLong(0, size.longValue());
} else {
plen.setInt(0, size.intValue());
}
int ret = SystemB.INSTANCE.sysctlbyname(mibName, p, plen, null, size_t.ZERO);
assertEquals(ret, 0);
// These values should be equal unless affinity is set, limiting nCpu
assertTrue(p.getInt(0) >= nCpu);

size = new IntByReference();
ret = SystemB.INSTANCE.sysctlnametomib(mibName, null, size);
size = new size_t(Integer.BYTES);
// sizep and sizepval would be easier with a size_tByReference
Pointer sizep = new Memory(Native.SIZE_T_SIZE);
ret = SystemB.INSTANCE.sysctlnametomib(mibName, null, sizep);
assertEquals(ret, 0);
// Size should be 2
assertEquals(size.getValue(), 2);
// Array size should be 2
int sizepval = Native.SIZE_T_SIZE > 4 ? (int) sizep.getLong(0) : sizep.getInt(0);
assertEquals(sizepval, 2);

Pointer mibp = new Memory(size.getValue() * SystemB.INT_SIZE);
ret = SystemB.INSTANCE.sysctlnametomib(mibName, mibp, size);
Pointer mibp = new Memory(sizepval * SystemB.INT_SIZE);
ret = SystemB.INSTANCE.sysctlnametomib(mibName, mibp, sizep);
assertEquals(ret, 0);
// Size should be 2
assertEquals(size.getValue(), 2);
// Array size should still be 2
sizepval = Native.SIZE_T_SIZE > 4 ? (int) sizep.getLong(0) : sizep.getInt(0);
assertEquals(sizepval, 2);

int[] mib = mibp.getIntArray(0, size.getValue());
int[] mib = mibp.getIntArray(0, sizepval);
// mib should be { 6, 103(?) }
assertEquals(mib.length, 2);
assertEquals(mib[0], 6);

size = new IntByReference(SystemB.INT_SIZE);
p = new Memory(size.getValue());
ret = SystemB.INSTANCE.sysctl(mib, mib.length, p, size, null, 0);
size = new size_t(Integer.BYTES);
p = new Memory(size.longValue());
// plen would be easier with a size_tByReference
plen = new Memory(Native.SIZE_T_SIZE);
if (Native.SIZE_T_SIZE > 4) {
plen.setLong(0, size.longValue());
} else {
plen.setInt(0, size.intValue());
}
ret = SystemB.INSTANCE.sysctl(mib, mib.length, p, plen, null, size_t.ZERO);
assertTrue(p.getInt(0) >= nCpu);
}

Expand Down

0 comments on commit 83c67e1

Please sign in to comment.