Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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 @@ -11,6 +11,7 @@ Features
* [#1697](https://github.com/java-native-access/jna/pull/1697): Add WlanApi module - [@eranl](https://github.com/eranl).
* [#1718](https://github.com/java-native-access/jna/pull/1718): Add `Cups` to `c.s.j.p.unix` providing CUPS printing system bindings for destinations, jobs, options, and server configuration - [@dbwiddis](https://github.com/dbwiddis).
* [#1720](https://github.com/java-native-access/jna/pull/1720): Add `groupCount` and `groupMasks` fields to `CACHE_RELATIONSHIP` in `c.s.j.p.win32.WinNT`, matching the updated Windows struct layout - [@dbwiddis](https://github.com/dbwiddis).
* [#1723](https://github.com/java-native-access/jna/pull/1723): Add `ProcFdInfo`, `InSockInfo`, `TcpSockInfo`, `proc_pidfdinfo`, `statfs64`, and `vm_deallocate` to `c.s.j.p.mac.SystemB` - [@dbwiddis](https://github.com/dbwiddis).

Bug Fixes
---------
Expand Down
132 changes: 132 additions & 0 deletions contrib/platform/src/com/sun/jna/platform/mac/SystemB.java
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,91 @@ class RUsageInfoV2 extends Structure {
public long ri_diskio_byteswritten;
}

// proc_info.h: Flavors for proc_pidinfo and proc_pidfdinfo
int PROC_PIDLISTFDS = 1;
int PROC_PIDFDSOCKETINFO = 3;

// proc_info.h: File descriptor types
int PROX_FDTYPE_SOCKET = 2;

// proc_info.h: Socket info kinds
int SOCKINFO_IN = 1;
int SOCKINFO_TCP = 2;

// proc_info.h: TCP timer count
int TSI_T_NTIMERS = 4;

// socket.h: Address families
int AF_INET = 2;
int AF_INET6 = 30;

/**
* File descriptor information as returned by {@code proc_pidinfo} with
* {@link #PROC_PIDLISTFDS}.
* <p>
* Corresponds to {@code struct proc_fdinfo} in {@code <sys/proc_info.h>}.
*/
@Structure.FieldOrder({ "proc_fd", "proc_fdtype" })
class ProcFdInfo extends Structure {
public int proc_fd;
public int proc_fdtype;
}

/**
* Internet socket information.
* <p>
* Corresponds to {@code struct in_sockinfo} in {@code <sys/proc_info.h>}.
* The {@code insi_faddr} and {@code insi_laddr} fields are unions of
* {@code in4in6_addr} and {@code in6_addr}, both 16 bytes, mapped as
* {@code int[4]}.
*/
@Structure.FieldOrder({ "insi_fport", "insi_lport", "insi_gencnt", "insi_flags", "insi_flow", "insi_vflag",
"insi_ip_ttl", "rfu_1", "insi_faddr", "insi_laddr", "insi_v4", "insi_v6" })
class InSockInfo extends Structure {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found this: https://github.com/phracker/MacOSX-SDKs/blob/041600eda65c6a668f66cb7d56b7d1da3e8bcc93/MacOSX11.3.sdk/usr/include/sys/proc_info.h#L360-L388

The first members match. Are the latter members intentionally not mapped as struct but instead as byte arrays?

/** Foreign port. */
public int insi_fport;
/** Local port. */
public int insi_lport;
/** Generation count of this instance. */
public long insi_gencnt;
/** Generic IP/datagram flags. */
public int insi_flags;
public int insi_flow;
/** INI_IPV4 or INI_IPV6. */
public byte insi_vflag;
/** Time to live proto. */
public byte insi_ip_ttl;
/** Reserved. */
public int rfu_1;
/** Foreign host table entry (union of in4in6_addr/in6_addr, 16 bytes). */
public int[] insi_faddr = new int[4];
/** Local host table entry (union of in4in6_addr/in6_addr, 16 bytes). */
public int[] insi_laddr = new int[4];
/** IPv4 type of service. */
public byte insi_v4;
/** IPv6 info (in6_hlim, in6_cksum, in6_ifindex, in6_hops). */
public byte[] insi_v6 = new byte[9];
}

/**
* TCP socket information.
* <p>
* Corresponds to {@code struct tcp_sockinfo} in {@code <sys/proc_info.h>}.
*/
@Structure.FieldOrder({ "tcpsi_ini", "tcpsi_state", "tcpsi_timer", "tcpsi_mss", "tcpsi_flags", "rfu_1",
"tcpsi_tp" })
class TcpSockInfo extends Structure {
public InSockInfo tcpsi_ini;
public int tcpsi_state;
public int[] tcpsi_timer = new int[TSI_T_NTIMERS];
public int tcpsi_mss;
public int tcpsi_flags;
/** Reserved. */
public int rfu_1;
/** Opaque handle of TCP protocol control block. */
public long tcpsi_tp;
}

@Structure.FieldOrder({ "vip_vi", "vip_path" })
class VnodeInfoPath extends Structure {
public byte[] vip_vi = new byte[152]; // vnode_info but we don't
Expand Down Expand Up @@ -877,4 +962,51 @@ int host_processor_info(int hostPort, int flavor, IntByReference procCount, Poin
* @return the process ID of the calling process.
*/
int getpid();

/**
* Returns information about a file descriptor of a process.
*
* @param pid
* the process identifier
* @param fd
* the file descriptor
* @param flavor
* the type of information requested (e.g.,
* {@link #PROC_PIDFDSOCKETINFO})
* @param buffer
* holds results
* @param buffersize
* size of results
* @return the number of bytes of data returned in the provided buffer; -1 if an
* error was encountered
*/
int proc_pidfdinfo(int pid, int fd, int flavor, Structure buffer, int buffersize);

/**
* The statfs64() routine returns information about a mounted file system.
* The {@code path} argument is the path name of any file or directory within
* the mounted file system. The {@code buf} argument is a pointer to a
* {@code statfs} structure.
*
* @param path
* the path to any file within the mounted filesystem
* @param buf
* a {@link Statfs} structure
* @return 0 on success; -1 on failure (sets errno)
*/
int statfs64(String path, Statfs buf);

/**
* Deallocates a region of virtual memory in the specified task.
*
* @param targetTask
* the target task (typically from {@link #mach_task_self()})
* @param address
* the starting address of the region to deallocate
* @param size
* the number of bytes to deallocate
* @return 0 ({@code KERN_SUCCESS}) on success; a {@code kern_return_t} error
* code otherwise
*/
int vm_deallocate(int targetTask, long address, long size);
}
34 changes: 34 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/mac/SystemBTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.sun.jna.platform.mac.SystemB.IFmsgHdr;
import com.sun.jna.platform.mac.SystemB.IFmsgHdr2;
import com.sun.jna.platform.mac.SystemB.Passwd;
import com.sun.jna.platform.mac.SystemB.ProcFdInfo;
import com.sun.jna.platform.mac.SystemB.ProcTaskAllInfo;
import com.sun.jna.platform.mac.SystemB.RUsageInfoV2;
import com.sun.jna.platform.mac.SystemB.Statfs;
Expand Down Expand Up @@ -171,6 +172,12 @@ public void testHostProcessorInfo() {
assertTrue(procCount.getValue() > 0);
assertEquals(procCpuLoadInfo.getValue().getIntArray(0, procInfoCount.getValue()).length,
procInfoCount.getValue());

// Deallocate the memory allocated by host_processor_info
int taskSelf = SystemB.INSTANCE.mach_task_self();
ret = SystemB.INSTANCE.vm_deallocate(taskSelf, Pointer.nativeValue(procCpuLoadInfo.getValue()),
(long) procInfoCount.getValue() * SystemB.INT_SIZE);
assertEquals(0, ret);
}

// From Unix LibCAPI
Expand Down Expand Up @@ -366,6 +373,33 @@ public void testIFs() {
}
}

public void testProcPidFdInfo() {
int pid = SystemB.INSTANCE.getpid();

// Get the list of open file descriptors for this process
int bufferSize = SystemB.INSTANCE.proc_pidinfo(pid, SystemB.PROC_PIDLISTFDS, 0, null, 0);
assertTrue(bufferSize > 0);

int numFds = bufferSize / new ProcFdInfo().size();
assertTrue(numFds > 0);

ProcFdInfo[] fdInfoArray = (ProcFdInfo[]) new ProcFdInfo().toArray(numFds);
int ret = SystemB.INSTANCE.proc_pidinfo(pid, SystemB.PROC_PIDLISTFDS, 0, fdInfoArray[0],
bufferSize);
Comment on lines +380 to +388
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is fishy here. I'd expect proc_pidfdinfo not proc_pidinfo to be called here.

assertTrue(ret > 0);

// Verify we got valid fd entries
assertTrue(fdInfoArray[0].proc_fd >= 0);
assertTrue(fdInfoArray[0].proc_fdtype >= 0);
}

public void testStatfs64() {
Statfs buf = new Statfs();
assertEquals(0, SystemB.INSTANCE.statfs64("/", buf));
assertTrue(buf.f_blocks > 0);
assertTrue(buf.f_bsize > 0);
}

public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(SystemBTest.class);
}
Expand Down
Loading