diff --git a/scheme/debug.rs b/scheme/debug.rs
index 27ab62614ccfa9a76397c89d28554ba6e9a03d88..8a8f556a8e47c15de9b74eee2c89ae792c21b14c 100644
--- a/scheme/debug.rs
+++ b/scheme/debug.rs
@@ -33,7 +33,7 @@ impl Scheme for DebugScheme {
         Ok(0)
     }
 
-    fn dup(&self, _file: usize) -> Result<usize> {
+    fn dup(&self, _file: usize, _buf: &[u8]) -> Result<usize> {
         Ok(0)
     }
 
diff --git a/scheme/env.rs b/scheme/env.rs
index 4a51485001fa96755ed3b68459e8342b71c0146d..3c88b1e19ea5eddaefe18470ec9b0e3d8720e937 100644
--- a/scheme/env.rs
+++ b/scheme/env.rs
@@ -88,7 +88,7 @@ impl Scheme for EnvScheme {
         }
     }
 
-    fn dup(&self, id: usize) -> Result<usize> {
+    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
         let new_handle = {
             let handles = self.handles.read();
             let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
diff --git a/scheme/event.rs b/scheme/event.rs
index cca7420c404aa661f6ec0aaa28452ac89e6c3886..2266141eba0cab79d33d452f22f3b172e7830e9d 100644
--- a/scheme/event.rs
+++ b/scheme/event.rs
@@ -39,7 +39,7 @@ impl Scheme for EventScheme {
         Ok(id)
     }
 
-    fn dup(&self, id: usize) -> Result<usize> {
+    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
         let handle = {
             let handles = self.handles.read();
             let handle_weak = handles.get(&id).ok_or(Error::new(EBADF))?;
diff --git a/scheme/initfs.rs b/scheme/initfs.rs
index 18696ed0f8fee306fc6d867e8ecaa0f214d95f40..99f1f7d277009317b3d4f8033d5c4ccace40ff70 100644
--- a/scheme/initfs.rs
+++ b/scheme/initfs.rs
@@ -57,7 +57,7 @@ impl Scheme for InitFsScheme {
         Err(Error::new(ENOENT))
     }
 
-    fn dup(&self, id: usize) -> Result<usize> {
+    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
         let (path, data, mode, seek) = {
             let handles = self.handles.read();
             let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
diff --git a/scheme/irq.rs b/scheme/irq.rs
index f91118e870e079a5b7cc55fc7d2198ac2a8eb340..a20aca71c39efa570a3744a348659e8b4c6c9f93 100644
--- a/scheme/irq.rs
+++ b/scheme/irq.rs
@@ -40,7 +40,7 @@ impl Scheme for IrqScheme {
         }
     }
 
-    fn dup(&self, file: usize) -> Result<usize> {
+    fn dup(&self, file: usize, _buf: &[u8]) -> Result<usize> {
         Ok(file)
     }
 
diff --git a/scheme/pipe.rs b/scheme/pipe.rs
index 35dfd004f756ee727ed765f908b764b9eb929c78..49d48956f34e2eb59403122c00414ad133dab2aa 100644
--- a/scheme/pipe.rs
+++ b/scheme/pipe.rs
@@ -42,7 +42,7 @@ pub fn pipe(flags: usize) -> (usize, usize) {
 pub struct PipeScheme;
 
 impl Scheme for PipeScheme {
-    fn dup(&self, id: usize) -> Result<usize> {
+    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
         let mut pipes = pipes_mut();
 
         let read_option = pipes.0.get(&id).map(|pipe| pipe.clone());
diff --git a/scheme/root.rs b/scheme/root.rs
index a2531328c0eb6480165fdfad33e08f7c7b79c21e..737e74b665f8e9fca93bfea4b69f794b139efe78 100644
--- a/scheme/root.rs
+++ b/scheme/root.rs
@@ -56,7 +56,7 @@ impl Scheme for RootScheme {
         }
     }
 
-    fn dup(&self, file: usize) -> Result<usize> {
+    fn dup(&self, file: usize, _buf: &[u8]) -> Result<usize> {
         let mut handles = self.handles.write();
         let inner = {
             let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
@@ -89,12 +89,24 @@ impl Scheme for RootScheme {
         inner.write(buf)
     }
 
-    fn fevent(&self, file: usize, _flags: usize) -> Result<usize> {
-        Ok(file)
+    fn fevent(&self, file: usize, flags: usize) -> Result<usize> {
+        let inner = {
+            let handles = self.handles.read();
+            let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
+            inner.clone()
+        };
+
+        inner.fevent(flags)
     }
 
-    fn fsync(&self, _file: usize) -> Result<usize> {
-        Ok(0)
+    fn fsync(&self, file: usize) -> Result<usize> {
+        let inner = {
+            let handles = self.handles.read();
+            let inner = handles.get(&file).ok_or(Error::new(EBADF))?;
+            inner.clone()
+        };
+
+        inner.fsync()
     }
 
     fn close(&self, file: usize) -> Result<usize> {
diff --git a/scheme/sys/mod.rs b/scheme/sys/mod.rs
index 917b9071edb67386c316d2090a9cd2535fab04ce..7d560d37001fba627df760793c3ea0308749b328 100644
--- a/scheme/sys/mod.rs
+++ b/scheme/sys/mod.rs
@@ -92,7 +92,7 @@ impl Scheme for SysScheme {
         Err(Error::new(ENOENT))
     }
 
-    fn dup(&self, id: usize) -> Result<usize> {
+    fn dup(&self, id: usize, _buf: &[u8]) -> Result<usize> {
         let (path, data, mode, seek) = {
             let handles = self.handles.read();
             let handle = handles.get(&id).ok_or(Error::new(EBADF))?;
diff --git a/scheme/user.rs b/scheme/user.rs
index 8f1c95a7d47880f81797a5ceecc5f911e207b471..28548217750a7885e98a5efa0646b5a8b0568b95 100644
--- a/scheme/user.rs
+++ b/scheme/user.rs
@@ -61,10 +61,7 @@ impl UserInner {
         };
 
         let len = self.todo.send(packet);
-        //TODO: Use O_NONBLOCK and send one notification
-        for _i in 0 .. len {
-            context::event::trigger(ROOT_SCHEME_ID.load(Ordering::SeqCst), self.handle_id, EVENT_READ, mem::size_of::<Packet>());
-        }
+        context::event::trigger(ROOT_SCHEME_ID.load(Ordering::SeqCst), self.handle_id, EVENT_READ, mem::size_of::<Packet>() * len);
 
         Error::demux(self.done.receive(&id))
     }
@@ -182,6 +179,14 @@ impl UserInner {
 
         Ok(i * packet_size)
     }
+
+    pub fn fevent(&self, _flags: usize) -> Result<usize> {
+        Ok(self.handle_id)
+    }
+
+    pub fn fsync(&self) -> Result<usize> {
+        Ok(0)
+    }
 }
 
 /// UserInner has to be wrapped
@@ -230,9 +235,12 @@ impl Scheme for UserScheme {
         result
     }
 
-    fn dup(&self, file: usize) -> Result<usize> {
+    fn dup(&self, file: usize, buf: &[u8]) -> Result<usize> {
         let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
-        inner.call(SYS_DUP, file, 0, 0)
+        let address = inner.capture(buf)?;
+        let result = inner.call(SYS_DUP, file, address, buf.len());
+        let _ = inner.release(address);
+        result
     }
 
     fn read(&self, file: usize, buf: &mut [u8]) -> Result<usize> {
diff --git a/syscall/fs.rs b/syscall/fs.rs
index 6c953e468f2caf6a272a4409c03a0122f9aaea87..ff4a51d8eaf5b9a8779316f2f9c5c886240bb978 100644
--- a/syscall/fs.rs
+++ b/syscall/fs.rs
@@ -83,10 +83,10 @@ pub fn open(path: &[u8], flags: usize) -> Result<usize> {
     let reference_opt = parts.next();
 
     let (scheme_id, file_id) = {
-        let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
+        let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
         let (scheme_id, scheme) = {
             let schemes = scheme::schemes();
-            let (scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
+            let (scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
             (scheme_id, scheme.clone())
         };
         let file_id = scheme.open(reference_opt.unwrap_or(b""), flags, uid, gid)?;
@@ -146,10 +146,10 @@ pub fn mkdir(path: &[u8], mode: u16) -> Result<usize> {
     let namespace_opt = parts.next();
     let reference_opt = parts.next();
 
-    let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
+    let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
     let scheme = {
         let schemes = scheme::schemes();
-        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
+        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
         scheme.clone()
     };
     scheme.mkdir(reference_opt.unwrap_or(b""), mode, uid, gid)
@@ -168,10 +168,10 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
     let namespace_opt = parts.next();
     let reference_opt = parts.next();
 
-    let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
+    let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
     let scheme = {
         let schemes = scheme::schemes();
-        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
+        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
         scheme.clone()
     };
     scheme.rmdir(reference_opt.unwrap_or(b""), uid, gid)
@@ -190,10 +190,10 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
     let namespace_opt = parts.next();
     let reference_opt = parts.next();
 
-    let namespace = namespace_opt.ok_or(Error::new(ENOENT))?;
+    let namespace = namespace_opt.ok_or(Error::new(ENODEV))?;
     let scheme = {
         let schemes = scheme::schemes();
-        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENOENT))?;
+        let (_scheme_id, scheme) = schemes.get_name(namespace).ok_or(Error::new(ENODEV))?;
         scheme.clone()
     };
     scheme.unlink(reference_opt.unwrap_or(b""), uid, gid)
@@ -222,7 +222,7 @@ pub fn close(fd: usize) -> Result<usize> {
 }
 
 /// Duplicate file descriptor
-pub fn dup(fd: usize) -> Result<usize> {
+pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
     let file = {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@@ -237,7 +237,7 @@ pub fn dup(fd: usize) -> Result<usize> {
             let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
             scheme.clone()
         };
-        scheme.dup(file.number)?
+        scheme.dup(file.number, buf)?
     };
 
     let contexts = context::contexts();
diff --git a/syscall/mod.rs b/syscall/mod.rs
index 8e1c190ebd49b75b882cf50bd2d51eac7948e9c3..2598cfa5a754d23d624b39adcf4831605e584bb1 100644
--- a/syscall/mod.rs
+++ b/syscall/mod.rs
@@ -39,7 +39,7 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
                 SYS_ARG_MSLICE => file_op_mut_slice(a, b, validate_slice_mut(c as *mut u8, d)?),
                 _ => match a {
                     SYS_CLOSE => close(b),
-                    SYS_DUP => dup(b),
+                    SYS_DUP => dup(b, validate_slice(c as *const u8, d)?),
                     SYS_FEVENT => fevent(b, c),
                     _ => file_op(a, b, c, d)
                 }
diff --git a/syscall/process.rs b/syscall/process.rs
index 39dd822c78bc88b1e3380bb865c31224a74801cb..e3cd886cffd01b783622fe7d3993051723fc4480 100644
--- a/syscall/process.rs
+++ b/syscall/process.rs
@@ -227,7 +227,7 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
                             let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?;
                             scheme.clone()
                         };
-                        let result = scheme.dup(file.number);
+                        let result = scheme.dup(file.number, &[]);
                         result
                     };
                     match result {