Quellcode durchsuchen

:new: 完成了ls的功能

fslongjin vor 2 Jahren
Ursprung
Commit
9ee6d33318

+ 11 - 0
kernel/common/dirent.h

@@ -0,0 +1,11 @@
+#pragma once
+
+#include <common/miniLibc/sys/types.h>
+struct dirent
+{
+    ino_t d_ino;    // 文件序列号
+    off_t d_off;    // dir偏移量
+    unsigned short d_reclen;    // 目录下的记录数
+    unsigned char d_type;   // entry的类型
+    char d_name[];   // 文件entry的名字(是一个零长度的数组)
+};

+ 23 - 2
kernel/filesystem/VFS/VFS.c

@@ -1,5 +1,8 @@
 #include "VFS.h"
 #include <common/kprint.h>
+#include <common/dirent.h>
+#include <common/errno.h>
+#include <mm/mm.h>
 #include <mm/slab.h>
 
 // 为filesystem_type_t结构体实例化一个链表头
@@ -138,9 +141,27 @@ struct vfs_dir_entry_t *vfs_path_walk(char *path, uint64_t flags)
 
 /**
  * @brief 填充dentry
- * 
+ *
  */
 int vfs_fill_dentry(void *buf, ino_t d_ino, char *name, int namelen, unsigned char type, off_t offset)
 {
-    
+    struct dirent *dent = (struct dirent *)buf;
+
+    // 如果尝试访问内核空间,则返回错误
+    if (!(verify_area((uint64_t)buf, sizeof(struct dirent) + namelen)))
+        return -EFAULT;
+
+    // ====== 填充dirent结构体 =====
+    memset(buf, 0, sizeof(struct dirent) + namelen);
+
+    memcpy(dent->d_name, name, namelen);
+    dent->d_name[namelen] = '\0';
+    // 暂时不显示目录下的记录数
+    dent->d_reclen = 0;
+    dent->d_ino = d_ino;
+    dent->d_off = offset;
+    dent->d_type = type;
+
+    // 返回dirent的总大小
+    return sizeof(struct dirent) + namelen;
 }

+ 13 - 1
kernel/filesystem/fat32/fat32.c

@@ -930,6 +930,8 @@ int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t f
         }
     }
 
+    uint64_t dentry_type = 0; // 传递给filler的dentry类型数据
+
     char *dir_name = NULL;
     int name_len = 0;
     // ==== 此时已经将文件夹的目录项起始簇的簇号读取到cluster变量中 ===
@@ -1012,6 +1014,7 @@ int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t f
                 }
 
                 // 读取目录项成功,返回
+                dentry_type = dentry->DIR_Attr;
                 goto find_dir_success;
             }
             else // 不存在长目录项
@@ -1035,7 +1038,10 @@ int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t f
 
                 // 如果当前短目录项为文件夹,则直接返回,不需要读取扩展名
                 if (dentry->DIR_Attr & ATTR_DIRECTORY)
+                {
+                    dentry_type = dentry->DIR_Attr;
                     goto find_dir_success;
+                }
 
                 // 是文件,增加  .
                 dir_name[name_len++] = '.';
@@ -1056,6 +1062,7 @@ int64_t fat32_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t f
                 if (total_len == 8) // 没有扩展名
                     dir_name[--name_len] = '\0';
 
+                dentry_type = dentry->DIR_Attr;
                 goto find_dir_success;
             }
         }
@@ -1072,7 +1079,12 @@ find_dir_success:;
     // 将文件夹位置坐标加32(即指向下一个目录项)
     file_ptr->position += 32;
     // todo: 计算ino_t
-    return filler(dirent, 0, dir_name, name_len, 0, 0);
+    if(dentry_type & ATTR_DIRECTORY)
+        dentry_type = VFS_ATTR_DIR;
+    else
+        dentry_type = VFS_ATTR_FILE;
+    
+    return filler(dirent, 0, dir_name, name_len, dentry_type, 0);
 }
 
 struct vfs_inode_operations_t fat32_inode_ops =

+ 6 - 6
kernel/syscall/syscall.c

@@ -110,7 +110,7 @@ uint64_t sys_open(struct pt_regs *regs)
 
     char *filename = (char *)(regs->r8);
     int flags = (int)(regs->r9);
-    kdebug("filename=%s", filename);
+    // kdebug("filename=%s", filename);
 
     long path_len = strnlen_user(filename, PAGE_4K_SIZE) + 1;
 
@@ -134,10 +134,10 @@ uint64_t sys_open(struct pt_regs *regs)
     // 寻找文件
     struct vfs_dir_entry_t *dentry = vfs_path_walk(path, 0);
 
-    if (dentry != NULL)
-        printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size);
-    else
-        printk_color(ORANGE, BLACK, "Can`t find file\n");
+    // if (dentry != NULL)
+    //     printk_color(ORANGE, BLACK, "Found %s\nDIR_FstClus:%#018lx\tDIR_FileSize:%#018lx\n", path, ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus, dentry->dir_inode->file_size);
+    // else
+    //     printk_color(ORANGE, BLACK, "Can`t find file\n");
 
     kfree(path);
     if (dentry == NULL)
