diff --git a/CHANGES.md b/CHANGES.md index 60bdf75096..36b7b130df 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,7 +17,7 @@ Features * [#1194](https://github.com/java-native-access/jna/pull/1194): Add `GetConsoleScreenBufferInfo`, `ReadConsoleInput` and `WriteConsole` with associated structures to `c.s.j.p.win32.Wincon` - [@rednoah](https://github.com/rednoah). * [#1198](https://github.com/java-native-access/jna/pull/1198): Add `NetSessionEnum` to `c.s.j.p.win32.Netapi32` and `WTSEnumerateSessions`, `WTSQuerySessionInformation`, and `WTSFreeMemory` to `c.s.j.p.win32.Wtsapi32` - [@dbwiddis](https://github.com/dbwiddis). * [#1200](https://github.com/java-native-access/jna/pull/1200): Add mappings for `libudev` to `c.s.j.p.linux.Udev` - [@dbwiddis](https://github.com/dbwiddis). -* [#1202](https://github.com/java-native-access/jna/pull/1202): Add mappings supporting shared memory `c.s.j.p.unix.LibCAPI` including `size_t`, `ssize_t`, and `off_t` types and `mmap()`, `munmap()`, `msync()`, `ftruncate()`, and `close()` methods, `c.s.j.p.unix.LibCUtil` exposing `OFF_T_SIZE` and mapping `mmap()`, `c.s.j.p.linux.LibRT` methods `shm_open()` and `shm_unlink()` - [@dbwiddis](https://github.com/dbwiddis). +* [#1202](https://github.com/java-native-access/jna/pull/1202): Add mappings supporting shared memory `c.s.j.p.unix.LibCAPI` including `size_t`, `ssize_t`, and `off_t` types, `c.s.j.p.linux.LibC` methods `munmap()`, `msync()`, and `close()`, `c.s.j.p.unix.LibCUtil` mapping `mmap()` and `ftruncate()`, and `c.s.j.p.linux.LibRT` methods `shm_open()` and `shm_unlink()` - [@dbwiddis](https://github.com/dbwiddis). Bug Fixes --------- diff --git a/contrib/platform/src/com/sun/jna/platform/linux/LibC.java b/contrib/platform/src/com/sun/jna/platform/linux/LibC.java index c5e2860bba..ae21e0c9c5 100644 --- a/contrib/platform/src/com/sun/jna/platform/linux/LibC.java +++ b/contrib/platform/src/com/sun/jna/platform/linux/LibC.java @@ -1,4 +1,4 @@ -/* Copyright (c) 2017,2020 Daniel Widdis, All Rights Reserved +/* Copyright (c) 2017 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 @@ -38,7 +38,7 @@ /** * LibC structures and functions unique to Linux */ -public interface LibC extends LibCAPI, ErrNo, Fcntl, Mman, Library { +public interface LibC extends LibCAPI, Library { String NAME = "c"; LibC INSTANCE = Native.load(NAME, LibC.class); 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 ba202fc04b..23dce12c45 100644 --- a/contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java +++ b/contrib/platform/src/com/sun/jna/platform/unix/LibCAPI.java @@ -77,6 +77,9 @@ public ssize_t(long value) { * systems, the bit width of this type may be dependent on compile-time options * in the end-user's library. The parameter {@code ilp32OffBig} permits this * type to be defined as 64-bit on a 32-bit operating system. + *
+ * Portable versions of C library methods which ensure appropriate bit width for + * {@code off_t} arguments are defined in {@link LibCUtil}. * * @see IEEE @@ -86,7 +89,6 @@ public ssize_t(long value) { * Std 1003.1-2017 (POSIX v7) */ class off_t extends IntegerType { - public static final off_t ZERO = new off_t(); private static final long serialVersionUID = 1L; @@ -128,7 +130,7 @@ public off_t(long value) { * If {@code true}, use 64-bit width. */ public off_t(long value, boolean ilp32OffBig) { - super(ilp32OffBig ? 8 : LibCUtil.OFF_T_SIZE, value); + super(ilp32OffBig ? 8 : Native.LONG_SIZE, value); } } @@ -221,75 +223,9 @@ public off_t(long value, boolean ilp32OffBig) { */ int close(int fd); - /** - * Causes the regular file referenced by {@code fd} to be truncated to a size of - * precisely {@code length} bytes. - *
- * If the file previously was larger than this size, the extra data is lost. If - * the file previously was shorter, it is extended, and the extended part reads - * as null bytes ('\0'). - *
- * The file must be open for writing - * - * @param fd - * a file descriptor - * @param length - * the number of bytes to truncate or extend the file to - * @return On success, zero is returned. On error, -1 is returned, and - * {@code errno} is set appropriately. - */ - int ftruncate(int fd, off_t length); - - /** - * Creates a new mapping in the virtual address space of the calling process. - * - * @param addr - * The starting address for the new mapping. - *
- * If {@code addr} is NULL, then the kernel chooses the
- * (page-aligned) address at which to create the mapping; this is the
- * most portable method of creating a new mapping. If {@code addr} is
- * not NULL, then the kernel takes it as a hint about where to place
- * the mapping; on Linux, the kernel will pick a nearby page boundary
- * (but always above or equal to the value specified by
- * {@code /proc/sys/vm/mmap_min_addr}) and attempt to create the
- * mapping there. If another mapping already exists there, the kernel
- * picks a new address that may or may not depend on the hint. The
- * address of the new mapping is returned as the result of the call.
- * @param length
- * Specifies the length of the mapping (which must be greater than
- * 0).
- * @param prot
- * describes the desired memory protection of the mapping (and must
- * not conflict with the open mode of the file). It is either
- * {@code PROT_NONE} or the bitwise OR of one or more of
- * {@code PROT_READ}, {@code PROT_WRITE}, or {@code PROT_EXEC}.
- * @param flags
- * determines whether updates to the mapping are visible to other
- * processes mapping the same region, and whether updates are carried
- * through to the underlying file. This behavior is determined by
- * including exactly one of {@code MAP_SHARED},
- * {@code MAP_SHARED_VALIDATE}, or {@code MAP_PRIVATE}. In addition,
- * 0 or more additional flags can be ORed in {@code flags}.
- * @param fd
- * The file descriptor for the object to be mapped. After the
- * {@code mmap()} call has returned, the file descriptor can be
- * closed immediately without invalidating the mapping.
- * @param offset
- * The contents of a file mapping (as opposed to an anonymous
- * mapping), are initialized using {@code length} bytes starting at
- * offset {@code offset} in the file (or other object) referred to by
- * the file descriptor, {@code fd}. {@code offset} must be a multiple
- * of the page size as returned by {@code sysconf(_SC_PAGE_SIZE)}.
- * @return On success, returns a pointer to the mapped area. On error, the value
- * {@code MAP_FAILED} (that is, (void *) -1) is returned, and
- * {@code errno} is set to indicate the cause of the error.
- */
- Pointer mmap(Pointer addr, size_t length, int prot, int flags, int fd, off_t offset);
-
/**
* Flushes changes made to the in-core copy of a file that was mapped into
- * memory using {@link LibCAPI#mmap(Pointer, size_t, int, int, int, off_t)} back
+ * memory using {@link LibCUtil#mmap(Pointer, long, int, int, int, long)} back
* to the filesystem. Without use of this call, there is no guarantee that
* changes are written back before {@link #munmap(Pointer, size_t)} is called.
* To be more precise, the part of the file that corresponds to the memory area
diff --git a/contrib/platform/src/com/sun/jna/platform/unix/LibCUtil.java b/contrib/platform/src/com/sun/jna/platform/unix/LibCUtil.java
index 39e616f4e0..df9ec2af97 100644
--- a/contrib/platform/src/com/sun/jna/platform/unix/LibCUtil.java
+++ b/contrib/platform/src/com/sun/jna/platform/unix/LibCUtil.java
@@ -35,32 +35,23 @@ public class LibCUtil {
private static final NativeLibrary LIBC = NativeLibrary.getInstance("c");
- /** Size of a native off_t
type, in bytes. */
- public static final int OFF_T_SIZE;
- static {
- // Observations shows, that without LFS, on linux, solaris, aix, mac OS and
- // windows (apart from cygwin32) sizeof(off_t) == sizeof(long)
- int size = Native.LONG_SIZE;
- // On 64-bit, off_t is 64 bit, otherwise test compiler flags that would create
- // 64-bit versions of off_t functions
- if (size < 8) {
- try {
- LIBC.getFunction("mmap64", Function.THROW_LAST_ERROR);
- // on 32-bit, mmap64 only exists when off_t is 64-bit
- size = 8;
- } catch (UnsatisfiedLinkError ex) {
- }
- }
- OFF_T_SIZE = size;
- }
-
- private static Function mmap;
+ private static Function mmap = null;
+ private static boolean mmap64 = false;
+ private static Function ftruncate = null;
+ private static boolean ftruncate64 = false;
static {
try {
mmap = LIBC.getFunction("mmap64", Function.THROW_LAST_ERROR);
+ mmap64 = true;
} catch (UnsatisfiedLinkError ex) {
mmap = LIBC.getFunction("mmap", Function.THROW_LAST_ERROR);
}
+ try {
+ ftruncate = LIBC.getFunction("ftruncate64", Function.THROW_LAST_ERROR);
+ ftruncate64 = true;
+ } catch (UnsatisfiedLinkError ex) {
+ ftruncate = LIBC.getFunction("ftruncate", Function.THROW_LAST_ERROR);
+ }
}
private LibCUtil() {
@@ -123,15 +114,55 @@ public static Pointer mmap(Pointer addr, long length, int prot, int flags, int f
params[2] = prot;
params[3] = flags;
params[4] = fd;
- if (OFF_T_SIZE == 4) {
+ if (mmap64) {
+ params[5] = offset;
+ } else {
require32Bit(offset, "offset");
params[5] = (int) offset;
- } else {
- params[5] = offset;
}
return mmap.invokePointer(params);
}
+ /**
+ * Causes the regular file referenced by {@code fd} to be truncated to a size of
+ * precisely {@code length} bytes.
+ *
+ * If the file previously was larger than this size, the extra data is lost. If + * the file previously was shorter, it is extended, and the extended part reads + * as null bytes ('\0'). + *
+ * The file must be open for writing + * + * @param fd + * a file descriptor + * @param length + * the number of bytes to truncate or extend the file to + * @return On success, zero is returned. On error, -1 is returned, and + * {@code errno} is set appropriately. + */ + public static int ftruncate(int fd, long length) { + Object[] params = new Object[2]; + params[0] = fd; + if (ftruncate64) { + params[1] = length; + } else { + require32Bit(length, "length"); + params[1] = (int) length; + } + return ftruncate.invokeInt(params); + } + + /** + * Test that a value is 32-bit, throwing a custom exception otherwise + * + * @param val + * The value to test + * @param value + * The name of the value, to be inserted in the exception message if + * not 32-bit + * @throws IllegalArgumentException + * if {@code val} is not 32-bit + */ public static void require32Bit(long val, String value) { if (val > Integer.MAX_VALUE) { throw new IllegalArgumentException(value + " exceeds 32bit"); diff --git a/contrib/platform/test/com/sun/jna/platform/linux/LibRTTest.java b/contrib/platform/test/com/sun/jna/platform/linux/LibRTTest.java index 32800ba69c..73a0ce3b7a 100644 --- a/contrib/platform/test/com/sun/jna/platform/linux/LibRTTest.java +++ b/contrib/platform/test/com/sun/jna/platform/linux/LibRTTest.java @@ -42,7 +42,6 @@ import com.sun.jna.Native; import com.sun.jna.Pointer; -import com.sun.jna.platform.unix.LibCAPI.off_t; import com.sun.jna.platform.unix.LibCAPI.size_t; import com.sun.jna.platform.unix.LibCUtil; @@ -66,12 +65,11 @@ public void testMmapToShm() throws IOException { // Multiply by 4 to handle all possible encodings int bufLen = 4 * (share.length() + 1); size_t length = new size_t(bufLen); - off_t truncLen = new off_t(bufLen); // Allocate memory to the share (fills with null bytes) - int ret = LIBC.ftruncate(fd, truncLen); + int ret = LibCUtil.ftruncate(fd, bufLen); assertNotEquals("Failed to ftruncate. Error: " + Native.getLastError(), -1, ret); // Map a pointer to the share. Offset must be a multiple of page size - Pointer p = LIBC.mmap(null, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, off_t.ZERO); + Pointer p = LibCUtil.mmap(null, bufLen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); assertNotEquals("Failed mmap to new share. Error: " + Native.getLastError(), MAP_FAILED, p); // We can now close the file descriptor ret = LIBC.close(fd);