authorgravatar for gitkim@westryn.netKim SHrier <gitkim@westryn.net> 2022-07-11 13:54:40-06:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-15 10:16:31+03:00
log397e6547a9b1745df520a65ca615934b8c0a02d2
tree5c1fc6340f038073228ddc04f5207a68f2af4e0f
parent4c7fe74b2c0e8279d0003f820a18d59e1237b74a

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>

2 files changed, 187 insertions(+), 3 deletions(-)

lib/std/c/freebsd.zig+169-1
......@@ -19,6 +19,8 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
1919pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int;
2020pub extern "c" fn malloc_usable_size(?*const anyopaque) usize;
2121
22pub extern "c" fn getpid() pid_t;
23
2224pub const sf_hdtr = extern struct {
2325 headers: [*]const iovec_const,
2426 hdr_cnt: c_int,
......@@ -397,6 +399,127 @@ pub const sockaddr = extern struct {
397399 };
398400};
399401
402pub const CAP_RIGHTS_VERSION = 0;
403
404pub const cap_rights = extern struct {
405 rights: [CAP_RIGHTS_VERSION + 2]u64,
406};
407
408pub const kinfo_file = extern struct {
409 /// Size of this record.
410 /// A zero value is for the sentinel record at the end of an array.
411 structsize: c_int,
412 /// Descriptor type.
413 @"type": c_int,
414 /// Array index.
415 fd: fd_t,
416 /// Reference count.
417 ref_count: c_int,
418 /// Flags.
419 flags: c_int,
420 // 64bit padding.
421 _pad0: c_int,
422 /// Seek location.
423 offset: i64,
424 un: extern union {
425 socket: extern struct {
426 /// Sendq size.
427 sendq: u32,
428 /// Socket domain.
429 domain: c_int,
430 /// Socket type.
431 @"type": c_int,
432 /// Socket protocol.
433 protocol: c_int,
434 /// Socket address.
435 address: sockaddr.storage,
436 /// Peer address.
437 peer: sockaddr.storage,
438 /// Address of so_pcb.
439 pcb: u64,
440 /// Address of inp_ppcb.
441 inpcb: u64,
442 /// Address of unp_conn.
443 unpconn: u64,
444 /// Send buffer state.
445 snd_sb_state: u16,
446 /// Receive buffer state.
447 rcv_sb_state: u16,
448 /// Recvq size.
449 recvq: u32,
450 },
451 file: extern struct {
452 /// Vnode type.
453 @"type": i32,
454 // Reserved for future use
455 _spare1: [3]i32,
456 _spare2: [30]u64,
457 /// Vnode filesystem id.
458 fsid: u64,
459 /// File device.
460 rdev: u64,
461 /// Global file id.
462 fileid: u64,
463 /// File size.
464 size: u64,
465 /// fsid compat for FreeBSD 11.
466 fsid_freebsd11: u32,
467 /// rdev compat for FreeBSD 11.
468 rdev_freebsd11: u32,
469 /// File mode.
470 mode: u16,
471 // 64bit padding.
472 _pad0: u16,
473 _pad1: u32,
474 },
475 sem: extern struct {
476 _spare0: [4]u32,
477 _spare1: [32]u64,
478 /// Semaphore value.
479 value: u32,
480 /// Semaphore mode.
481 mode: u16,
482 },
483 pipe: extern struct {
484 _spare1: [4]u32,
485 _spare2: [32]u64,
486 addr: u64,
487 peer: u64,
488 buffer_cnt: u32,
489 // 64bit padding.
490 kf_pipe_pad0: [3]u32,
491 },
492 proc: extern struct {
493 _spare1: [4]u32,
494 _spare2: [32]u64,
495 pid: pid_t,
496 },
497 eventfd: extern struct {
498 value: u64,
499 flags: u32,
500 },
501 },
502 /// Status flags.
503 status: u16,
504 // 32-bit alignment padding.
505 _pad1: u16,
506 // Reserved for future use.
507 _spare: c_int,
508 /// Capability rights.
509 cap_rights: cap_rights,
510 /// Reserved for future cap_rights
511 _cap_spare: u64,
512 /// Path to file, if any.
513 path: [PATH_MAX - 1:0]u8,
514};
515
516pub const KINFO_FILE_SIZE = 1392;
517
518comptime {
519 std.debug.assert(@sizeOf(kinfo_file) == KINFO_FILE_SIZE);
520 std.debug.assert(@alignOf(kinfo_file) == @sizeOf(u64));
521}
522
400523pub const CTL = struct {
401524 pub const KERN = 1;
402525 pub const DEBUG = 5;
......@@ -405,6 +528,7 @@ pub const CTL = struct {
405528pub const KERN = struct {
406529 pub const PROC = 14; // struct: process entries
407530 pub const PROC_PATHNAME = 12; // path to executable
531 pub const PROC_FILEDESC = 33; // file descriptors for process
408532 pub const IOV_MAX = 35;
409533};
410534
......@@ -613,23 +737,67 @@ pub const O = struct {
613737 pub const NDELAY = NONBLOCK;
614738};
615739
740/// Command flags for fcntl(2).
616741pub const F = struct {
742 /// Duplicate file descriptor.
617743 pub const DUPFD = 0;
744 /// Get file descriptor flags.
618745 pub const GETFD = 1;
746 /// Set file descriptor flags.
619747 pub const SETFD = 2;
748 /// Get file status flags.
620749 pub const GETFL = 3;
750 /// Set file status flags.
621751 pub const SETFL = 4;
622752
753 /// Get SIGIO/SIGURG proc/pgrrp.
623754 pub const GETOWN = 5;
755 /// Set SIGIO/SIGURG proc/pgrrp.
624756 pub const SETOWN = 6;
625757
758 /// Get record locking information.
626759 pub const GETLK = 11;
760 /// Set record locking information.
627761 pub const SETLK = 12;
762 /// Set record locking information and wait if blocked.
628763 pub const SETLKW = 13;
629764
765 /// Debugging support for remote locks.
766 pub const SETLK_REMOTE = 14;
767 /// Read ahead.
768 pub const READAHEAD = 15;
769
770 /// DUPFD with FD_CLOEXEC set.
771 pub const DUPFD_CLOEXEC = 17;
772 /// DUP2FD with FD_CLOEXEC set.
773 pub const DUP2FD_CLOEXEC = 18;
774
775 pub const ADD_SEALS = 19;
776 pub const GET_SEALS = 20;
777 /// Return `kinfo_file` for a file descriptor.
778 pub const KINFO = 22;
779
780 // Seals (ADD_SEALS, GET_SEALS)
781 /// Prevent adding sealings.
782 pub const SEAL_SEAL = 0x0001;
783 /// May not shrink
784 pub const SEAL_SHRINK = 0x0002;
785 /// May not grow.
786 pub const SEAL_GROW = 0x0004;
787 /// May not write.
788 pub const SEAL_WRITE = 0x0008;
789
790 // Record locking flags (GETLK, SETLK, SETLKW).
791 /// Shared or read lock.
630792 pub const RDLCK = 1;
631 pub const WRLCK = 3;
793 /// Unlock.
632794 pub const UNLCK = 2;
795 /// Exclusive or write lock.
796 pub const WRLCK = 3;
797 /// Purge locks for a given system ID.
798 pub const UNLCKSYS = 4;
799 /// Cancel an async lock request.
800 pub const CANCEL = 5;
633801
634802 pub const SETOWN_EX = 15;
635803 pub const GETOWN_EX = 16;
lib/std/os.zig+18-2
......@@ -5167,8 +5167,8 @@ pub fn realpathW(pathname: []const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
51675167
51685168/// Return canonical path of handle `fd`.
51695169/// This function is very host-specific and is not universally supported by all hosts.
5170/// For example, while it generally works on Linux, macOS or Windows, it is unsupported
5171/// on FreeBSD, or WASI.
5170/// For example, while it generally works on Linux, macOS, FreeBSD or Windows, it is
5171/// unsupported on WASI.
51725172pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
51735173 switch (builtin.os.tag) {
51745174 .windows => {
......@@ -5217,6 +5217,22 @@ pub fn getFdPath(fd: fd_t, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
52175217 };
52185218 return target;
52195219 },
5220 .freebsd => {
5221 comptime if (builtin.os.version_range.semver.max.order(.{ .major = 13, .minor = 0 }) == .lt)
5222 @compileError("querying for canonical path of a handle is unsupported on FreeBSD 12 and below");
5223
5224 var kfile: system.kinfo_file = undefined;
5225 kfile.structsize = system.KINFO_FILE_SIZE;
5226 switch (errno(system.fcntl(fd, system.F.KINFO, @ptrToInt(&kfile)))) {
5227 .SUCCESS => {},
5228 .BADF => return error.FileNotFound,
5229 else => |err| return unexpectedErrno(err),
5230 }
5231
5232 const len = mem.indexOfScalar(u8, &kfile.path, 0) orelse MAX_PATH_BYTES;
5233 mem.copy(u8, out_buffer, kfile.path[0..len]);
5234 return out_buffer[0..len];
5235 },
52205236 else => @compileError("querying for canonical path of a handle is unsupported on this host"),
52215237 }
52225238}