Browse Source

feat: close() syscall and shell redirection

greatbridf 2 years ago
parent
commit
ca1a736d4f

+ 4 - 2
gblibc/include/unistd.h

@@ -6,9 +6,9 @@
 #undef STDOUT_FILENO
 #undef STDIN_FILENO
 #undef STDERR_FILENO
-#define STDOUT_FILENO (0)
 #define STDIN_FILENO (0)
-#define STDERR_FILENO (0)
+#define STDOUT_FILENO (1)
+#define STDERR_FILENO (2)
 
 #ifdef __cplusplus
 extern "C" {
@@ -17,6 +17,8 @@ extern "C" {
 ssize_t read(int fd, void* buf, size_t count);
 ssize_t write(int fd, const void* buf, size_t count);
 
+int close(int fd);
+
 void __attribute__((noreturn)) _exit(int code);
 pid_t fork(void);
 int execve(const char* pathname, char* const argv[], char* const envp[]);

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

@@ -16,6 +16,7 @@
 #define SYS_getcwd (0x0a)
 #define SYS_setsid (0x0b)
 #define SYS_getsid (0x0c)
+#define SYS_close (0x0d)
 
 #ifdef __cplusplus
 extern "C" {

+ 5 - 0
gblibc/src/unistd.c

@@ -11,6 +11,11 @@ ssize_t write(int fd, const void* buf, size_t count)
     return syscall3(SYS_write, fd, (uint32_t)buf, count);
 }
 
+int close(int fd)
+{
+    return syscall1(SYS_close, fd);
+}
+
 _Noreturn void _exit(int code)
 {
     (void)syscall1(SYS_exit, code);

+ 1 - 0
include/kernel/errno.h

@@ -23,5 +23,6 @@ extern uint32_t* _get_errno(void);
 #define ENOTDIR (1 << 5)
 #define ENOTFOUND (1 << 6)
 #define ECHILD (1 << 7)
+#define EBADF (1 << 8)
 
 #endif

+ 11 - 8
include/kernel/process.hpp

@@ -152,7 +152,6 @@ public:
     private:
         inline static container_type* files;
         array_type arr;
-        int next_fd = 0;
 
     public:
         inline static void init_global_file_container(void)
@@ -177,18 +176,22 @@ public:
         constexpr filearr(void) = default;
         constexpr filearr(filearr&& val)
             : arr { types::move(val.arr) }
-            , next_fd { val.next_fd }
         {
-            val.next_fd = 0;
         }
 
-        constexpr void dup(const filearr& orig)
+        constexpr int _next_fd(void) const
         {
-            if (this->next_fd)
-                return;
+            int fd = 0;
+
+            for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter)
+                if (iter->key == fd)
+                    ++fd;
 
-            this->next_fd = orig.next_fd;
+            return fd;
+        }
 
+        constexpr void dup(const filearr& orig)
+        {
             for (auto iter : orig.arr) {
                 this->arr.insert(types::make_pair(iter.key, iter.value));
                 ++iter.value->ref;
@@ -234,7 +237,7 @@ public:
                 0,
                 1 });
 
-            int fd = next_fd++;
+            int fd = _next_fd();
             arr.insert(types::make_pair(fd, iter));
             return fd;
         }

+ 37 - 0
include/types/map.hpp

@@ -220,6 +220,43 @@ public:
                 second = tmp;
             }
 
+            if (second->is_root()) {
+                node* tmp = first;
+                first = second;
+                second = tmp;
+            }
+
+            if (first->is_root()) {
+                node* sl = second->left;
+                node* sr = second->right;
+
+                if (sl)
+                    sl->parent = first;
+                if (sr)
+                    sr->parent = first;
+
+                if (second->is_right_child()) {
+                    second->left = first->left;
+                    second->right = first;
+
+                    if (second->left)
+                        second->left->parent = second;
+                } else {
+                    second->right = first->right;
+                    second->left = first;
+
+                    if (second->right)
+                        second->right->parent = second;
+                }
+
+                first->left = sl;
+                first->right = sr;
+                first->parent = second;
+
+                second->parent = nullptr;
+                return;
+            }
+
             node* p = first->parent;
             node* cl = first->left;
             node* cr = first->right;

