Commit 9af0590a28

LeRoyce Pearson <leroycepearson@geemili.xyz>
2020-03-09 03:57:47
Add fnctlFlock system call, use it to lock files
1 parent 3110060
Changed files (5)
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,
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,
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);
 }
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,
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 {