authorgravatar for git@l4.pmLuna <git@l4.pm> 2019-11-13 21:25:19-03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-31 15:58:03-05:00
log997812e8fb9146360aa5200f0adbcd4863183287
treed4e32f9806a712ba9047a62482146c5475c252ba
parent25051832b37bab8d945e6284899a4c916ae00ada
signature Commit is signed but in an unrecognized format.

os: add memfd_create

currently only linux is supported

4 files changed, 85 insertions(+), 0 deletions(-)

lib/std/io/test.zig+13
......@@ -649,3 +649,16 @@ test "updateTimes" {
649649 std.testing.expect(stat_new.atime < stat_old.atime);
650650 std.testing.expect(stat_new.mtime < stat_old.mtime);
651651}
652
653test "memfd_create" {
654 if (builtin.os != .linux) return error.SkipZigTest;
655
656 const fd = try std.os.memfd_create("test", 0);
657 try std.os.write(fd, "test");
658 try std.os.lseek_SET(fd, 0);
659
660 var buf: [10]u8 = undefined;
661 const bytes_read = try std.os.read(fd, &buf);
662 expect(bytes_read == 4);
663 expect(mem.eql(u8, buf[0..4], "test"));
664}
lib/std/os.zig+32
......@@ -3281,3 +3281,35 @@ pub fn setsockopt(fd: fd_t, level: u32, optname: u32, opt: []const u8) SetSockOp
32813281 else => |err| return unexpectedErrno(err),
32823282 }
32833283}
3284
3285// TODO support for non-null terminated strings?
3286pub fn memfd_createC(name: [*:0]const u8, flags: usize) !fd_t {
3287 if (builtin.os != .linux) @compileError("memfd_create() not implemented for this target");
3288
3289 const rc = linux.memfd_create(name, flags);
3290 switch (linux.getErrno(rc)) {
3291 0 => return @intCast(fd_t, rc),
3292 EFAULT => unreachable, // name has invalid memory
3293 EINVAL => unreachable, // name/flags are faulty
3294 ENFILE => return error.SystemFdQuotaExceeded,
3295 EMFILE => return error.ProcessFdQuotaExceeded,
3296 ENOMEM => return error.OutOfMemory,
3297 else => |err| return unexpectedErrno(err),
3298 }
3299}
3300
3301pub const MFD_NAME_PREFIX = "memfd:";
3302pub const MFD_MAX_NAME_LEN = NAME_MAX - MFD_NAME_PREFIX.len;
3303fn toMemFdPath(name: []const u8) ![MFD_MAX_NAME_LEN:0]u8 {
3304 var path_with_null: [MFD_MAX_NAME_LEN:0]u8 = undefined;
3305 // >= rather than > to make room for the null byte
3306 if (name.len >= MFD_MAX_NAME_LEN) return error.NameTooLong;
3307 mem.copy(u8, &path_with_null, name);
3308 path_with_null[name.len] = 0;
3309 return path_with_null;
3310}
3311
3312pub fn memfd_create(name: []const u8, flags: usize) !fd_t {
3313 const name_t = try toMemFdPath(name);
3314 return try memfd_createC(&name_t, flags);
3315}
lib/std/os/bits/linux.zig+36
......@@ -26,6 +26,7 @@ pub const uid_t = i32;
2626pub const gid_t = u32;
2727pub const clock_t = isize;
2828
29pub const NAME_MAX = 255;
2930pub const PATH_MAX = 4096;
3031pub const IOV_MAX = 1024;
3132
......@@ -1417,3 +1418,38 @@ pub const POLLHUP = 0x010;
14171418pub const POLLNVAL = 0x020;
14181419pub const POLLRDNORM = 0x040;
14191420pub const POLLRDBAND = 0x080;
1421
1422pub const MFD_CLOEXEC = 0x0001;
1423pub const MFD_ALLOW_SEALING = 0x0002;
1424pub const MFD_HUGETLB = 0x0004;
1425pub const MFD_ALL_FLAGS = MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_HUGETLB;
1426
1427pub const HUGETLB_FLAG_ENCODE_SHIFT = 26;
1428pub const HUGETLB_FLAG_ENCODE_MASK = 0x3f;
1429pub const HUGETLB_FLAG_ENCODE_64KB = 16 << HUGETLB_FLAG_ENCODE_SHIFT;
1430pub const HUGETLB_FLAG_ENCODE_512KB = 19 << HUGETLB_FLAG_ENCODE_SHIFT;
1431pub const HUGETLB_FLAG_ENCODE_1MB = 20 << HUGETLB_FLAG_ENCODE_SHIFT;
1432pub const HUGETLB_FLAG_ENCODE_2MB = 21 << HUGETLB_FLAG_ENCODE_SHIFT;
1433pub const HUGETLB_FLAG_ENCODE_8MB = 23 << HUGETLB_FLAG_ENCODE_SHIFT;
1434pub const HUGETLB_FLAG_ENCODE_16MB = 24 << HUGETLB_FLAG_ENCODE_SHIFT;
1435pub const HUGETLB_FLAG_ENCODE_32MB = 25 << HUGETLB_FLAG_ENCODE_SHIFT;
1436pub const HUGETLB_FLAG_ENCODE_256MB = 28 << HUGETLB_FLAG_ENCODE_SHIFT;
1437pub const HUGETLB_FLAG_ENCODE_512MB = 29 << HUGETLB_FLAG_ENCODE_SHIFT;
1438pub const HUGETLB_FLAG_ENCODE_1GB = 30 << HUGETLB_FLAG_ENCODE_SHIFT;
1439pub const HUGETLB_FLAG_ENCODE_2GB = 31 << HUGETLB_FLAG_ENCODE_SHIFT;
1440pub const HUGETLB_FLAG_ENCODE_16GB = 34 << HUGETLB_FLAG_ENCODE_SHIFT;
1441
1442pub const MFD_HUGE_SHIFT = HUGETLB_FLAG_ENCODE_SHIFT;
1443pub const MFD_HUGE_MASK = HUGETLB_FLAG_ENCODE_MASK;
1444pub const MFD_HUGE_64KB = HUGETLB_FLAG_ENCODE_64KB;
1445pub const MFD_HUGE_512KB = HUGETLB_FLAG_ENCODE_512KB;
1446pub const MFD_HUGE_1MB = HUGETLB_FLAG_ENCODE_1MB;
1447pub const MFD_HUGE_2MB = HUGETLB_FLAG_ENCODE_2MB;
1448pub const MFD_HUGE_8MB = HUGETLB_FLAG_ENCODE_8MB;
1449pub const MFD_HUGE_16MB = HUGETLB_FLAG_ENCODE_16MB;
1450pub const MFD_HUGE_32MB = HUGETLB_FLAG_ENCODE_32MB;
1451pub const MFD_HUGE_256MB = HUGETLB_FLAG_ENCODE_256MB;
1452pub const MFD_HUGE_512MB = HUGETLB_FLAG_ENCODE_512MB;
1453pub const MFD_HUGE_1GB = HUGETLB_FLAG_ENCODE_1GB;
1454pub const MFD_HUGE_2GB = HUGETLB_FLAG_ENCODE_2GB;
1455pub const MFD_HUGE_16GB = HUGETLB_FLAG_ENCODE_16GB;
lib/std/os/linux.zig+4
......@@ -1110,6 +1110,10 @@ pub fn io_uring_register(fd: i32, opcode: u32, arg: ?*const c_void, nr_args: u32
11101110 return syscall4(SYS_io_uring_register, @bitCast(usize, @as(isize, fd)), opcode, @ptrToInt(arg), nr_args);
11111111}
11121112
1113pub fn memfd_create(name: [*:0]const u8, flags: usize) usize {
1114 return syscall2(SYS_memfd_create, @ptrToInt(name), flags);
1115}
1116
11131117test "" {
11141118 if (builtin.os == .linux) {
11151119 _ = @import("linux/test.zig");