diff --git a/lib/std/fs.zig b/lib/std/fs.zig index de6be91f71..edb12e0f01 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -677,6 +677,20 @@ pub const Dir = struct { try std.event.Loop.instance.?.openatZ(self.fd, sub_path, os_flags, 0) else try os.openatC(self.fd, sub_path, os_flags, 0); + + var locked = false; + if (flags.lock) { + // TODO: integrate async I/O + try os.fcntlFlockBlocking(fd, &os.flock{ + .lock_type = if (flags.write) os.F_WRLCK else os.F_RDLCK, + .whence = os.SEEK_SET, + .start = 0, + .len = 0, + .pid = 0, + }); + locked = true; + } + return File{ .handle = fd, .io_mode = .blocking, diff --git a/lib/std/os.zig b/lib/std/os.zig index ed99c48021..ca007ecb44 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1140,6 +1140,14 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) allocator.free(envp_buf); } +/// Attempts to get lock the file, blocking if the file is locked. +pub fn fcntlFlockBlocking(fd: fd_t, flock_p: *flock) OpenError!void { + const rc = system.fcntlFlock(fd, F_SETLKW, flock_p); + if (rc < 0) { + std.debug.panic("fcntl error: {}\n", .{rc}); + } +} + /// Get an environment variable. /// See also `getenvZ`. pub fn getenv(key: []const u8) ?[]const u8 { diff --git a/lib/std/os/bits/linux/i386.zig b/lib/std/os/bits/linux/i386.zig index 2585785b13..e075f1826e 100644 --- a/lib/std/os/bits/linux/i386.zig +++ b/lib/std/os/bits/linux/i386.zig @@ -488,6 +488,14 @@ pub const MMAP2_UNIT = 4096; pub const VDSO_CGT_SYM = "__vdso_clock_gettime"; pub const VDSO_CGT_VER = "LINUX_2.6"; +pub const flock = extern struct { + lock_type: i16, + whence: i16, + start: off_t, + len: off_t, + pid: pid_t, +}; + pub const msghdr = extern struct { msg_name: ?*sockaddr, msg_namelen: socklen_t, diff --git a/lib/std/os/bits/linux/x86_64.zig b/lib/std/os/bits/linux/x86_64.zig index e92591d94e..97905e4a3e 100644 --- a/lib/std/os/bits/linux/x86_64.zig +++ b/lib/std/os/bits/linux/x86_64.zig @@ -456,6 +456,18 @@ pub const REG_TRAPNO = 20; pub const REG_OLDMASK = 21; pub const REG_CR2 = 22; +pub const F_RDLCK = 0; +pub const F_WRLCK = 1; +pub const F_UNLCK = 2; + +pub const flock = extern struct { + lock_type: i16, + whence: i16, + start: off_t, + len: off_t, + pid: pid_t, +}; + pub const msghdr = extern struct { msg_name: ?*sockaddr, msg_namelen: socklen_t, diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index ba7356d62c..389f110d0a 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -219,6 +219,10 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of } } +pub fn fcntlFlock(fd: fd_t, cmd: i32, flock_p: *flock) usize { + return syscall3(SYS_fcntl, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, cmd)), @ptrToInt(flock_p)); +} + pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize { return syscall3(SYS_mprotect, @ptrToInt(address), length, protection); }