From bae8bb68df99d4e8f6a5df7bd5f95a15dbef1e1c Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen@gmail.com>
Date: Tue, 16 May 2023 23:40:40 +0100
Subject: [PATCH] lockf implementation proposal

---
 src/c/fcntl.c                 |  6 +++---
 src/header/fcntl/mod.rs       |  8 ++++++-
 src/header/stdio/helpers.rs   |  4 ++--
 src/header/stdio/mod.rs       |  8 +++----
 src/header/sys_ioctl/redox.rs |  4 ++--
 src/header/unistd/mod.rs      | 40 ++++++++++++++++++++++++++++++++---
 src/platform/linux/mod.rs     |  2 +-
 src/platform/pal/mod.rs       |  2 +-
 src/platform/redox/mod.rs     |  2 +-
 9 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/src/c/fcntl.c b/src/c/fcntl.c
index 23c48fa1..cc67e4e6 100644
--- a/src/c/fcntl.c
+++ b/src/c/fcntl.c
@@ -14,13 +14,13 @@ int open(const char* filename, int flags, ...) {
     return sys_open(filename, flags, mode);
 }
 
-int sys_fcntl(int fildes, int cmd, int args);
+int sys_fcntl(int fildes, int cmd, unsigned long long args);
 
 int fcntl(int fildes, int cmd, ...) {
-    int args = 0;
+    unsigned long long args = 0;
     va_list ap;
     va_start(ap, cmd);
-    args = va_arg(ap, int);
+    args = va_arg(ap, unsigned long long);
     va_end(ap);
     return sys_fcntl(fildes, cmd, args);
 }
diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs
index 1e9975c6..d428d87f 100644
--- a/src/header/fcntl/mod.rs
+++ b/src/header/fcntl/mod.rs
@@ -28,11 +28,17 @@ pub const F_RDLCK: c_int = 0;
 pub const F_WRLCK: c_int = 1;
 pub const F_UNLCK: c_int = 2;
 
+pub const F_ULOCK: c_int = 0;
+pub const F_LOCK: c_int = 1;
+pub const F_TLOCK: c_int = 2;
+pub const F_TEST: c_int = 3;
+
 #[no_mangle]
 pub unsafe extern "C" fn creat(path: *const c_char, mode: mode_t) -> c_int {
     sys_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode)
 }
 #[repr(C)]
+#[derive(Clone, Copy, Default)]
 pub struct flock {
     pub l_type: c_short,
     pub l_whence: c_short,
@@ -41,7 +47,7 @@ pub struct flock {
     pub l_pid: pid_t,
 }
 #[no_mangle]
-pub extern "C" fn sys_fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
+pub extern "C" fn sys_fcntl(fildes: c_int, cmd: c_int, arg: c_ulonglong) -> c_int {
     Sys::fcntl(fildes, cmd, arg)
 }
 
diff --git a/src/header/stdio/helpers.rs b/src/header/stdio/helpers.rs
index dc42b100..f2924211 100644
--- a/src/header/stdio/helpers.rs
+++ b/src/header/stdio/helpers.rs
@@ -50,13 +50,13 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
     }
 
     if !strchr(mode, b'e' as i32).is_null() {
-        sys_fcntl(fd, F_SETFD, FD_CLOEXEC);
+        sys_fcntl(fd, F_SETFD, FD_CLOEXEC as c_ulonglong);
     }
 
     if *mode == 'a' as i8 {
         let f = sys_fcntl(fd, F_GETFL, 0);
         if (f & O_APPEND) == 0 {
-            sys_fcntl(fd, F_SETFL, f | O_APPEND);
+            sys_fcntl(fd, F_SETFL, (f | O_APPEND) as c_ulonglong);
         }
         flags |= F_APP;
     }
diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs
index a5ace892..79d7a1be 100644
--- a/src/header/stdio/mod.rs
+++ b/src/header/stdio/mod.rs
@@ -505,7 +505,7 @@ pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) ->
     }
 
     if flags & fcntl::O_CLOEXEC > 0 {
-        fcntl::sys_fcntl(fd, fcntl::F_SETFD, fcntl::FD_CLOEXEC);
+        fcntl::sys_fcntl(fd, fcntl::F_SETFD, fcntl::FD_CLOEXEC as c_ulonglong);
     }
 
     if let Some(f) = helpers::_fdopen(fd, mode) {
@@ -596,10 +596,10 @@ pub unsafe extern "C" fn freopen(
     if filename.is_null() {
         // Reopen stream in new mode
         if flags & fcntl::O_CLOEXEC > 0 {
-            fcntl::sys_fcntl(*stream.file, fcntl::F_SETFD, fcntl::FD_CLOEXEC);
+            fcntl::sys_fcntl(*stream.file, fcntl::F_SETFD, fcntl::FD_CLOEXEC as c_ulonglong);
         }
         flags &= !(fcntl::O_CREAT | fcntl::O_EXCL | fcntl::O_CLOEXEC);
-        if fcntl::sys_fcntl(*stream.file, fcntl::F_SETFL, flags) < 0 {
+        if fcntl::sys_fcntl(*stream.file, fcntl::F_SETFL, flags as c_ulonglong) < 0 {
             funlockfile(stream);
             fclose(stream);
             return ptr::null_mut();
@@ -615,7 +615,7 @@ pub unsafe extern "C" fn freopen(
         if *new.file == *stream.file {
             new.file.fd = -1;
         } else if Sys::dup2(*new.file, *stream.file) < 0
-            || fcntl::sys_fcntl(*stream.file, fcntl::F_SETFL, flags & fcntl::O_CLOEXEC) < 0
+            || fcntl::sys_fcntl(*stream.file, fcntl::F_SETFL, (flags & fcntl::O_CLOEXEC) as c_ulonglong) < 0
         {
             funlockfile(stream);
             fclose(new);
diff --git a/src/header/sys_ioctl/redox.rs b/src/header/sys_ioctl/redox.rs
index 8c0a2ea4..ab298026 100644
--- a/src/header/sys_ioctl/redox.rs
+++ b/src/header/sys_ioctl/redox.rs
@@ -63,7 +63,7 @@ fn dup_write<T>(fd: c_int, name: &str, t: &T) -> syscall::Result<usize> {
 pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int {
     match request {
         FIONBIO => {
-            let mut flags = fcntl::sys_fcntl(fd, fcntl::F_GETFL, 0);
+            let mut flags = fcntl::sys_fcntl(fd, fcntl::F_GETFL, 0usize);
             if flags < 0 {
                 return -1;
             }
@@ -72,7 +72,7 @@ pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) ->
             } else {
                 flags | fcntl::O_NONBLOCK
             };
-            if fcntl::sys_fcntl(fd, fcntl::F_SETFL, flags) < 0 {
+            if fcntl::sys_fcntl(fd, fcntl::F_SETFL, flags as c_ulonglong) < 0 {
                 -1
             } else {
                 0
diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs
index d443509b..cfe2fc53 100644
--- a/src/header/unistd/mod.rs
+++ b/src/header/unistd/mod.rs
@@ -451,9 +451,43 @@ pub unsafe extern "C" fn link(path1: *const c_char, path2: *const c_char) -> c_i
     Sys::link(path1, path2)
 }
 
-// #[no_mangle]
-pub extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
+    let mut fl = fcntl::flock {
+        l_type: fcntl::F_WRLCK as c_short,
+        l_whence: SEEK_CUR as c_short,
+        l_start: 0,
+        l_len: size,
+        l_pid: -1,
+    };
+
+    match function {
+        fcntl::F_TEST => {
+            fl.l_type = fcntl::F_RDLCK as c_short;
+            if fcntl::sys_fcntl(fildes, fcntl::F_GETLK, &mut fl as *mut _ as c_ulonglong) < 0 {
+                return -1;
+            }
+            if fl.l_type == fcntl::F_UNLCK as c_short || fl.l_pid == getpid() {
+                return 0;
+            }
+            platform::errno = errno::EACCES;
+            return -1;
+        },
+        fcntl::F_ULOCK => {
+            fl.l_type = fcntl::F_UNLCK as c_short;
+            return fcntl::sys_fcntl(fildes, fcntl::F_SETLK, &mut fl as *mut _ as c_ulonglong);
+        },
+        fcntl::F_TLOCK => {
+            return fcntl::sys_fcntl(fildes, fcntl::F_SETLK, &mut fl as *mut _ as c_ulonglong);
+        },
+        fcntl::F_LOCK => {
+            return fcntl::sys_fcntl(fildes, fcntl::F_SETLKW, &mut fl as *mut _ as c_ulonglong);
+        },
+        _ => {
+            platform::errno = errno::EINVAL;
+            return -1;
+        },
+    };
 }
 
 #[no_mangle]
diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs
index 59fb84f8..fa5e770b 100644
--- a/src/platform/linux/mod.rs
+++ b/src/platform/linux/mod.rs
@@ -210,7 +210,7 @@ impl Pal for Sys {
         res
     }
 
-    fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int {
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_ulonglong) -> c_int {
         e(unsafe { syscall!(FCNTL, fildes, cmd, arg) }) as c_int
     }
 
diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs
index 5c3f7b14..2f78c777 100644
--- a/src/platform/pal/mod.rs
+++ b/src/platform/pal/mod.rs
@@ -67,7 +67,7 @@ pub trait Pal {
 
     fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> c_int;
 
-    fn fcntl(fildes: c_int, cmd: c_int, arg: c_int) -> c_int;
+    fn fcntl(fildes: c_int, cmd: c_int, arg: c_ulonglong) -> c_int;
 
     fn fork() -> pid_t;
 
diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
index 6477939e..5e09657f 100644
--- a/src/platform/redox/mod.rs
+++ b/src/platform/redox/mod.rs
@@ -259,7 +259,7 @@ impl Pal for Sys {
         e(syscall::fchown(fd as usize, owner as u32, group as u32)) as c_int
     }
 
-    fn fcntl(fd: c_int, cmd: c_int, args: c_int) -> c_int {
+    fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> c_int {
         e(syscall::fcntl(fd as usize, cmd as usize, args as usize)) as c_int
     }
 
-- 
GitLab