+ 16 - 0
src/kernel/syscall.cpp

@@ -69,6 +69,10 @@ int _syscall_write(interrupt_stack* data)
     size_t n = data->s_regs.edx;
 
     auto* file = current_process->files[fd];
+
+    if (!file)
+        return -EBADF;
+
     if (file->type == fs::file::types::directory)
         return GB_FAILED;
 
@@ -84,6 +88,10 @@ int _syscall_read(interrupt_stack* data)
     size_t n = data->s_regs.edx;
 
     auto* file = current_process->files[fd];
+
+    if (!file)
+        return -EBADF;
+
     if (file->type == fs::file::types::directory)
         return GB_FAILED;
 
@@ -291,6 +299,13 @@ int _syscall_getsid(interrupt_stack* data)
     return proc->sid;
 }
 
+int _syscall_close(interrupt_stack* data)
+{
+    int fd = data->s_regs.edi;
+    current_process->files.close(fd);
+    return 0;
+}
+
 extern "C" void syscall_entry(interrupt_stack* data)
 {
     int ret = syscall_handlers[data->s_regs.eax](data);
@@ -316,4 +331,5 @@ void init_syscall(void)
     syscall_handlers[10] = _syscall_getcwd;
     syscall_handlers[11] = _syscall_setsid;
     syscall_handlers[12] = _syscall_getsid;
+    syscall_handlers[13] = _syscall_close;
 }

+ 1 - 1
user-space-program/hello-world.s

@@ -8,7 +8,7 @@ main:
 	movl $0xacacacac, %edx
 
 	movl $0x01, %eax
-	movl $0, %edi
+	movl $1, %edi
 	movl $_str, %esi
 	movl $_str_size, %ecx
 	movl (%ecx), %edx

+ 1 - 1
user-space-program/interrupt-test.s

@@ -14,7 +14,7 @@ main:
 	movl %eax, %ecx
 # write
 	movl $1, %eax
-	movl $0, %edi
+	movl $1, %edi
 	movl $__user_interrupt_test_string, %esi
 	movl $(__user_interrupt_test_string_end - __user_interrupt_test_string), %edx
 	int $0x80

+ 18 - 17
user-space-program/sh.c

@@ -116,7 +116,7 @@ runcmd(struct cmd *cmd)
   struct execcmd *ecmd;
   struct listcmd *lcmd;
 //   struct pipecmd *pcmd;
-//   struct redircmd *rcmd;
+  struct redircmd *rcmd;
 
   if(cmd == 0)
     _exit(-1);
@@ -134,15 +134,15 @@ runcmd(struct cmd *cmd)
     printf("exec %s failed\n", ecmd->argv[0]);
     break;
 
-//   case REDIR:
-//     rcmd = (struct redircmd*)cmd;
-//     close(rcmd->fd);
-//     if(open(rcmd->file, rcmd->mode) < 0){
-//       printf("open %s failed\n", rcmd->file);
-//       _exit(-1);
-//     }
-//     runcmd(rcmd->cmd);
-//     break;
+  case REDIR:
+    rcmd = (struct redircmd*)cmd;
+    close(rcmd->fd);
+    if(open(rcmd->file, rcmd->mode) < 0){
+      printf("open %s failed\n", rcmd->file);
+      _exit(-1);
+    }
+    runcmd(rcmd->cmd);
+    break;
 
   case LIST:
     lcmd = (struct listcmd*)cmd;
@@ -202,13 +202,14 @@ main(void)
 {
   static char buf[100];
   
-//   // Assumes three file descriptors open.
-//   while((fd = open("console", 0)) >= 0){
-//     if(fd >= 3){
-//       close(fd);
-//       break;
-//     }
-//   }
+  int fd = 0;
+  // Assumes three file descriptors open.
+  while((fd = open("/dev/console", 0)) >= 0){
+    if(fd >= 3){
+      close(fd);
+      break;
+    }
+  }
   
   // Read and run input commands.
   while(getcmd(buf, sizeof(buf)) >= 0){