Browse Source

feat(gblibc): add stat()

greatbridf 2 years ago
parent
commit
7e873a0e79
4 changed files with 34 additions and 5 deletions
  1. 1 0
      gblibc/include/sys/stat.h
  2. 1 0
      gblibc/private-include/syscall.h
  3. 11 0
      gblibc/src/stat.c
  4. 21 5
      src/kernel/syscall.cpp

+ 1 - 0
gblibc/include/sys/stat.h

@@ -25,6 +25,7 @@ struct stat {
     struct timespec st_ctim;
 };
 
+int stat(const char* pathname, struct stat* statbuf);
 int fstat(int fd, struct stat* statbuf);
 
 #ifdef __cplusplus

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

@@ -7,6 +7,7 @@
 #define SYS_write (1)
 #define SYS_open (2)
 #define SYS_close (3)
+#define SYS_stat (4)
 #define SYS_fstat (5)
 #define SYS_brk (12)
 #define SYS_ioctl (16)

+ 11 - 0
gblibc/src/stat.c

@@ -1,7 +1,18 @@
+#include <stdint.h>
 #include <errno.h>
 #include <syscall.h>
 #include <sys/stat.h>
 
+int stat(const char* pathname, struct stat* statbuf)
+{
+    int ret = syscall2(SYS_stat, (uint32_t)pathname, (uint32_t)statbuf);
+    if (ret < 0) {
+        errno = -ret;
+        return -1;
+    }
+    return ret;
+}
+
 int fstat(int fd, struct stat* statbuf)
 {
     int ret = syscall2(SYS_fstat, fd, (uint32_t)statbuf);

+ 21 - 5
src/kernel/syscall.cpp

@@ -480,6 +480,25 @@ int _syscall_brk(interrupt_stack* data)
     return (int)brk;
 }
 
+static inline int __stat(fs::inode* ind, fs::user_stat* buf)
+{
+    // TODO: use copy_to_user
+    assert(ind->fs->inode_stat(ind, buf) == GB_OK);
+    return 0;
+}
+
+int _syscall_stat(interrupt_stack* data)
+{
+    auto* pathname = (const char*)data->s_regs.edi;
+    auto* buf = (fs::user_stat*)data->s_regs.esi;
+
+    auto* dent = fs::vfs_open_proc(pathname);
+    if (!dent)
+        return -ENOENT;
+
+    return __stat(dent->ind, buf);
+}
+
 int _syscall_fstat(interrupt_stack* data)
 {
     int fd = data->s_regs.edi;
@@ -489,11 +508,7 @@ int _syscall_fstat(interrupt_stack* data)
     if (!file || file->type != fs::file::types::ind)
         return -EBADF;
 
-    auto* inode = file->ptr.ind;
-    // TODO: use copy_to_user
-    assert(inode->fs->inode_stat(inode, buf) == GB_OK);
-
-    return 0;
+    return __stat(file->ptr.ind, buf);
 }
 
 extern "C" void syscall_entry(interrupt_stack* data)
@@ -518,6 +533,7 @@ void init_syscall(void)
     syscall_handlers[1] = _syscall_write;
     syscall_handlers[2] = _syscall_open;
     syscall_handlers[3] = _syscall_close;
+    syscall_handlers[4] = _syscall_stat;
     syscall_handlers[5] = _syscall_fstat;
     syscall_handlers[12] = _syscall_brk;
     syscall_handlers[16] = _syscall_ioctl;