diff --git a/kernel/common/dirent.h b/kernel/common/dirent.h new file mode 100644 index 00000000..e60bf653 --- /dev/null +++ b/kernel/common/dirent.h @@ -0,0 +1,11 @@ +#pragma once + +#include +struct dirent +{ + ino_t d_ino; // 文件序列号 + off_t d_off; // dir偏移量 + unsigned short d_reclen; // 目录下的记录数 + unsigned char d_type; // entry的类型 + char d_name[]; // 文件entry的名字(是一个零长度的数组) +}; diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index 3039d31d..63fe11e3 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -1,5 +1,8 @@ #include "VFS.h" #include +#include +#include +#include #include // 为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; } \ No newline at end of file diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index d9d3bc7b..820f92d0 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/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 = diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 5d682ade..9c1ed36e 100644 --- a/kernel/syscall/syscall.c +++ b/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; diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index 7d868b2f..5ad8cc3f 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -8,6 +8,8 @@ #include #include +#include + #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; } diff --git a/user/libs/libc/Makefile b/user/libs/libc/Makefile index 5c3a1aab..689f64bb 100644 --- a/user/libs/libc/Makefile +++ b/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;\ diff --git a/user/libs/libc/dirent.c b/user/libs/libc/dirent.c index 60767780..2450cbd7 100644 --- a/user/libs/libc/dirent.c +++ b/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 diff --git a/user/libs/libc/dirent.h b/user/libs/libc/dirent.h index 1f13a379..591fe2e9 100644 --- a/user/libs/libc/dirent.h +++ b/user/libs/libc/dirent.h @@ -1,6 +1,15 @@ #pragma once #include + +/** + * @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); \ No newline at end of file +struct dirent* readdir(struct DIR* dir); \ No newline at end of file