add FreeBSD support to std.os.getFdPath
This implementation uses the F_KINFO fcntl command added in FreeBSD 13 release. FreeBSD 12 users get a compile error. Co-authored-by: Stephen Gregoratto <dev@sgregoratto.me>
This commit is contained in:
committed by
Veikka Tuominen
parent
4c7fe74b2c
commit
397e6547a9
@@ -19,6 +19,8 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
|
||||
pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;
|
||||
pub extern "c" fn malloc_usable_size(?*const anyopaque) usize;
|
||||
|
||||
pub extern "c" fn getpid() pid_t;
|
||||
|
||||
pub const sf_hdtr = extern struct {
|
||||
headers: [*]const iovec_const,
|
||||
hdr_cnt: c_int,
|
||||
@@ -397,6 +399,127 @@ pub const sockaddr = extern struct {
|
||||
};
|
||||
};
|
||||
|
||||
pub const CAP_RIGHTS_VERSION = 0;
|
||||
|
||||
pub const cap_rights = extern struct {
|
||||
rights: [CAP_RIGHTS_VERSION + 2]u64,
|
||||
};
|
||||
|
||||
pub const kinfo_file = extern struct {
|
||||
/// Size of this record.
|
||||
/// A zero value is for the sentinel record at the end of an array.
|
||||
structsize: c_int,
|
||||
/// Descriptor type.
|
||||
@"type": c_int,
|
||||
/// Array index.
|
||||
fd: fd_t,
|
||||
/// Reference count.
|
||||
ref_count: c_int,
|
||||
/// Flags.
|
||||
flags: c_int,
|
||||
// 64bit padding.
|
||||
_pad0: c_int,
|
||||
/// Seek location.
|
||||
offset: i64,
|
||||
un: extern union {
|
||||
socket: extern struct {
|
||||
/// Sendq size.
|
||||
sendq: u32,
|
||||
/// Socket domain.
|
||||
domain: c_int,
|
||||
/// Socket type.
|
||||
@"type": c_int,
|
||||
/// Socket protocol.
|
||||
protocol: c_int,
|
||||
/// Socket address.
|
||||
address: sockaddr.storage,
|
||||
/// Peer address.
|
||||
peer: sockaddr.storage,
|
||||
/// Address of so_pcb.
|
||||
pcb: u64,
|
||||
/// Address of inp_ppcb.
|
||||
inpcb: u64,
|
||||
/// Address of unp_conn.
|
||||
unpconn: u64,
|
||||
/// Send buffer state.
|
||||
snd_sb_state: u16,
|
||||
/// Receive buffer state.
|
||||
rcv_sb_state: u16,
|
||||
/// Recvq size.
|
||||
recvq: u32,
|
||||
},
|
||||
file: extern struct {
|
||||
/// Vnode type.
|
||||
@"type": i32,
|
||||
// Reserved for future use
|
||||
_spare1: [3]i32,
|
||||
_spare2: [30]u64,
|
||||
/// Vnode filesystem id.
|
||||
fsid: u64,
|
||||
/// File device.
|
||||
rdev: u64,
|
||||
/// Global file id.
|
||||
fileid: u64,
|
||||
/// File size.
|
||||
size: u64,
|
||||
/// fsid compat for FreeBSD 11.
|
||||
fsid_freebsd11: u32,
|
||||
/// rdev compat for FreeBSD 11.
|
||||
rdev_freebsd11: u32,
|
||||
/// File mode.
|
||||
mode: u16,
|
||||
// 64bit padding.
|
||||
_pad0: u16,
|
||||
_pad1: u32,
|
||||
},
|
||||
sem: extern struct {
|
||||
_spare0: [4]u32,
|
||||
_spare1: [32]u64,
|
||||
/// Semaphore value.
|
||||
value: u32,
|
||||
/// Semaphore mode.
|
||||
mode: u16,
|
||||
},
|
||||
pipe: extern struct {
|
||||
_spare1: [4]u32,
|
||||
_spare2: [32]u64,
|
||||
addr: u64,
|
||||
peer: u64,
|
||||
buffer_cnt: u32,
|
||||
// 64bit padding.
|
||||
kf_pipe_pad0: [3]u32,
|
||||
},
|
||||
proc: extern struct {
|
||||
_spare1: [4]u32,
|
||||
_spare2: [32]u64,
|
||||
pid: pid_t,
|
||||
},
|
||||
eventfd: extern struct {
|
||||
value: u64,
|
||||
flags: u32,
|
||||
},
|
||||
},
|
||||
/// Status flags.
|
||||
status: u16,
|
||||
// 32-bit alignment padding.
|
||||
_pad1: u16,
|
||||
// Reserved for future use.
|
||||
_spare: c_int,
|
||||
/// Capability rights.
|
||||
cap_rights: cap_rights,
|
||||
/// Reserved for future cap_rights
|
||||
_cap_spare: u64,
|
||||
/// Path to file, if any.
|
||||
path: [PATH_MAX - 1:0]u8,
|
||||
};
|
||||
|
||||
pub const KINFO_FILE_SIZE = 1392;
|
||||
|
||||
comptime {
|
||||
std.debug.assert(@sizeOf(kinfo_file) == KINFO_FILE_SIZE);
|
||||
std.debug.assert(@alignOf(kinfo_file) == @sizeOf(u64));
|
||||
}
|
||||
|
||||
pub const CTL = struct {
|
||||
pub const KERN = 1;
|
||||
pub const DEBUG = 5;
|
||||
@@ -405,6 +528,7 @@ pub const CTL = struct {
|
||||
pub const KERN = struct {
|
||||
pub const PROC = 14; // struct: process entries
|
||||
pub const PROC_PATHNAME = 12; // path to executable
|
||||
pub const PROC_FILEDESC = 33; // file descriptors for process
|
||||
pub const IOV_MAX = 35;
|
||||
};
|
||||
|
||||
@@ -613,23 +737,67 @@ pub const O = struct {
|
||||
pub const NDELAY = NONBLOCK;
|
||||
};
|
||||
|
||||
/// Command flags for fcntl(2).
|
||||
pub const F = struct {
|
||||
/// Duplicate file descriptor.
|
||||
pub const DUPFD = 0;
|
||||
/// Get file descriptor flags.
|
||||
pub const GETFD = 1;
|
||||
/// Set file descriptor flags.
|
||||
pub const SETFD = 2;
|
||||
/// Get file status flags.
|
||||
pub const GETFL = 3;
|
||||
/// Set file status flags.
|
||||
pub const SETFL = 4;
|
||||
|
||||
/// Get SIGIO/SIGURG proc/pgrrp.
|
||||
pub const GETOWN = 5;
|
||||
/// Set SIGIO/SIGURG proc/pgrrp.
|
||||
pub const SETOWN = 6;
|
||||
|
||||
/// Get record locking information.
|
||||
pub const GETLK = 11;
|
||||
/// Set record locking information.
|
||||
pub const SETLK = 12;
|
||||
/// Set record locking information and wait if blocked.
|
||||
pub const SETLKW = 13;
|
||||
|
||||
/// Debugging support for remote locks.
|
||||
pub const SETLK_REMOTE = 14;
|
||||
/// Read ahead.
|
||||
pub const READAHEAD = 15;
|
||||
|
||||
/// DUPFD with FD_CLOEXEC set.
|
||||
pub const DUPFD_CLOEXEC = 17;
|
||||
/// DUP2FD with FD_CLOEXEC set.
|
||||
pub const DUP2FD_CLOEXEC = 18;
|
||||
|
||||
pub const ADD_SEALS = 19;
|
||||
pub const GET_SEALS = 20;
|
||||
/// Return `kinfo_file` for a file descriptor.
|
||||
pub const KINFO = 22;
|
||||
|
||||
// Seals (ADD_SEALS, GET_SEALS)
|
||||
/// Prevent adding sealings.
|
||||
pub const SEAL_SEAL = 0x0001;
|
||||
/// May not shrink
|
||||
pub const SEAL_SHRINK = 0x0002;
|
||||
/// May not grow.
|
||||
pub const SEAL_GROW = 0x0004;
|
||||
/// May not write.
|
||||
pub const SEAL_WRITE = 0x0008;
|
||||
|
||||
// Record locking flags (GETLK, SETLK, SETLKW).
|
||||
/// Shared or read lock.
|
||||
pub const RDLCK = 1;
|
||||
pub const WRLCK = 3;
|
||||
/// Unlock.
|
||||
pub const UNLCK = 2;
|
||||
/// Exclusive or write lock.
|
||||
pub const WRLCK = 3;
|
||||
/// Purge locks for a given system ID.
|
||||
pub const UNLCKSYS = 4;
|
||||
/// Cancel an async lock request.
|
||||
pub const CANCEL = 5;
|
||||
|
||||
pub const SETOWN_EX = 15;
|
||||
pub const GETOWN_EX = 16;
|
||||
|
||||
@@ -5167,8 +5167,8 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
|
||||
|
||||
/// Return canonical path of handle `fd`.
|
||||
/// This function is very host-specific and is not universally supported by all hosts.
|
||||
/// For example, while it generally works on Linux, macOS or Windows, it is unsupported
|
||||
/// on FreeBSD, or WASI.
|
||||
/// For example, while it generally works on Linux, macOS, FreeBSD or Windows, it is
|
||||
/// unsupported on WASI.
|
||||
pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
|
||||
switch (builtin.os.tag) {
|
||||
.windows => {
|
||||
@@ -5217,6 +5217,22 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
|
||||
};
|
||||
return target;
|
||||
},
|
||||
.freebsd => {
|
||||
comptime if (builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0 }) == .lt)
|
||||
@compileError("querying for canonical path of a handle is unsupported on FreeBSD 12 and below");
|
||||
|
||||
var kfile: system.kinfo_file = undefined;
|
||||
kfile.structsize = system.KINFO_FILE_SIZE;
|
||||
switch (errno(system.fcntl(fd, system.F.KINFO, @ptrToInt(&kfile)))) {
|
||||
.SUCCESS => {},
|
||||
.BADF => return error.FileNotFound,
|
||||
else => |err| return unexpectedErrno(err),
|
||||
}
|
||||
|
||||
const len = mem.indexOfScalar(u8, &kfile.path, 0) orelse MAX_PATH_BYTES;
|
||||
mem.copy(u8, out_buffer, kfile.path[0..len]);
|
||||
return out_buffer[0..len];
|
||||
},
|
||||
else => @compileError("querying for canonical path of a handle is unsupported on this host"),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user