Преглед на файлове

feat(chdir): add syscall chdir

greatbridf преди 2 години
родител
ревизия
0be57320a7
променени са 7 файла, в които са добавени 44 реда и са изтрити 17 реда
  1. 3 0
      gblibc/include/unistd.h
  2. 1 1
      gblibc/private-include/syscall.h
  3. 5 0
      gblibc/src/unistd.c
  4. 3 1
      include/kernel/process.hpp
  5. 4 2
      src/kernel/process.cpp
  6. 20 5
      src/kernel/syscall.cpp
  7. 8 8
      user-space-program/sh.c

+ 3 - 0
gblibc/include/unistd.h

@@ -23,6 +23,9 @@ int execve(const char* pathname, char* const argv[], char* const envp[]);
 
 unsigned int sleep(unsigned int seconds);
 
+int chdir(const char* path);
+char* getcwd(char* buf, size_t bufsize);
+
 #ifdef __cplusplus
 }
 #endif

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

@@ -6,7 +6,7 @@
 #define SYS_fork (0x00)
 #define SYS_write (0x01)
 #define SYS_sleep (0x02)
-#define SYS_crash (0x03)
+#define SYS_chdir (0x03)
 #define SYS_exec (0x04)
 #define SYS_exit (0x05)
 #define SYS_wait (0x06)

+ 5 - 0
gblibc/src/unistd.c

@@ -32,3 +32,8 @@ unsigned int sleep(unsigned int seconds)
 {
     return syscall1(SYS_sleep, seconds);
 }
+
+int chdir(const char* path)
+{
+    return syscall1(SYS_chdir, (uint32_t)path);
+}

+ 3 - 1
include/kernel/process.hpp

@@ -14,6 +14,7 @@
 #include <types/map.hpp>
 #include <types/pair.hpp>
 #include <types/status.h>
+#include <types/string.hpp>
 #include <types/types.h>
 
 typedef size_t pid_t;
@@ -270,12 +271,13 @@ public:
     pid_t pid;
     pid_t ppid;
     filearr files;
+    types::string<> pwd;
 
 public:
     process(process&& val);
     process(const process&);
 
-    explicit process(pid_t ppid, bool system = true);
+    explicit process(pid_t ppid, bool system = true, types::string<>&& path = "/");
 
     constexpr bool is_system(void) const
     {

+ 4 - 2
src/kernel/process.cpp

@@ -53,6 +53,7 @@ process::process(process&& val)
     , pid(val.pid)
     , ppid(val.ppid)
     , files(types::move(val.files))
+    , pwd(types::move(val.pwd))
 {
     if (current_process == &val)
         current_process = this;
@@ -64,7 +65,7 @@ process::process(process&& val)
 }
 
 process::process(const process& parent)
-    : process { parent.pid, parent.is_system() }
+    : process { parent.pid, parent.is_system(), types::string<>(parent.pwd) }
 {
     for (auto& area : parent.mms) {
         if (area.is_ident())
@@ -76,11 +77,12 @@ process::process(const process& parent)
     this->files.dup(parent.files);
 }
 
-process::process(pid_t _ppid, bool _system)
+process::process(pid_t _ppid, bool _system, types::string<>&& path)
     : mms(*kernel_mms)
     , attr { .system = _system }
     , pid { process::alloc_pid() }
     , ppid { _ppid }
+    , pwd { path }
 {
 }
 

+ 20 - 5
src/kernel/syscall.cpp

@@ -122,10 +122,25 @@ void _syscall_sleep(interrupt_stack* data)
     schedule();
 }
 
-void _syscall_crash(interrupt_stack*)
+void _syscall_chdir(interrupt_stack* data)
 {
-    kmsg("\nan error occurred while executing command\n");
-    freeze();
+    const char* path = reinterpret_cast<const char*>(data->s_regs.edi);
+    auto* dir = fs::vfs_open(path);
+    if (!dir) {
+        // set errno ENOTFOUND
+        SYSCALL_SET_RETURN_VAL_EAX(-1);
+        return;
+    }
+
+    if (!dir->ind->flags.in.directory) {
+        // set errno ENOTDIR
+        SYSCALL_SET_RETURN_VAL_EAX(-1);
+        return;
+    }
+
+    current_process->pwd = path;
+
+    SYSCALL_SET_RETURN_VAL_EAX(0);
 }
 
 // syscall_exec(const char* exec, const char** argv)
@@ -161,7 +176,7 @@ void _syscall_exit(interrupt_stack* data)
 
     // TODO: terminating a thread only
     if (current_thread->owner->thds.size() != 1) {
-        _syscall_crash(data);
+        assert(false);
     }
 
     // terminating a whole process:
@@ -270,7 +285,7 @@ void init_syscall(void)
     syscall_handlers[0] = _syscall_fork;
     syscall_handlers[1] = _syscall_write;
     syscall_handlers[2] = _syscall_sleep;
-    syscall_handlers[3] = _syscall_crash;
+    syscall_handlers[3] = _syscall_chdir;
     syscall_handlers[4] = _syscall_exec;
     syscall_handlers[5] = _syscall_exit;
     syscall_handlers[6] = _syscall_wait;

+ 8 - 8
user-space-program/sh.c

@@ -212,14 +212,14 @@ main(void)
   
   // Read and run input commands.
   while(getcmd(buf, sizeof(buf)) >= 0){
-    // if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' '){
-    //   // Clumsy but will have to do for now.
-    //   // Chdir has no effect on the parent if run in the child.
-    //   buf[strlen(buf)-1] = 0;  // chop \n
-    //   if(chdir(buf+3) < 0)
-    //     printf("cannot cd %s\n", buf+3);
-    //   continue;
-    // }
+    if(buf[0] == 'c' && buf[1] == 'd' && buf[2] == ' ')
+    {
+      // Clumsy but will have to do for now.
+      // Chdir has no effect on the parent if run in the child.
+      if(chdir(buf+3) < 0)
+        printf("cannot cd %s\n", buf+3);
+      continue;
+    }
     if(fork1() == 0)
       runcmd(parsecmd(buf));
     int code;