From 059cc8078d778d238963525df8011635bc27bf66 Mon Sep 17 00:00:00 2001
From: Jeremy Soller <jackpot51@gmail.com>
Date: Wed, 27 Dec 2017 20:19:37 -0700
Subject: [PATCH] Add frename

---
 Cargo.lock         |  6 +++---
 Cargo.toml         |  2 +-
 src/scheme/user.rs |  8 ++++++++
 src/syscall/fs.rs  | 36 ++++++++++++++++++++++++++++++++++++
 src/syscall/mod.rs |  1 +
 syscall            |  2 +-
 6 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 2003e81b..efb0e69a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,13 +32,13 @@ dependencies = [
 
 [[package]]
 name = "kernel"
-version = "0.1.32"
+version = "0.1.33"
 dependencies = [
  "alloc_kernel 0.1.0",
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "goblin 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "raw-cpuid 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.32",
+ "redox_syscall 0.1.33",
  "spin 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -75,7 +75,7 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.32"
+version = "0.1.33"
 
 [[package]]
 name = "scroll"
diff --git a/Cargo.toml b/Cargo.toml
index 2f066eb3..3cee8c96 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "kernel"
-version = "0.1.32"
+version = "0.1.33"
 build = "build.rs"
 
 [lib]
diff --git a/src/scheme/user.rs b/src/scheme/user.rs
index 31b69bed..8ceb2843 100644
--- a/src/scheme/user.rs
+++ b/src/scheme/user.rs
@@ -334,6 +334,14 @@ impl Scheme for UserScheme {
         result
     }
 
+    fn frename(&self, file: usize, path: &[u8], _uid: u32, _gid: u32) -> Result<usize> {
+        let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
+        let address = inner.capture(path)?;
+        let result = inner.call(SYS_FRENAME, file, address, path.len());
+        let _ = inner.release(address);
+        result
+    }
+
     fn fstat(&self, file: usize, stat: &mut Stat) -> Result<usize> {
         let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
         let address = inner.capture_mut(stat)?;
diff --git a/src/syscall/fs.rs b/src/syscall/fs.rs
index 168d165c..6cd747a1 100644
--- a/src/syscall/fs.rs
+++ b/src/syscall/fs.rs
@@ -422,6 +422,42 @@ pub fn fevent(fd: FileHandle, flags: usize) -> Result<usize> {
     Ok(0)
 }
 
+pub fn frename(fd: FileHandle, path: &[u8]) -> Result<usize> {
+    let file = {
+        let contexts = context::contexts();
+        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+        let context = context_lock.read();
+        let file = context.get_file(fd).ok_or(Error::new(EBADF))?;
+        file
+    };
+
+    let (path_canon, uid, gid, scheme_ns) = {
+        let contexts = context::contexts();
+        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+        let context = context_lock.read();
+        (context.canonicalize(path), context.euid, context.egid, context.ens)
+    };
+
+    let mut parts = path_canon.splitn(2, |&b| b == b':');
+    let scheme_name_opt = parts.next();
+    let reference_opt = parts.next();
+
+    let scheme_name = scheme_name_opt.ok_or(Error::new(ENODEV))?;
+    let (scheme_id, scheme) = {
+        let schemes = scheme::schemes();
+        let (scheme_id, scheme) = schemes.get_name(scheme_ns, scheme_name).ok_or(Error::new(ENODEV))?;
+        (scheme_id, scheme.clone())
+    };
+
+    let description = file.description.read();
+
+    if scheme_id == description.scheme {
+        scheme.frename(description.number, reference_opt.unwrap_or(b""), uid, gid)
+    } else {
+        Err(Error::new(EXDEV))
+    }
+}
+
 pub fn funmap(virtual_address: usize) -> Result<usize> {
     if virtual_address == 0 {
         Ok(0)
diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs
index 793f23b2..d0ff5f32 100644
--- a/src/syscall/mod.rs
+++ b/src/syscall/mod.rs
@@ -64,6 +64,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
                         SYS_DUP2 => dup2(fd, FileHandle::from(c), validate_slice(d as *const u8, e)?).map(FileHandle::into),
                         SYS_FCNTL => fcntl(fd, c, d),
                         SYS_FEVENT => fevent(fd, c),
+                        SYS_FRENAME => frename(fd, validate_slice(c as *const u8, d)?),
                         SYS_FUNMAP => funmap(b),
                         _ => file_op(a, fd, c, d)
                     }
diff --git a/syscall b/syscall
index 3c765737..414b8e0b 160000
--- a/syscall
+++ b/syscall
@@ -1 +1 @@
-Subproject commit 3c765737a5e9146ffb241c67050c1be9bf28aab7
+Subproject commit 414b8e0be011c70d5c55692f4dd835184f33579f
-- 
GitLab