std.os: Add memfd_create for FreeBSD

This is minorly breaking as e.g. std.os.linux.MFD_CLOEXEC is now
std.os.linux.MFD.CLOEXEC.
This commit is contained in:
Isaac Freund 2022-05-14 14:16:19 +02:00 committed by Andrew Kelley
parent 5b03d55c5e
commit 1392c24166
4 changed files with 65 additions and 35 deletions

View File

@ -1640,3 +1640,12 @@ pub const POLL = struct {
pub const STANDARD = IN | PRI | OUT | RDNORM | RDBAND | WRBAND | ERR | HUP | NVAL;
};
pub const NAME_MAX = 255;
pub const MFD = struct {
pub const CLOEXEC = 0x0001;
pub const ALLOW_SEALING = 0x0002;
};
pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int;

View File

@ -97,6 +97,7 @@ pub const MADV = system.MADV;
pub const MAP = system.MAP;
pub const MSF = system.MSF;
pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN;
pub const MFD = system.MFD;
pub const MMAP2_UNIT = system.MMAP2_UNIT;
pub const MSG = system.MSG;
pub const NAME_MAX = system.NAME_MAX;
@ -6522,20 +6523,37 @@ pub const MemFdCreateError = error{
} || UnexpectedError;
pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
// memfd_create is available only in glibc versions starting with 2.27.
const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok;
const sys = if (use_c) std.c else linux;
const getErrno = if (use_c) std.c.getErrno else linux.getErrno;
const rc = sys.memfd_create(name, flags);
switch (getErrno(rc)) {
.SUCCESS => return @intCast(fd_t, rc),
.FAULT => unreachable, // name has invalid memory
.INVAL => unreachable, // name/flags are faulty
.NFILE => return error.SystemFdQuotaExceeded,
.MFILE => return error.ProcessFdQuotaExceeded,
.NOMEM => return error.OutOfMemory,
.NOSYS => return error.SystemOutdated,
else => |err| return unexpectedErrno(err),
switch (builtin.os.tag) {
.linux => {
// memfd_create is available only in glibc versions starting with 2.27.
const use_c = std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 }).ok;
const sys = if (use_c) std.c else linux;
const getErrno = if (use_c) std.c.getErrno else linux.getErrno;
const rc = sys.memfd_create(name, flags);
switch (getErrno(rc)) {
.SUCCESS => return @intCast(fd_t, rc),
.FAULT => unreachable, // name has invalid memory
.INVAL => unreachable, // name/flags are faulty
.NFILE => return error.SystemFdQuotaExceeded,
.MFILE => return error.ProcessFdQuotaExceeded,
.NOMEM => return error.OutOfMemory,
.NOSYS => return error.SystemOutdated,
else => |err| return unexpectedErrno(err),
}
},
.freebsd => {
const rc = system.memfd_create(name, flags);
switch (errno(rc)) {
.SUCCESS => return rc,
.BADF => unreachable, // name argument NULL
.INVAL => unreachable, // name too long or invalid/unsupported flags.
.MFILE => return error.ProcessFdQuotaExceeded,
.NFILE => return error.SystemFdQuotaExceeded,
.NOSYS => return error.SystemOutdated,
else => |err| return unexpectedErrno(err),
}
},
else => @compileError("target OS does not support memfd_create()"),
}
}

View File

