| author | |
| committer | |
| log | 4843c3b4c386008418ff8ab7238feebab3711352 |
| tree | 9d6ae6578a92bde27f718a6597a9872b486f2ead |
| parent | b1537b525fa0cd8d51ff89519254db0f066fc04b |
| signature |
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 | } |
| 3165 | 3165 | ||
| 3166 | pub const FcntlError = error{ | ||
| 3167 | PermissionDenied, | ||
| 3168 | FileBusy, | ||
| 3169 | ProcessFdQuotaExceeded, | ||
| 3170 | Locked, | ||
| 3171 | } || UnexpectedError; | ||
| 3172 | |||
| 3173 | pub 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 | |||
| 3166 | pub const RealPathError = error{ | 3191 | pub 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; |
| 283 | pub const F_TLOCK = 2; | 283 | pub const F_TLOCK = 2; |
| 284 | pub const F_TEST = 3; | 284 | pub const F_TEST = 3; |
| 285 | 285 | ||
| 286 | pub const FD_CLOEXEC = 1; | ||
| 287 | |||
| 286 | pub const AT_FDCWD = -328243; | 288 | pub const AT_FDCWD = -328243; |
| 287 | pub const AT_SYMLINK_NOFOLLOW = 1; | 289 | pub const AT_SYMLINK_NOFOLLOW = 1; |
| 288 | pub const AT_REMOVEDIR = 2; | 290 | pub 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; |
| 355 | 355 | ||
| 356 | pub const F_GETOWNER_UIDS = 17; | 356 | pub const F_GETOWNER_UIDS = 17; |
| 357 | 357 | ||
| 358 | pub const FD_CLOEXEC = 1; | ||
| 359 | |||
| 358 | pub const SEEK_SET = 0; | 360 | pub const SEEK_SET = 0; |
| 359 | pub const SEEK_CUR = 1; | 361 | pub const SEEK_CUR = 1; |
| 360 | pub const SEEK_END = 2; | 362 | pub 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 uninitialized | 136 | /// For anonymous mmap, memory could be uninitialized |
| 137 | pub const MAP_UNINITIALIZED = 0x4000000; | 137 | pub const MAP_UNINITIALIZED = 0x4000000; |
| 138 | 138 | ||
| 139 | pub const FD_CLOEXEC = 1; | ||
| 140 | |||
| 139 | pub const F_OK = 0; | 141 | pub const F_OK = 0; |
| 140 | pub const X_OK = 1; | 142 | pub const X_OK = 1; |
| 141 | pub const W_OK = 2; | 143 | pub 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; |
| 312 | pub const F_SETLK = 8; | 312 | pub const F_SETLK = 8; |
| 313 | pub const F_SETLKW = 9; | 313 | pub const F_SETLKW = 9; |
| 314 | 314 | ||
| 315 | pub const FD_CLOEXEC = 1; | ||
| 316 | |||
| 315 | pub const SEEK_SET = 0; | 317 | pub const SEEK_SET = 0; |
| 316 | pub const SEEK_CUR = 1; | 318 | pub const SEEK_CUR = 1; |
| 317 | pub const SEEK_END = 2; | 319 | pub 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 | } |
| 590 | 590 | ||
| 591 | pub 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 | |||
| 591 | var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime); | 595 | var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime); |
| 592 | 596 | ||
| 593 | // We must follow the C calling convention when we call into the VDSO | 597 | // 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 @@ |
| 1 | const std = @import("../std.zig"); | 1 | const std = @import("../std.zig"); |
| 2 | const os = std.os; | 2 | const os = std.os; |
| 3 | const testing = std.testing; | 3 | const testing = std.testing; |
| 4 | const expect = std.testing.expect; | 4 | const expect = testing.expect; |
| 5 | const expectEqual = testing.expectEqual; | ||
| 5 | const io = std.io; | 6 | const io = std.io; |
| 6 | const fs = std.fs; | 7 | const fs = std.fs; |
| 7 | const mem = std.mem; | 8 | const 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 | |||
| 451 | test "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 | } |