authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-16 11:39:18+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-18 13:45:52-04:00
log4843c3b4c386008418ff8ab7238feebab3711352
tree9d6ae6578a92bde27f718a6597a9872b486f2ead
parentb1537b525fa0cd8d51ff89519254db0f066fc04b
signaturelock-open Commit is signed but in an unrecognized format.

std: Introduce fnctl wrapper


7 files changed, 67 insertions(+), 1 deletions(-)

lib/std/os.zig+25
...@@ -3163,6 +3163,31 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {...@@ -3163,6 +3163,31 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
3163 }3163 }
3164}3164}
31653165
3166pub const FcntlError = error{
3167 PermissionDenied,
3168 FileBusy,
3169 ProcessFdQuotaExceeded,
3170 Locked,
3171} || UnexpectedError;
3172
3173pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize {
3174 while (true) {
3175 const rc = system.fcntl(fd, cmd, arg);
3176 switch (errno(rc)) {
3177 0 => return @intCast(usize, rc),
3178 EINTR => continue,
3179 EACCES => return error.Locked,
3180 EBADF => unreachable,
3181 EBUSY => return error.FileBusy,
3182 EINVAL => unreachable, // invalid parameters
3183 EPERM => return error.PermissionDenied,
3184 EMFILE => return error.ProcessFdQuotaExceeded,
3185 ENOTDIR => unreachable, // invalid parameter
3186 else => |err| return unexpectedErrno(err),
3187 }
3188 }
3189}
3190
3166pub const RealPathError = error{3191pub const RealPathError = error{
3167 FileNotFound,3192 FileNotFound,
3168 AccessDenied,3193 AccessDenied,
lib/std/os/bits/dragonfly.zig+2
...@@ -283,6 +283,8 @@ pub const F_LOCK = 1;...@@ -283,6 +283,8 @@ pub const F_LOCK = 1;
283pub const F_TLOCK = 2;283pub const F_TLOCK = 2;
284pub const F_TEST = 3;284pub const F_TEST = 3;
285285
286pub const FD_CLOEXEC = 1;
287
286pub const AT_FDCWD = -328243;288pub const AT_FDCWD = -328243;
287pub const AT_SYMLINK_NOFOLLOW = 1;289pub const AT_SYMLINK_NOFOLLOW = 1;
288pub const AT_REMOVEDIR = 2;290pub const AT_REMOVEDIR = 2;
lib/std/os/bits/freebsd.zig+2
...@@ -355,6 +355,8 @@ pub const F_GETOWN_EX = 16;...@@ -355,6 +355,8 @@ pub const F_GETOWN_EX = 16;
355355
356pub const F_GETOWNER_UIDS = 17;356pub const F_GETOWNER_UIDS = 17;
357357
358pub const FD_CLOEXEC = 1;
359
358pub const SEEK_SET = 0;360pub const SEEK_SET = 0;
359pub const SEEK_CUR = 1;361pub const SEEK_CUR = 1;
360pub const SEEK_END = 2;362pub const SEEK_END = 2;
lib/std/os/bits/linux.zig+2
...@@ -136,6 +136,8 @@ pub const MAP_FIXED_NOREPLACE = 0x100000;...@@ -136,6 +136,8 @@ pub const MAP_FIXED_NOREPLACE = 0x100000;
136/// For anonymous mmap, memory could be uninitialized136/// For anonymous mmap, memory could be uninitialized
137pub const MAP_UNINITIALIZED = 0x4000000;137pub const MAP_UNINITIALIZED = 0x4000000;
138138
139pub const FD_CLOEXEC = 1;
140
139pub const F_OK = 0;141pub const F_OK = 0;
140pub const X_OK = 1;142pub const X_OK = 1;
141pub const W_OK = 2;143pub const W_OK = 2;
lib/std/os/bits/netbsd.zig+2
...@@ -312,6 +312,8 @@ pub const F_GETLK = 7;...@@ -312,6 +312,8 @@ pub const F_GETLK = 7;
312pub const F_SETLK = 8;312pub const F_SETLK = 8;
313pub const F_SETLKW = 9;313pub const F_SETLKW = 9;
314314
315pub const FD_CLOEXEC = 1;
316
315pub const SEEK_SET = 0;317pub const SEEK_SET = 0;
316pub const SEEK_CUR = 1;318pub const SEEK_CUR = 1;
317pub const SEEK_END = 2;319pub const SEEK_END = 2;
lib/std/os/linux.zig+4
...@@ -588,6 +588,10 @@ pub fn waitpid(pid: pid_t, status: *u32, flags: u32) usize {...@@ -588,6 +588,10 @@ pub fn waitpid(pid: pid_t, status: *u32, flags: u32) usize {
588 return syscall4(SYS_wait4, @bitCast(usize, @as(isize, pid)), @ptrToInt(status), flags, 0);588 return syscall4(SYS_wait4, @bitCast(usize, @as(isize, pid)), @ptrToInt(status), flags, 0);
589}589}
590590
591pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize {
592 return syscall3(SYS_fcntl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, cmd)), arg);
593}
594
591var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);595var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime);
592596
593// We must follow the C calling convention when we call into the VDSO597// We must follow the C calling convention when we call into the VDSO
lib/std/os/test.zig+30-1
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const os = std.os;2const os = std.os;
3const testing = std.testing;3const testing = std.testing;
4const expect = std.testing.expect;4const expect = testing.expect;
5const expectEqual = testing.expectEqual;
5const io = std.io;6const io = std.io;
6const fs = std.fs;7const fs = std.fs;
7const mem = std.mem;8const mem = std.mem;
...@@ -446,3 +447,31 @@ test "getenv" {...@@ -446,3 +447,31 @@ test "getenv" {
446 expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);447 expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
447 }448 }
448}449}
450
451test "fcntl" {
452 if (builtin.os.tag == .windows)
453 return error.SkipZigTest;
454
455 const test_out_file = "os_tmp_test";
456
457 const file = try fs.cwd().createFile(test_out_file, .{});
458 defer file.close();
459
460 // Note: The test assumes createFile opens the file with O_CLOEXEC
461 {
462 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
463 expect((flags & os.FD_CLOEXEC) != 0);
464 }
465 {
466 _ = try os.fcntl(file.handle, os.F_SETFD, 0);
467 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
468 expect((flags & os.FD_CLOEXEC) == 0);
469 }
470 {
471 _ = try os.fcntl(file.handle, os.F_SETFD, os.FD_CLOEXEC);
472 const flags = try os.fcntl(file.handle, os.F_GETFD, 0);
473 expect((flags & os.FD_CLOEXEC) != 0);
474 }
475
476 try fs.cwd().deleteFile(test_out_file);
477}