Parcourir la source

feat: add {open,read}dir and lazybox ls

greatbridf il y a 2 ans
Parent
commit
68b4a8d207

+ 4 - 2
gblibc/CMakeLists.txt

@@ -10,12 +10,14 @@ add_library(gblibc STATIC
     src/unistd.c
     src/wait.c
     src/assert.c
+    src/dirent.c
 )
 
+file(GLOB_RECURSE GBLIBC_PUBLIC_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include)
+
 target_include_directories(gblibc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
                                   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private-include)
 
 set_target_properties(gblibc PROPERTIES PRIVATE_HEADER
     "private-include/devutil.h,private-include/syscall.h")
-set_target_properties(gblibc PROPERTIES PUBLIC_HEADER
-    "include/stdio.h,include/stdint.h,include/stdarg.h,include/string.h,include/unistd.h,include/sys/types.h,include/sys/wait.h,include/fcntl.h,include/assert.h")
+set_target_properties(gblibc PROPERTIES PUBLIC_HEADER "${GBLIBC_PUBLIC_HEADERS}")

+ 35 - 0
gblibc/include/dirent.h

@@ -0,0 +1,35 @@
+#ifndef __GBLIBC_DIRENT_H_
+#define __GBLIBC_DIRENT_H_
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct dirent {
+    ino_t d_ino;
+    off_t d_off;
+    unsigned short d_reclen;
+    unsigned char d_type;
+    char d_name[256];
+};
+
+typedef struct _DIR {
+    int fd;
+    struct dirent dent;
+    char buffer[232];
+    int bpos;
+    int blen;
+} DIR;
+
+DIR* opendir(const char* name);
+DIR* fdopendir(int fd);
+
+struct dirent* readdir(DIR* dirp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 2 - 0
gblibc/include/sys/types.h

@@ -8,6 +8,8 @@ extern "C" {
 #endif
 
 typedef int pid_t;
+typedef uint32_t ino_t;
+typedef int32_t off_t;
 
 #ifdef __cplusplus
 }

+ 71 - 0
gblibc/src/dirent.c

@@ -0,0 +1,71 @@
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <syscall.h>
+
+DIR* opendir(const char* name)
+{
+    // TODO: set flags
+    int fd = open(name, 0);
+
+    if (fd < 0)
+        return NULL;
+
+    return fdopendir(fd);
+}
+
+DIR* fdopendir(int fd)
+{
+    static DIR dirs[64];
+    static int next = 0;
+
+    dirs[next].fd = fd;
+    dirs[next].bpos = 0;
+
+    return dirs + next++;
+}
+
+struct kernel_dirent {
+    ino_t d_ino; // inode number
+    uint32_t d_off; // ignored
+    uint16_t d_reclen; // length of this struct user_dirent
+    char d_name[1]; // file name with a padding zero
+    // uint8_t d_type; // file type, with offset of (d_reclen - 1)
+};
+
+size_t fill_dirent(struct dirent* dent, char* buffer, size_t bpos)
+{
+    struct kernel_dirent* dp = (struct kernel_dirent*)(buffer + bpos);
+    dent->d_ino = dp->d_ino;
+    dent->d_off = dp->d_off;
+    dent->d_reclen = dp->d_reclen;
+    dent->d_type = buffer[bpos + dp->d_reclen - 1];
+    strncpy(dent->d_name, dp->d_name, sizeof(dent->d_name));
+    dent->d_name[sizeof(dent->d_name) - 1] = 0;
+
+    return bpos + dp->d_reclen;
+}
+
+struct dirent* readdir(DIR* dirp)
+{
+    if (dirp->bpos) {
+        if (dirp->bpos >= dirp->blen) {
+            dirp->bpos = 0;
+        } else {
+            goto fill;
+        }
+    }
+
+    dirp->blen = syscall3(SYS_getdents,
+        dirp->fd,
+        (uint32_t)dirp->buffer,
+        sizeof(dirp->buffer)
+    );
+
+    if (dirp->blen <= 0)
+        return NULL;
+
+fill:
+    dirp->bpos = fill_dirent(&dirp->dent, dirp->buffer, dirp->bpos);
+    return &dirp->dent;
+}

+ 40 - 1
user-space-program/lazybox.c

@@ -1,4 +1,5 @@
-#include "unistd.h"
+#include <unistd.h>
+#include <dirent.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -9,6 +10,12 @@ struct applet {
     int (*func)(const char** args);
 };
 
+int putchar(int c)
+{
+    write(STDOUT_FILENO, &c, 1);
+    return c;
+}
+
 int puts(const char* str)
 {
     size_t ret = write(STDOUT_FILENO, str, strlen(str));
@@ -48,6 +55,34 @@ int pwd(const char** _)
     return 0;
 }
 
+int ls(const char** args)
+{
+    const char* path = args[0];
+    DIR* dir = NULL;
+
+    if (path == NULL) {
+        char buf[256];
+        if (getcwd(buf, sizeof(buf)) == 0)
+            return -1;
+
+        dir = opendir(buf);
+    } else {
+        dir = opendir(args[0]);
+    }
+
+    if (!dir)
+        return -1;
+
+    struct dirent* dp = NULL;
+    while ((dp = readdir(dir)) != NULL) {
+        printf("%s ", dp->d_name);
+    }
+
+    printf("\n");
+
+    return 0;
+}
+
 struct applet applets[] = {
     {
         "lazybox",
@@ -56,6 +91,10 @@ struct applet applets[] = {
     {
         "pwd",
         pwd,
+    },
+    {
+        "ls",
+        ls,
     }
 };