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 @@ -12,6 +12,7 @@ Features
* [#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).
* [#1719](https://github.com/java-native-access/jna/pull/1719): Add `CoreGraphics` to `c.s.j.p.mac` with Quartz Window Services and Display Services bindings; implement `getAllWindows()` in `MacWindowUtils` - [@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
287 changes: 287 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 @@ -30,6 +30,7 @@
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.Union;
import com.sun.jna.platform.unix.LibCAPI;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
Expand Down Expand Up @@ -298,6 +299,245 @@ 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;
}

/**
* IPv4 address mapped into IPv6 address space.
* <p>
* Corresponds to {@code struct in4in6_addr} in {@code <sys/proc_info.h>}.
*/
@Structure.FieldOrder({ "i46a_pad32", "i46a_addr4" })
class In4In6Addr extends Structure {
/** Padding to align IPv4 address at offset 12. */
public int[] i46a_pad32 = new int[3];
/** IPv4 address (network byte order). */
public int i46a_addr4;
}

/**
* IPv6 address (128 bits).
* <p>
* Corresponds to {@code struct in6_addr} in {@code <netinet/in.h>}.
*/
@Structure.FieldOrder({ "__u6_addr" })
class In6Addr extends Structure {
/** 16-byte IPv6 address. */
public byte[] __u6_addr = new byte[16];
}

/**
* Union of IPv4-mapped-in-IPv6 and IPv6 addresses, used in
* {@link InSockInfo}.
* <p>
* Corresponds to the anonymous union containing {@code ina_46} and
* {@code ina_6} in {@code struct in_sockinfo}.
*/
class InsiAddr extends Union {
public In4In6Addr ina_46;
public In6Addr ina_6;
}

/**
* Internet socket information.
* <p>
* Corresponds to {@code struct in_sockinfo} in {@code <sys/proc_info.h>}.
*/
@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?

Copy link
Copy Markdown
Contributor Author

@dbwiddis dbwiddis May 12, 2026

Choose a reason for hiding this comment

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

int arrays to be precise.

I knew there was a reason I hadn't contributed these upstream for years... since I didn't really need them in my project I just made sure the byte counts matched as creating a union I would never need was annoying.

So this is four 32-bit IP addresses, the larger member of the first and second unions (thus int[4])

struct in4in6_addr {
	u_int32_t               i46a_pad32[3];
	struct in_addr          i46a_addr4;
};
struct in_addr {
    in_addr_t s_addr;
};
typedef __uint32_t      in_addr_t;      /* base type for internet address */

Similarly with the last insi_v6 structure.

Not sure I want to go to the trouble of mapping them. I can just close this PR. (I guess it's not that hard. I'm just lazy.)

/** 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. */
public InsiAddr insi_faddr;
/** Local host table entry. */
public InsiAddr insi_laddr;
/** 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];

@Override
public void read() {
super.read();
if (insi_vflag == 2) {
insi_faddr.setType("ina_6");
insi_laddr.setType("ina_6");
} else {
insi_faddr.setType("ina_46");
insi_laddr.setType("ina_46");
}
insi_faddr.read();
insi_laddr.read();
}
}

/**
* 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;
}

/**
* Per-file descriptor information.
* <p>
* Corresponds to {@code struct proc_fileinfo} in {@code <sys/proc_info.h>}.
*/
@Structure.FieldOrder({ "fi_openflags", "fi_status", "fi_offset", "fi_type", "fi_guardflags" })
class ProcFileInfo extends Structure {
public int fi_openflags;
public int fi_status;
public long fi_offset;
public int fi_type;
public int fi_guardflags;
}

/**
* Socket buffer information.
* <p>
* Corresponds to {@code struct sockbuf_info} in {@code <sys/proc_info.h>}.
*/
@Structure.FieldOrder({ "sbi_cc", "sbi_hiwat", "sbi_mbcnt", "sbi_mbmax", "sbi_lowat", "sbi_flags",
"sbi_timeo" })
class SockbufInfo extends Structure {
public int sbi_cc;
public int sbi_hiwat;
public int sbi_mbcnt;
public int sbi_mbmax;
public int sbi_lowat;
public short sbi_flags;
public short sbi_timeo;
}

/**
* Union of protocol-specific socket information in {@link SocketInfo}.
* <p>
* Corresponds to the {@code soi_proto} union in
* {@code struct socket_info}.
*/
class Pri extends Union {
public InSockInfo pri_in;
public TcpSockInfo pri_tcp;
/** Ensures the union is large enough for all protocol variants. */
public byte[] max_size = new byte[524];
}

/**
* Socket information.
* <p>
* Corresponds to {@code struct socket_info} in {@code <sys/proc_info.h>}.
* The {@code soi_stat} field ({@code struct vinfo_stat}) is mapped as a
* 136-byte opaque region.
*/
@Structure.FieldOrder({ "soi_stat", "soi_so", "soi_pcb", "soi_type", "soi_protocol", "soi_family",
"soi_options", "soi_linger", "soi_state", "soi_qlen", "soi_incqlen", "soi_qlimit", "soi_timeo",
"soi_error", "soi_oobmark", "soi_rcv", "soi_snd", "soi_kind", "rfu_1", "soi_proto" })
class SocketInfo extends Structure {
/** Opaque {@code vinfo_stat} (136 bytes). */
public byte[] soi_stat = new byte[136];
/** Opaque handle of socket. */
public long soi_so;
/** Opaque handle of protocol control block. */
public long soi_pcb;
public int soi_type;
public int soi_protocol;
public int soi_family;
public short soi_options;
public short soi_linger;
public short soi_state;
public short soi_qlen;
public short soi_incqlen;
public short soi_qlimit;
public short soi_timeo;
public short soi_error;
public int soi_oobmark;
public SockbufInfo soi_rcv;
public SockbufInfo soi_snd;
public int soi_kind;
/** Reserved. */
public int rfu_1;
public Pri soi_proto;

@Override
public void read() {
super.read();
if (soi_kind == SOCKINFO_TCP) {
soi_proto.setType("pri_tcp");
} else if (soi_kind == SOCKINFO_IN) {
soi_proto.setType("pri_in");
} else {
soi_proto.setType("max_size");
}
soi_proto.read();
}
}

/**
* Socket file descriptor information as returned by
* {@code proc_pidfdinfo} with {@link #PROC_PIDFDSOCKETINFO}.
* <p>
* Corresponds to {@code struct socket_fdinfo} in
* {@code <sys/proc_info.h>}.
*/
@Structure.FieldOrder({ "pfi", "psi" })
class SocketFdInfo extends Structure {
public ProcFileInfo pfi;
public SocketInfo psi;
}

@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 +1117,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);
}
Loading
Loading