@@ -236,7 +236,7 @@ uint64_t sys_close(struct pt_regs *regs)
 {
     int fd_num = (int)regs->r8;
 
-    kdebug("sys close: fd=%d", fd_num);
+    // kdebug("sys close: fd=%d", fd_num);
     // 校验文件描述符范围
     if (fd_num < 0 || fd_num > PROC_MAX_FD_NUM)
         return -EBADF;

+ 31 - 1
user/apps/shell/cmd.c

@@ -8,6 +8,8 @@
 #include <libc/unistd.h>
 #include <libc/stdlib.h>
 
+#include <libc/dirent.h>
+
 #include "cmd_help.h"
 
 // 当前工作目录(在main_loop中初始化)
@@ -152,7 +154,7 @@ int shell_cmd_cd(int argc, char **argv)
             if (argv[1][0] == '.' && argv[1][1] == '/') // 相对路径
                 dest_offset = 2;
         }
-        
+
         int new_len = current_dir_len + dest_len - dest_offset;
         // ======进入相对路径=====
         if (new_len >= SHELL_CWD_MAX_SIZE - 1)
@@ -201,6 +203,34 @@ done:;
 // todo:
 int shell_cmd_ls(int argc, char **argv)
 {
+    struct DIR *dir = opendir(shell_current_path);
+    
+    if (dir == NULL)
+        return -1;
+
+    struct dirent *buf = NULL;
+    // printf("dir=%#018lx\n", dir);
+
+    while (1)
+    {
+        buf = readdir(dir);
+        if(buf == NULL)
+            break;
+        
+        int color = COLOR_WHITE;
+        if(buf->d_type & VFS_ATTR_DIR)
+            color = COLOR_YELLOW;
+        else if(buf->d_type & VFS_ATTR_FILE)
+            color = COLOR_INDIGO;
+        
+        char output_buf[256] = {0};
+
+        sprintf(output_buf, "%s   ", buf->d_name);
+        put_string(output_buf, color, COLOR_BLACK);
+        
+    }
+    printf("\n");
+    closedir(dir);
     return 0;
 }
 

+ 1 - 1
user/libs/libc/Makefile

@@ -5,7 +5,7 @@ CFLAGS += -I .
 libc_sub_dirs=math
 
 
-libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o
+libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o dirent.o
 	@list='$(libc_sub_dirs)'; for subdir in $$list; do \
     		echo "make all in $$subdir";\
     		cd $$subdir;\

+ 10 - 3
user/libs/libc/dirent.c

@@ -17,10 +17,15 @@ struct DIR *opendir(const char *path)
 {
     int fd = open(path, O_DIRECTORY);
     if (fd < 0) // 目录打开失败
+    {
+        printf("Failed to open dir\n");
         return NULL;
+    }
+    // printf("open dir: %s\n", path);
 
     // 分配DIR结构体
     struct DIR *dirp = (struct DIR *)malloc(sizeof(struct DIR));
+    // printf("dirp = %#018lx", dirp);
     memset(dirp, 0, sizeof(struct DIR));
     dirp->fd = fd;
     dirp->buf_len = DIR_BUF_SIZE;
@@ -59,11 +64,13 @@ int64_t getdents(int fd, struct dirent *dirent, long count)
  * @param dir
  * @return struct dirent*
  */
-struct dirent *reaaddir(struct DIR *dir)
+struct dirent *readdir(struct DIR *dir)
 {
-    memset(dir, 0, DIR_BUF_SIZE);
+    // printf("dir->buf = %#018lx\n", (dir->buf));
+    memset((dir->buf), 0, DIR_BUF_SIZE);
+    // printf("memeset_ok\n");
     int len = getdents(dir->fd, (struct dirent *)dir->buf, DIR_BUF_SIZE);
-
+    // printf("len=%d\n", len);
     if (len > 0)
         return (struct dirent *)dir->buf;
     else

+ 11 - 2
user/libs/libc/dirent.h

@@ -1,6 +1,15 @@
 #pragma once
 #include <libc/sys/types.h>
 
+
+/**
+ * @brief 目录项的属性(copy from vfs.h)
+ *
+ */
+#define VFS_ATTR_FILE (1UL << 0)
+#define VFS_ATTR_DIR (1UL << 1)
+#define VFS_ATTR_DEVICE (1UL << 2)
+
 #define DIR_BUF_SIZE 256
 /**
  * @brief 文件夹结构体
@@ -22,7 +31,7 @@ struct dirent
     off_t d_off;    // dir偏移量
     unsigned short d_reclen;    // 目录下的记录数
     unsigned char d_type;   // entry的类型
-    char d_name[256];   // 文件entry的名字
+    char d_name[];   // 文件entry的名字(是一个零长数组)
 };
 
 /**
@@ -54,4 +63,4 @@ int closedir(struct DIR *dirp);
  * @param dir 
  * @return struct dirent* 
  */
-struct dirent* reaaddir(struct DIR* dir);
+struct dirent* readdir(struct DIR* dir);