From 32d80c6cec45d7a69b9bda1983f2da164a539402 Mon Sep 17 00:00:00 2001 From: Daniel Widdis Date: Tue, 25 May 2021 22:38:27 -0700 Subject: [PATCH] Define size_t.ByReference and fix macOS sysctl size_t* parameters --- CHANGES.md | 1 + .../src/com/sun/jna/platform/mac/SystemB.java | 56 +++++++++++----- .../com/sun/jna/platform/unix/LibCAPI.java | 29 ++++++++- .../com/sun/jna/platform/mac/SystemBTest.java | 64 ++++++++++--------- 4 files changed, 104 insertions(+), 46 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b9eb878a2a..f258b9a91e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 ============= diff --git a/contrib/platform/src/com/sun/jna/platform/mac/SystemB.java b/contrib/platform/src/com/sun/jna/platform/mac/SystemB.java index d11396b630..d17eeb8fa6 100644 --- a/contrib/platform/src/com/sun/jna/platform/mac/SystemB.java +++ b/contrib/platform/src/com/sun/jna/platform/mac/SystemB.java @@ -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. - * + *

* The state is described using a "Management Information Base" (MIB) style * name, listed in name, which is a namelen length array of integers. - * + *

* 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 @@ -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. - * + *

* 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. - * + *

* 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); /** @@ -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); /** @@ -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. diff --git a/contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java b/contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java index c2a9b9485e..2753be5759 100644 --- a/contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java +++ b/contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java @@ -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 @@ -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) { + 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); } diff --git a/contrib/platform/test/com/sun/jna/platform/mac/SystemBTest.java b/contrib/platform/test/com/sun/jna/platform/mac/SystemBTest.java index 6b9af6ebca..b4ab335a78 100644 --- a/contrib/platform/test/com/sun/jna/platform/mac/SystemBTest.java +++ b/contrib/platform/test/com/sun/jna/platform/mac/SystemBTest.java @@ -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. */ @@ -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)); + // 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); + 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); + assertEquals(0, SystemB.INSTANCE.sysctl(mib, mib.length, p, plen, null, size_t.ZERO)); assertTrue(p.getInt(0) >= nCpu); } @@ -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 @@ -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