@ -3972,11 +3972,6 @@ pub const POLL = struct {
pub const RDBAND = 0x080;
};
pub const MFD_CLOEXEC = 0x0001;
pub const MFD_ALLOW_SEALING = 0x0002;
pub const MFD_HUGETLB = 0x0004;
pub const MFD_ALL_FLAGS = MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB;
pub const HUGETLB_FLAG_ENCODE_SHIFT = 26;
pub const HUGETLB_FLAG_ENCODE_MASK = 0x3f;
pub const HUGETLB_FLAG_ENCODE_64KB = 16 << HUGETLB_FLAG_ENCODE_SHIFT;
@ -3992,20 +3987,27 @@ pub const HUGETLB_FLAG_ENCODE_1GB = 30 << HUGETLB_FLAG_ENCODE_SHIFT;
pub const HUGETLB_FLAG_ENCODE_2GB = 31 << HUGETLB_FLAG_ENCODE_SHIFT;
pub const HUGETLB_FLAG_ENCODE_16GB = 34 << HUGETLB_FLAG_ENCODE_SHIFT;
pub const MFD_HUGE_SHIFT = HUGETLB_FLAG_ENCODE_SHIFT;
pub const MFD_HUGE_MASK = HUGETLB_FLAG_ENCODE_MASK;
pub const MFD_HUGE_64KB = HUGETLB_FLAG_ENCODE_64KB;
pub const MFD_HUGE_512KB = HUGETLB_FLAG_ENCODE_512KB;
pub const MFD_HUGE_1MB = HUGETLB_FLAG_ENCODE_1MB;
pub const MFD_HUGE_2MB = HUGETLB_FLAG_ENCODE_2MB;
pub const MFD_HUGE_8MB = HUGETLB_FLAG_ENCODE_8MB;
pub const MFD_HUGE_16MB = HUGETLB_FLAG_ENCODE_16MB;
pub const MFD_HUGE_32MB = HUGETLB_FLAG_ENCODE_32MB;
pub const MFD_HUGE_256MB = HUGETLB_FLAG_ENCODE_256MB;
pub const MFD_HUGE_512MB = HUGETLB_FLAG_ENCODE_512MB;
pub const MFD_HUGE_1GB = HUGETLB_FLAG_ENCODE_1GB;
pub const MFD_HUGE_2GB = HUGETLB_FLAG_ENCODE_2GB;
pub const MFD_HUGE_16GB = HUGETLB_FLAG_ENCODE_16GB;
pub const MFD = struct {
pub const CLOEXEC = 0x0001;
pub const ALLOW_SEALING = 0x0002;
pub const HUGETLB = 0x0004;
pub const ALL_FLAGS = CLOEXEC | ALLOW_SEALING | HUGETLB;
pub const HUGE_SHIFT = HUGETLB_FLAG_ENCODE_SHIFT;
pub const HUGE_MASK = HUGETLB_FLAG_ENCODE_MASK;
pub const HUGE_64KB = HUGETLB_FLAG_ENCODE_64KB;
pub const HUGE_512KB = HUGETLB_FLAG_ENCODE_512KB;
pub const HUGE_1MB = HUGETLB_FLAG_ENCODE_1MB;
pub const HUGE_2MB = HUGETLB_FLAG_ENCODE_2MB;
pub const HUGE_8MB = HUGETLB_FLAG_ENCODE_8MB;
pub const HUGE_16MB = HUGETLB_FLAG_ENCODE_16MB;
pub const HUGE_32MB = HUGETLB_FLAG_ENCODE_32MB;
pub const HUGE_256MB = HUGETLB_FLAG_ENCODE_256MB;
pub const HUGE_512MB = HUGETLB_FLAG_ENCODE_512MB;
pub const HUGE_1GB = HUGETLB_FLAG_ENCODE_1GB;
pub const HUGE_2GB = HUGETLB_FLAG_ENCODE_2GB;
pub const HUGE_16GB = HUGETLB_FLAG_ENCODE_16GB;
};
pub const rusage = extern struct {
utime: timeval,

View File

@ -495,8 +495,9 @@ test "argsAlloc" {
}
test "memfd_create" {
// memfd_create is linux specific.
if (native_os != .linux) return error.SkipZigTest;
// memfd_create is only supported by linux and freebsd.
if (native_os != .linux and native_os != .freebsd) return error.SkipZigTest;
const fd = std.os.memfd_create("test", 0) catch |err| switch (err) {
// Related: https://github.com/ziglang/zig/issues/4019
error.SystemOutdated => return error.SkipZigTest,