瀏覽代碼

feat(dup): add syscall dup and dup2

greatbridf 2 年之前
父節點
當前提交
c268e31f28
共有 6 個文件被更改,包括 58 次插入8 次删除
  1. 3 0
      gblibc/include/unistd.h
  2. 2 0
      gblibc/private-include/syscall.h
  3. 10 0
      gblibc/src/unistd.c
  4. 27 7
      include/kernel/process.hpp
  5. 1 1
      src/kernel/process.cpp
  6. 15 0
      src/kernel/syscall.cpp

+ 3 - 0
gblibc/include/unistd.h

@@ -17,6 +17,9 @@ extern "C" {
 ssize_t read(int fd, void* buf, size_t count);
 ssize_t write(int fd, const void* buf, size_t count);
 
+int dup(int oldfd);
+int dup2(int oldfd, int newfd);
+
 int close(int fd);
 
 void __attribute__((noreturn)) _exit(int code);

+ 2 - 0
gblibc/private-include/syscall.h

@@ -17,6 +17,8 @@
 #define SYS_setsid (0x0b)
 #define SYS_getsid (0x0c)
 #define SYS_close (0x0d)
+#define SYS_dup (0x0e)
+#define SYS_dup2 (0x0f)
 
 #ifdef __cplusplus
 extern "C" {

+ 10 - 0
gblibc/src/unistd.c

@@ -11,6 +11,16 @@ ssize_t write(int fd, const void* buf, size_t count)
     return syscall3(SYS_write, fd, (uint32_t)buf, count);
 }
 
+int dup(int oldfd)
+{
+    return syscall1(SYS_dup, oldfd);
+}
+
+int dup2(int oldfd, int newfd)
+{
+    return syscall2(SYS_dup2, oldfd, newfd);
+}
+
 int close(int fd)
 {
     return syscall1(SYS_close, fd);

+ 27 - 7
include/kernel/process.hpp

@@ -169,6 +169,17 @@ public:
                 --iter->ref;
         }
 
+        constexpr int _next_fd(void) const
+        {
+            int fd = 0;
+
+            for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter)
+                if (iter->key == fd)
+                    ++fd;
+
+            return fd;
+        }
+
     public:
         constexpr filearr(const filearr&) = delete;
         constexpr filearr& operator=(const filearr&) = delete;
@@ -179,18 +190,27 @@ public:
         {
         }
 
-        constexpr int _next_fd(void) const
+        constexpr int dup(int old_fd)
         {
-            int fd = 0;
+            return dup2(old_fd, _next_fd());
+        }
 
-            for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter)
-                if (iter->key == fd)
-                    ++fd;
+        // TODO: the third parameter should be int flags
+        //       determining whether the fd should be closed
+        //       after exec() (FD_CLOEXEC)
+        constexpr int dup2(int old_fd, int new_fd)
+        {
+            close(new_fd);
 
-            return fd;
+            auto iter = arr.find(old_fd);
+            if (!iter)
+                return -EBADF;
+
+            this->arr.insert(types::make_pair(new_fd, iter->value));
+            return new_fd;
         }
 
-        constexpr void dup(const filearr& orig)
+        constexpr void dup_all(const filearr& orig)
         {
             for (auto iter : orig.arr) {
                 this->arr.insert(types::make_pair(iter.key, iter.value));

+ 1 - 1
src/kernel/process.cpp

@@ -120,7 +120,7 @@ process::process(const process& parent)
         mms.mirror_area(area);
     }
 
-    this->files.dup(parent.files);
+    this->files.dup_all(parent.files);
 }
 
 process::process(pid_t _ppid,

+ 15 - 0
src/kernel/syscall.cpp

@@ -300,6 +300,19 @@ int _syscall_close(interrupt_stack* data)
     return 0;
 }
 
+int _syscall_dup(interrupt_stack* data)
+{
+    int old_fd = data->s_regs.edi;
+    return current_process->files.dup(old_fd);
+}
+
+int _syscall_dup2(interrupt_stack* data)
+{
+    int old_fd = data->s_regs.edi;
+    int new_fd = data->s_regs.esi;
+    return current_process->files.dup2(old_fd, new_fd);
+}
+
 extern "C" void syscall_entry(interrupt_stack* data)
 {
     int ret = syscall_handlers[data->s_regs.eax](data);
@@ -326,4 +339,6 @@ void init_syscall(void)
     syscall_handlers[11] = _syscall_setsid;
     syscall_handlers[12] = _syscall_getsid;
     syscall_handlers[13] = _syscall_close;
+    syscall_handlers[14] = _syscall_dup;
+    syscall_handlers[15] = _syscall_dup2;
 }