Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define size_t.ByReference and fix macOS sysctl size_t* parameters #1351

Merged
merged 2 commits into from
Jun 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Features
Bug Fixes
---------
* [#1343](https://github.com/java-native-access/jna/issues/1343): `c.s.j.p.mac.CoreFoundation.CFStringRef#stringValue` buffer needs space for a null byte - [@dbwiddis](https://github.com/dbwiddis).
* [#1351](https://github.com/java-native-access/jna/issues/1351): Define `c.s.j.p.unix.size_t.ByReference` and fix macOS sysctl `size_t *` parameters - [@dbwiddis](https://github.com/dbwiddis).

Release 5.8.0
=============
Expand Down
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, size_t.ByReference 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, size_t.ByReference 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, size_t.ByReference 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
29 changes: 28 additions & 1 deletion contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2015 Goldstein Lyor, All Rights Reserved
/* Copyright (c) 2015 Goldstein Lyor, 2021 Daniel Widdis, All Rights Reserved
*
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
Expand Down Expand Up @@ -43,6 +43,33 @@ class size_t extends IntegerType {

private static final long serialVersionUID = 1L;

public static class ByReference extends com.sun.jna.ptr.ByReference {
public ByReference() {
this(0);
}

public ByReference(long value) {
this(new size_t(value));
}

public ByReference(size_t value) {
super(Native.SIZE_T_SIZE);
setValue(value);
}

public void setValue(size_t value) {
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved
if (Native.SIZE_T_SIZE > 4) {
getPointer().setLong(0, value.longValue());
} else {
getPointer().setInt(0, value.intValue());
}
}

public size_t getValue() {
return new size_t(Native.SIZE_T_SIZE > 4 ? getPointer().getLong(0) : getPointer().getInt(0));
}
}

public size_t() {
this(0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.unix.LibCAPI.size_t;
import com.sun.jna.platform.unix.X11.AtomByReference;
import com.sun.jna.platform.unix.X11.WindowByReference;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
Expand Down Expand Up @@ -137,6 +138,9 @@ public void testPlatformToStrings() {
SCODEByReference scodebr = new SCODEByReference(new SCODE(42));
parseAndTest(scodebr.toString(), "SCODE", "42");

size_t.ByReference sizetbr = new size_t.ByReference(42);
parseAndTest(sizetbr.toString(), "size_t", "42");

UINTByReference uibr = new UINTByReference(new UINT(42));
parseAndTest(uibr.toString(), "UINT", "42");

Expand Down
64 changes: 35 additions & 29 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,39 @@ 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);
assertEquals(ret, 0);
// This sysctl returns a 32-bit integer cpu count
size_t size = new size_t(Integer.BYTES);
Pointer p = new Memory(size.longValue());
size_t.ByReference plen = new size_t.ByReference(size);
assertEquals(0, SystemB.INSTANCE.sysctlbyname(mibName, p, plen, null, size_t.ZERO));
// 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);
assertEquals(ret, 0);
// Size should be 2
assertEquals(size.getValue(), 2);

Pointer mibp = new Memory(size.getValue() * SystemB.INT_SIZE);
ret = SystemB.INSTANCE.sysctlnametomib(mibName, mibp, size);
assertEquals(ret, 0);
// Size should be 2
assertEquals(size.getValue(), 2);

int[] mib = mibp.getIntArray(0, size.getValue());
// Get the same value by converting the string to the MIB array
// Get the size of the MIB array
size = new size_t(Integer.BYTES);
size_t.ByReference sizep = new size_t.ByReference(size);
assertEquals(0, SystemB.INSTANCE.sysctlnametomib(mibName, null, sizep));
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved
// Array size should be 2
int sizepval = sizep.getValue().intValue();
assertEquals(2, sizepval);

// Allocate the correct size and fill the MIB array
Pointer mibp = new Memory(sizepval * SystemB.INT_SIZE);
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved
assertEquals(0, SystemB.INSTANCE.sysctlnametomib(mibName, mibp, sizep));
// Array size should still be 2
sizepval = sizep.getValue().intValue();
assertEquals(2, sizepval);

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 = new size_t.ByReference(size);
dbwiddis marked this conversation as resolved.
Show resolved Hide resolved
assertEquals(0, SystemB.INSTANCE.sysctl(mib, mib.length, p, plen, null, size_t.ZERO));
assertTrue(p.getInt(0) >= nCpu);
}

Expand Down Expand Up @@ -257,16 +263,16 @@ public void testStatfs() {
public void testXswUsage() {
XswUsage xswUsage = new XswUsage();
assertEquals(0, SystemB.INSTANCE.sysctlbyname("vm.swapusage", xswUsage.getPointer(),
new IntByReference(xswUsage.size()), null, 0));
new size_t.ByReference(xswUsage.size()), null, size_t.ZERO));
xswUsage.read();
assertTrue(xswUsage.xsu_used <= xswUsage.xsu_total);
}

public void testProcessStructures() {
// Calc max # of processes
IntByReference size = new IntByReference(4);
size_t.ByReference size = new size_t.ByReference(4);
Memory mem = new Memory(4);
assertEquals(0, SystemB.INSTANCE.sysctlbyname("kern.maxproc", mem, size, null, 0));
assertEquals(0, SystemB.INSTANCE.sysctlbyname("kern.maxproc", mem, size, null, size_t.ZERO));
int maxProc = mem.getInt(0);

// Get list of pids
Expand Down Expand Up @@ -330,15 +336,15 @@ public void testIFs() {
int NET_RT_IFLIST2 = 6;
int[] mib = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST2, 0 };

IntByReference len = new IntByReference();
assertEquals(0, SystemB.INSTANCE.sysctl(mib, 6, null, len, null, 0));
size_t.ByReference len = new size_t.ByReference();
assertEquals(0, SystemB.INSTANCE.sysctl(mib, 6, null, len, null, size_t.ZERO));
// Add enough room for max size of IFmsgHdr to avoid JNA bounds check
// problems with worst case structure size
Memory buf = new Memory(len.getValue() + 112);
assertEquals(0, SystemB.INSTANCE.sysctl(mib, 6, buf, len, null, 0));
Memory buf = new Memory(len.getValue().longValue() + 112);
assertEquals(0, SystemB.INSTANCE.sysctl(mib, 6, buf, len, null, size_t.ZERO));

// Iterate offset from buf's pointer up to limit of buf
int lim = len.getValue();
int lim = len.getValue().intValue();
int next = 0;
while (next < lim) {
// Get pointer to current native part of buf
Expand Down