diff --git a/.vscode/settings.json b/.vscode/settings.json index 895c8f77..e95ee48f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -132,7 +132,11 @@ "limits.h": "c", "block.h": "c", "blk_types.h": "c", - "mutex.h": "c" + "mutex.h": "c", + "mount.h": "c", + "internal.h": "c", + "devfs.h": "c", + "devfs-types.h": "c" }, "C_Cpp.errorSquiggles": "Enabled", "esbonio.sphinx.confDir": "" diff --git a/docs/kernel/filesystem/vfs/overview.md b/docs/kernel/filesystem/vfs/overview.md index ffedc338..4f5d2584 100644 --- a/docs/kernel/filesystem/vfs/overview.md +++ b/docs/kernel/filesystem/vfs/overview.md @@ -173,11 +173,11 @@ struct vfs_index_node_t   inode的属性。可选值如下: -> - VFS_ATTR_FILE +> - VFS_IF_FILE > -> - VFS_ATTR_DIR +> - VFS_IF_DIR > -> - VFS_ATTR_DEVICE +> - VFS_IF_DEVICE **sb** diff --git a/docs/userland/libc/apis/api-list/dirent.md b/docs/userland/libc/apis/api-list/dirent.md index 58f02731..ced3ec17 100644 --- a/docs/userland/libc/apis/api-list/dirent.md +++ b/docs/userland/libc/apis/api-list/dirent.md @@ -48,11 +48,11 @@ 文件夹类型: - ``#define VFS_ATTR_FILE (1UL << 0)`` + ``#define VFS_IF_FILE (1UL << 0)`` - ``#define VFS_ATTR_DIR (1UL << 1)`` + ``#define VFS_IF_DIR (1UL << 1)`` - ``#define VFS_ATTR_DEVICE (1UL << 2)`` + ``#define VFS_IF_DEVICE (1UL << 2)`` 缓冲区长度的默认值 diff --git a/kernel/debug/bug.h b/kernel/debug/bug.h index 958b0d6f..7f2b851a 100644 --- a/kernel/debug/bug.h +++ b/kernel/debug/bug.h @@ -4,6 +4,18 @@ #pragma GCC push_options #pragma GCC optimize("O0") + +/** + * @brief 当condition为true时,认为产生了bug + * + */ +#define BUG_ON(condition) ({ \ + int __ret_bug_on = !!(condition); \ + if (unlikely(__ret_bug_on)) \ + kBUG("BUG at %s:%d", __FILE__, __LINE__); \ + unlikely(__ret_bug_on); \ +}) + /** * @brief 当condition为true时输出警告信息 * diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index c7d2d1d5..205efc4f 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -1,6 +1,8 @@ #include "VFS.h" #include "mount.h" +#include "internal.h" #include +#include #include #include #include @@ -46,7 +48,9 @@ struct vfs_superblock_t *vfs_mount_fs(const char *path, char *name, struct block { struct vfs_superblock_t *sb = p->read_superblock(blk); if (strcmp(path, "/") == 0) // 如果挂载到的是'/'挂载点,则让其成为最顶层的文件系统 + { vfs_root_sb = sb; + } else { kdebug("to mount %s", name); @@ -168,7 +172,7 @@ struct vfs_dir_entry_t *vfs_path_walk(const char *path, uint64_t flags) // 如果没有找到dentry缓存,则申请新的dentry if (dentry == NULL) { - dentry = vfs_alloc_dentry(tmp_path_len+1); + dentry = vfs_alloc_dentry(tmp_path_len + 1); memcpy(dentry->name, (void *)tmp_path, tmp_path_len); dentry->name[tmp_path_len] = '\0'; @@ -236,13 +240,13 @@ int vfs_fill_dirent(void *buf, ino_t d_ino, char *name, int namelen, unsigned ch /** * @brief 创建文件夹 - * + * * @param path 文件夹路径 * @param mode 创建模式 - * @param from_userland 该创建请求是否来自用户态 + * @param from_userland 该创建请求是否来自用户态 * @return int64_t 错误码 */ -int64_t vfs_mkdir(const char* path, mode_t mode, bool from_userland) +int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland) { uint32_t pathlen; if (from_userland) @@ -267,10 +271,9 @@ int64_t vfs_mkdir(const char* path, mode_t mode, bool from_userland) // 路径格式不合法(必须使用绝对路径) if (last_slash < 0) - return ENOTDIR; + return -ENOTDIR; - char *buf = (char *)kmalloc(last_slash + 1, 0); - memset(buf, 0, pathlen + 1); + char *buf = (char *)kzalloc(last_slash + 2, 0); // 拷贝字符串(不包含要被创建的部分) if (from_userland) @@ -341,13 +344,12 @@ uint64_t sys_mkdir(struct pt_regs *regs) return vfs_mkdir(path, mode, true); else return vfs_mkdir(path, mode, false); - } /** * @brief 打开文件 - * - * @param filename 文件路径 + * + * @param filename 文件路径 * @param flags 标志位 * @return uint64_t 错误码 */ @@ -445,23 +447,23 @@ uint64_t do_open(const char *filename, int flags) return -ENOENT; // 要求打开文件夹而目标不是文件夹 - if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_ATTR_DIR)) + if ((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != VFS_IF_DIR)) return -ENOTDIR; // // 要找的目标是文件夹 - // if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_ATTR_DIR) + // if ((flags & O_DIRECTORY) && dentry->dir_inode->attribute == VFS_IF_DIR) // return -EISDIR; // // todo: 引入devfs后删除这段代码 // // 暂时遇到设备文件的话,就将其first clus设置为特定值 // if (path_len >= 5 && filename[0] == '/' && filename[1] == 'd' && filename[2] == 'e' && filename[3] == 'v' && filename[4] == '/') // { - // if (dentry->dir_inode->attribute & VFS_ATTR_FILE) + // if (dentry->dir_inode->attribute & VFS_IF_FILE) // { // // 对于fat32文件系统上面的设备文件,设置其起始扇区 // ((struct fat32_inode_info_t *)(dentry->dir_inode->private_inode_info))->first_clus |= 0xf0000000; // dentry->dir_inode->sb->sb_ops->write_inode(dentry->dir_inode); - // dentry->dir_inode->attribute |= VFS_ATTR_DEVICE; + // dentry->dir_inode->attribute |= VFS_IF_DEVICE; // } // } @@ -544,6 +546,122 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size) return dentry; } +/** + * @brief 判断是否可以删除指定的dentry + * + * 1、我们不能删除一个只读的dentry + * 2、我们应当对这个dentry的inode拥有写、执行权限(暂时还没有实现权限) + * 3、如果dentry指向的是文件夹,而isdir为false,则不能删除 + * 3、如果dentry指向的是文件,而isdir为true,则不能删除 + * @param dentry 将要被删除的dentry + * @param isdir 是否要删除文件夹 + * @return int 错误码 + */ +int vfs_may_delete(struct vfs_dir_entry_t *dentry, bool isdir) +{ + // 当dentry没有inode的时候,认为是bug + BUG_ON(dentry->dir_inode == NULL); + + // todo: 进行权限检查 + + if (isdir) // 要删除文件夹 + { + if (!D_ISDIR(dentry)) + return -ENOTDIR; + else if (IS_ROOT(dentry)) + return -EBUSY; + } + else if (D_ISDIR(dentry)) // 要删除文件但是当前是文件夹 + return -EISDIR; + + return 0; +} + +/** + * @brief 删除文件夹 + * + * @param path 文件夹路径 + * @param from_userland 请求是否来自用户态 + * @return int64_t 错误码 + */ +int64_t vfs_rmdir(const char *path, bool from_userland) +{ + uint32_t pathlen; + if (from_userland) + pathlen = strnlen_user(path, PAGE_4K_SIZE - 1); + else + pathlen = strnlen(path, PAGE_4K_SIZE - 1); + + if (pathlen == 0) + return -ENOENT; + + int last_slash = -1; + + // 去除末尾的'/' + for (int i = pathlen - 1; i >= 0; --i) + { + if (path[i] != '/') + { + last_slash = i + 1; + break; + } + } + + // 路径格式不合法 + if (last_slash < 0) + return -ENOTDIR; + else if (path[0] != '/') + return -EINVAL; + + char *buf = (char *)kzalloc(last_slash + 2, 0); + + // 拷贝字符串(不包含要被创建的部分) + if (from_userland) + strncpy_from_user(buf, path, last_slash); + else + strncpy(buf, path, last_slash); + buf[last_slash + 1] = '\0'; + + struct vfs_dir_entry_t *dentry = vfs_path_walk(buf, 0); + + if (dentry == NULL) + return -ENOENT; + + int retval = vfs_may_delete(dentry, true); + if (retval != 0) + return retval; + // todo: 对dentry和inode加锁 + retval = -EBUSY; + if (is_local_mountpoint(dentry)) + goto out; + // todo: + retval = dentry->dir_inode->inode_ops->rmdir(dentry->dir_inode, dentry); + if (retval != 0) + goto out; + + dentry->dir_inode->attribute |= VFS_IF_DEAD; // 将当前inode标记为dead + dont_mount(dentry); // 将当前dentry标记为不可被挂载 + detach_mounts(dentry); // 清理同样挂载在该路径的所有挂载点的挂载树 + + vfs_dentry_put(dentry); // 释放dentry +out:; + // todo: 对dentry和inode放锁 + return retval; +} + +/** + * @brief 删除文件夹的系统调用函数 + * + * @param r8 文件夹路径 + * @return uint64_t 错误码 + */ +uint64_t sys_rmdir(struct pt_regs *regs) +{ + if (SYSCALL_FROM_USER(regs)) + return vfs_rmdir((char *)regs->r8, true); + else + return vfs_rmdir((char *)regs->r8, false); +} /** * @brief 初始化vfs * diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 13419849..dfbba17f 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -28,12 +28,13 @@ extern struct vfs_superblock_t *vfs_root_sb; #define VFS_MAX_PATHLEN 1024 /** - * @brief 目录项的属性 + * @brief inode的属性 * */ -#define VFS_ATTR_FILE (1UL << 0) -#define VFS_ATTR_DIR (1UL << 1) -#define VFS_ATTR_DEVICE (1UL << 2) +#define VFS_IF_FILE (1UL << 0) +#define VFS_IF_DIR (1UL << 1) +#define VFS_IF_DEVICE (1UL << 2) +#define VFS_IF_DEAD (1UL<<3) /* removed, but still open directory */ struct vfs_super_block_operations_t; struct vfs_inode_operations_t; @@ -41,10 +42,13 @@ struct vfs_inode_operations_t; struct vfs_index_node_t; struct vfs_dir_entry_operations_t; +#define VFS_DF_MOUNTED (1 << 0) // 当前dentry是一个挂载点 +#define VFS_DF_CANNOT_MOUNT (1 << 1) // 当前dentry是一个挂载点 struct vfs_dir_entry_t { char *name; int name_length; + uint32_t d_flags; // dentry标志位 struct List child_node_list; struct List subdirs_list; @@ -218,8 +222,8 @@ struct vfs_dir_entry_t *vfs_alloc_dentry(const int name_size); /** * @brief 打开文件 - * - * @param filename 文件路径 + * + * @param filename 文件路径 * @param flags 标志位 * @return uint64_t 错误码 */ @@ -227,10 +231,19 @@ uint64_t do_open(const char *filename, int flags); /** * @brief 创建文件夹 - * + * * @param path 文件夹路径 * @param mode 创建模式 - * @param from_userland 该创建请求是否来自用户态 + * @param from_userland 该创建请求是否来自用户态 * @return int64_t 错误码 */ -int64_t vfs_mkdir(const char* path, mode_t mode, bool from_userland); \ No newline at end of file +int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland); + +/** + * @brief 删除文件夹 + * + * @param path 文件夹路径 + * @param from_userland 请求是否来自用户态 + * @return int64_t 错误码 + */ +int64_t vfs_rmdir(const char *path, bool from_userland); \ No newline at end of file diff --git a/kernel/filesystem/VFS/dcache.c b/kernel/filesystem/VFS/dcache.c new file mode 100644 index 00000000..452d583f --- /dev/null +++ b/kernel/filesystem/VFS/dcache.c @@ -0,0 +1,19 @@ +#include "internal.h" + +/** + * @brief 释放dentry + * + * @param dentry 目标dentry + */ +void vfs_dentry_put(struct vfs_dir_entry_t * dentry) +{ + // todo: 加锁、放锁 + + list_del(&dentry->child_node_list);// 从父dentry中删除 + + // todo: 清除子目录的dentry + + dentry->dir_ops->release(dentry); + + kfree(dentry); +} \ No newline at end of file diff --git a/kernel/filesystem/VFS/internal.h b/kernel/filesystem/VFS/internal.h new file mode 100644 index 00000000..0c807024 --- /dev/null +++ b/kernel/filesystem/VFS/internal.h @@ -0,0 +1,41 @@ +#pragma once +#include "VFS.h" +#include "mount.h" + +/** + * @brief 判断是否可以删除指定的dentry + * + * 1、我们不能删除一个只读的dentry + * 2、我们应当对这个dentry拥有写、执行权限(暂时还没有实现权限) + * 3、如果dentry指向的是文件夹,而isdir为false,则不能删除 + * 3、如果dentry指向的是文件,而isdir为true,则不能删除 + * @param dentry 将要被删除的dentry + * @param isdir 是否要删除文件夹 + * @return int 错误码 + */ +int vfs_may_delete(struct vfs_dir_entry_t *dentry, bool isdir); + +#define D_ISDIR(dentry) ((dentry)->dir_inode->attribute & VFS_IF_DIR) + +// 判断是否为根目录 +#define IS_ROOT(x) ((x) == (x)->parent) + +/** + * @brief 判断当前dentry是否为挂载点 + * + * @param dentry + */ +static inline bool is_local_mountpoint(struct vfs_dir_entry_t *dentry) +{ + if (D_MOUNTED(dentry)) + return true; + else + return false; +} + +/** + * @brief 释放dentry + * + * @param dentry 目标dentry + */ +void vfs_dentry_put(struct vfs_dir_entry_t * dentry); \ No newline at end of file diff --git a/kernel/filesystem/VFS/mount.c b/kernel/filesystem/VFS/mount.c index af67d385..3bf54ced 100644 --- a/kernel/filesystem/VFS/mount.c +++ b/kernel/filesystem/VFS/mount.c @@ -29,16 +29,17 @@ int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_den list_init(&mp->mnt_list); mp->dentry = old_dentry; mp->parent_dentry = old_dentry->parent; - + // kdebug("&new_dentry->name=%#018lx, &old_dentry->name=%#018lx", &new_dentry->name, &old_dentry->name); // 拷贝名称 strncpy(new_dentry->name, old_dentry->name, old_dentry->name_length); + new_dentry->d_flags |= VFS_DF_MOUNTED; // 标记新的dentry是一个挂载点 + list_init(&new_dentry->child_node_list); list_init(&new_dentry->subdirs_list); new_dentry->parent = old_dentry->parent; - // 将新的dentry的list结点替换掉父dentry的列表中的old_dentry的list结点 list_replace(&old_dentry->child_node_list, &new_dentry->child_node_list); @@ -50,11 +51,11 @@ int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_den /** * @brief 取消某个文件系统的挂载 - * + * * @param dentry 对应文件系统的根dentry * @return int 错误码 */ -int do_umount(struct vfs_dir_entry_t* dentry) +int do_umount(struct vfs_dir_entry_t *dentry) { // todo: 实现umount(主要是结点的恢复问题) diff --git a/kernel/filesystem/VFS/mount.h b/kernel/filesystem/VFS/mount.h index 1c532023..5c0fa19a 100644 --- a/kernel/filesystem/VFS/mount.h +++ b/kernel/filesystem/VFS/mount.h @@ -1,6 +1,6 @@ #pragma once #include - +#include "VFS.h" /** * @brief 挂载点结构体(用来表示dentry被挂载其他文件系统之后,原先存在的数据) * @@ -30,8 +30,31 @@ int do_mount(struct vfs_dir_entry_t *old_dentry, struct vfs_dir_entry_t *new_den /** * @brief 取消某个文件系统的挂载 - * + * * @param dentry 对应文件系统的根dentry * @return int 错误码 */ -int do_umount(struct vfs_dir_entry_t* dentry); \ No newline at end of file +int do_umount(struct vfs_dir_entry_t *dentry); + +// 判断dentry是否是一个挂载点 +#define D_MOUNTED(x) ((x)->d_flags & VFS_DF_MOUNTED) + +/** + * @brief 将给定的dentry标记为“不可挂载” + * + * @param dentry 目标dentry + */ +static inline void dont_mount(struct vfs_dir_entry_t *dentry) +{ + // todo: 对dentry加锁 + dentry->d_flags |= VFS_DF_CANNOT_MOUNT; +} + +static inline void detach_mounts(struct vfs_dir_entry_t *dentry) +{ + if (!D_MOUNTED(dentry)) + return; // 如果当前文件夹不是一个挂载点,则直接返回 + + // todo:如果当前文件夹是一个挂载点,则对同样挂载在当前文件夹下的dentry进行清理。以免造成内存泄露 + // 可参考 linux5.17或以上的detach_mounts()函数 +} \ No newline at end of file diff --git a/kernel/filesystem/devfs/chardev.c b/kernel/filesystem/devfs/chardev.c index 5a220ca4..786ea745 100644 --- a/kernel/filesystem/devfs/chardev.c +++ b/kernel/filesystem/devfs/chardev.c @@ -55,7 +55,7 @@ int __devfs_chardev_register(struct devfs_private_inode_info_t *private_info, st struct vfs_dir_entry_t *dentry = vfs_alloc_dentry(namelen + 1); __devfs_fill_dentry(dentry, devname); - __devfs_fill_inode(dentry, __devfs_alloc_inode(), VFS_ATTR_DEVICE, private_info); + __devfs_fill_inode(dentry, __devfs_alloc_inode(), VFS_IF_DEVICE, private_info); // 将dentry挂载到char文件夹下 __devfs_dentry_bind_parent(chardev_folder_dentry, dentry); diff --git a/kernel/filesystem/devfs/devfs.c b/kernel/filesystem/devfs/devfs.c index 3d367a07..19be1711 100644 --- a/kernel/filesystem/devfs/devfs.c +++ b/kernel/filesystem/devfs/devfs.c @@ -33,11 +33,11 @@ struct vfs_superblock_t *devfs_read_superblock(struct block_device *blk) return &devfs_sb; } -static void devfs_write_superblock(struct vfs_superblock_t *sb) {} +static void devfs_write_superblock(struct vfs_superblock_t *sb) {return 0; } -static void devfs_put_superblock(struct vfs_superblock_t *sb) {} +static void devfs_put_superblock(struct vfs_superblock_t *sb) {return 0; } -static void devfs_write_inode(struct vfs_index_node_t *inode) {} +static void devfs_write_inode(struct vfs_index_node_t *inode) {return 0; } struct vfs_super_block_operations_t devfs_sb_ops = { .write_superblock = &devfs_write_superblock, @@ -45,13 +45,13 @@ struct vfs_super_block_operations_t devfs_sb_ops = .write_inode = &devfs_write_inode, }; -static long devfs_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename) {} +static long devfs_compare(struct vfs_dir_entry_t *parent_dEntry, char *source_filename, char *dest_filename) {return 0; } -static long devfs_hash(struct vfs_dir_entry_t *dEntry, char *filename) {} +static long devfs_hash(struct vfs_dir_entry_t *dEntry, char *filename) {return 0; } -static long devfs_release(struct vfs_dir_entry_t *dEntry) {} +static long devfs_release(struct vfs_dir_entry_t *dEntry) { return 0; } -static long devfs_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode) {} +static long devfs_iput(struct vfs_dir_entry_t *dEntry, struct vfs_index_node_t *inode) {return 0; } struct vfs_dir_entry_operations_t devfs_dentry_ops = { @@ -65,10 +65,10 @@ static long devfs_open(struct vfs_index_node_t *inode, struct vfs_file_t *file_p { return 0; } -static long devfs_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) {} -static long devfs_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {} -static long devfs_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {} -static long devfs_lseek(struct vfs_file_t *file_ptr, long offset, long origin) {} +static long devfs_close(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr) {return 0; } +static long devfs_read(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {return 0; } +static long devfs_write(struct vfs_file_t *file_ptr, char *buf, int64_t count, long *position) {return 0; } +static long devfs_lseek(struct vfs_file_t *file_ptr, long offset, long origin) {return 0; } static long devfs_ioctl(struct vfs_index_node_t *inode, struct vfs_file_t *file_ptr, uint64_t cmd, uint64_t arg) { return 0; } static long devfs_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir_t filler) @@ -94,10 +94,10 @@ static long devfs_readdir(struct vfs_file_t *file_ptr, void *dirent, vfs_filldir char *name = (char *)kzalloc(target_dent->name_length + 1, 0); strncpy(name, target_dent->name, target_dent->name_length); uint32_t dentry_type; - if (target_dent->dir_inode->attribute & VFS_ATTR_DIR) - dentry_type = VFS_ATTR_DIR; + if (target_dent->dir_inode->attribute & VFS_IF_DIR) + dentry_type = VFS_IF_DIR; else - dentry_type = VFS_ATTR_DEVICE; + dentry_type = VFS_IF_DEVICE; return filler(dirent, file_ptr->position - 1, name, target_dent->name_length, dentry_type, file_ptr->position - 1); failed:; @@ -123,6 +123,7 @@ struct vfs_file_operations_t devfs_file_ops = */ static long devfs_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry, int mode) { + return 0; } static struct vfs_dir_entry_t *devfs_lookup(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dest_dEntry) @@ -148,18 +149,18 @@ static long devfs_mkdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t * dEntry->dir_inode = (struct vfs_index_node_t *)kzalloc(sizeof(struct vfs_index_node_t), 0); dEntry->dir_inode->file_ops = &devfs_file_ops; dEntry->dir_inode->inode_ops = &devfs_inode_ops; - + dEntry->dir_ops = &devfs_dentry_ops; // todo: 增加private inode info dEntry->dir_inode->private_inode_info = NULL; dEntry->dir_inode->sb = &devfs_sb; - dEntry->dir_inode->attribute = VFS_ATTR_DIR; + dEntry->dir_inode->attribute = VFS_IF_DIR; return 0; } -static long devfs_rmdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry) {} -static long devfs_rename(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry, struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry) {} -static long devfs_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {} -static long devfs_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {} +static long devfs_rmdir(struct vfs_index_node_t *inode, struct vfs_dir_entry_t *dEntry) { return 0; } +static long devfs_rename(struct vfs_index_node_t *old_inode, struct vfs_dir_entry_t *old_dEntry, struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry) {return 0; } +static long devfs_getAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {return 0; } +static long devfs_setAttr(struct vfs_dir_entry_t *dEntry, uint64_t *attr) {return 0; } struct vfs_inode_operations_t devfs_inode_ops = { .create = &devfs_create, .lookup = &devfs_lookup, @@ -187,7 +188,7 @@ static __always_inline void __devfs_init_root_inode() // todo: 增加private inode info devfs_root_dentry->dir_inode->private_inode_info = NULL; devfs_root_dentry->dir_inode->sb = &devfs_sb; - devfs_root_dentry->dir_inode->attribute = VFS_ATTR_DIR; + devfs_root_dentry->dir_inode->attribute = VFS_IF_DIR; } /** * @brief 初始化devfs的根dentry @@ -251,7 +252,6 @@ void devfs_init() vfs_register_filesystem(&devfs_fs_type); vfs_mount_fs(__devfs_mount_path, "DEVFS", NULL); - __devfs_chardev_init(); // todo: 当rootfs实现后,将ps/2键盘的注册改为在驱动程序中进行(目前没有rootfs,因此还不能在不依赖fat32的情况下,挂载设备) diff --git a/kernel/filesystem/devfs/internal.h b/kernel/filesystem/devfs/internal.h index f0dfad53..98a8e5d3 100644 --- a/kernel/filesystem/devfs/internal.h +++ b/kernel/filesystem/devfs/internal.h @@ -58,7 +58,7 @@ static inline struct vfs_dir_entry_t *__devfs_find_dentry(struct vfs_dir_entry_t static inline struct vfs_dir_entry_t *__devfs_find_dir(struct vfs_dir_entry_t *parent_dentry, const char *name) { struct vfs_dir_entry_t *target_dent = __devfs_find_dentry(parent_dentry, name); - if (target_dent->dir_inode->attribute & VFS_ATTR_DIR) // 名称相符且为目录,则返回dentry + if (target_dent->dir_inode->attribute & VFS_IF_DIR) // 名称相符且为目录,则返回dentry return target_dent; else return NULL; // 否则直接返回空 diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index 21db82e0..528ceedb 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/kernel/filesystem/fat32/fat32.c @@ -293,7 +293,7 @@ find_lookup_success:; // 找到目标dentry p->file_size = tmp_dEntry->DIR_FileSize; // 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区 p->blocks = (p->file_size + fsbi->bytes_per_clus - 1) / fsbi->bytes_per_sec; - p->attribute = (tmp_dEntry->DIR_Attr & ATTR_DIRECTORY) ? VFS_ATTR_DIR : VFS_ATTR_FILE; + p->attribute = (tmp_dEntry->DIR_Attr & ATTR_DIRECTORY) ? VFS_IF_DIR : VFS_IF_FILE; p->sb = parent_inode->sb; p->file_ops = &fat32_file_ops; p->inode_ops = &fat32_inode_ops; @@ -315,8 +315,8 @@ find_lookup_success:; // 找到目标dentry // 暂时使用fat32的高4bit来标志设备文件 // todo: 引入devfs后删除这段代码 - if ((tmp_dEntry->DIR_FstClusHI >> 12) && (p->attribute & VFS_ATTR_FILE)) - p->attribute |= VFS_ATTR_DEVICE; + if ((tmp_dEntry->DIR_FstClusHI >> 12) && (p->attribute & VFS_IF_FILE)) + p->attribute |= VFS_IF_DEVICE; dest_dentry->dir_inode = p; dest_dentry->dir_ops = &fat32_dEntry_ops; @@ -394,7 +394,7 @@ struct vfs_superblock_t *fat32_read_superblock(struct block_device *blk) sb_ptr->root->dir_inode->file_size = 0; // 计算文件占用的扇区数, 由于最小存储单位是簇,因此需要按照簇的大小来对齐扇区 sb_ptr->root->dir_inode->blocks = (sb_ptr->root->dir_inode->file_size + fsbi->bytes_per_clus - 1) / fsbi->bytes_per_sec; - sb_ptr->root->dir_inode->attribute = VFS_ATTR_DIR; + sb_ptr->root->dir_inode->attribute = VFS_IF_DIR; sb_ptr->root->dir_inode->sb = sb_ptr; // 反向绑定对应的超级块 // 初始化inode信息 @@ -826,7 +826,7 @@ long fat32_create(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)kmalloc(sizeof(struct fat32_inode_info_t), 0); memset((void *)finode, 0, sizeof(struct fat32_inode_info_t)); - inode->attribute = VFS_ATTR_FILE; + inode->attribute = VFS_IF_FILE; inode->file_ops = &fat32_file_ops; inode->file_size = 0; inode->sb = parent_inode->sb; @@ -933,7 +933,7 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_ // ====== 初始化inode ======= struct vfs_index_node_t *inode = (struct vfs_index_node_t *)kmalloc(sizeof(struct vfs_index_node_t), 0); memset(inode, 0, sizeof(struct vfs_index_node_t)); - inode->attribute = VFS_ATTR_DIR; + inode->attribute = VFS_IF_DIR; inode->blocks = fsbi->sec_per_clus; inode->file_ops = &fat32_file_ops; inode->file_size = 0; @@ -1230,9 +1230,9 @@ find_dir_success:; file_ptr->position += 32; // todo: 计算ino_t if (dentry_type & ATTR_DIRECTORY) - dentry_type = VFS_ATTR_DIR; + dentry_type = VFS_IF_DIR; else - dentry_type = VFS_ATTR_FILE; + dentry_type = VFS_IF_FILE; return filler(dirent, 0, dir_name, name_len, dentry_type, 0); } diff --git a/kernel/filesystem/fat32/fat_ent.c b/kernel/filesystem/fat32/fat_ent.c index 4cc52261..8ce57796 100644 --- a/kernel/filesystem/fat32/fat_ent.c +++ b/kernel/filesystem/fat32/fat_ent.c @@ -335,7 +335,7 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory target->DIR_Name[tmp_index] = 0x20; ++tmp_index; } - if (dEntry->dir_inode->attribute & VFS_ATTR_DIR) + if (dEntry->dir_inode->attribute & VFS_IF_DIR) { while (tmp_index < 11) { @@ -355,7 +355,7 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory struct vfs_index_node_t *inode = dEntry->dir_inode; target->DIR_Attr = 0; - if (inode->attribute & VFS_ATTR_DIR) + if (inode->attribute & VFS_IF_DIR) target->DIR_Attr |= ATTR_DIRECTORY; target->DIR_FileSize = dEntry->dir_inode->file_size; diff --git a/kernel/process/process.c b/kernel/process/process.c index 09ab037f..4c575619 100644 --- a/kernel/process/process.c +++ b/kernel/process/process.c @@ -154,7 +154,7 @@ struct vfs_file_t *process_open_exec_file(char *path) if (dentry == NULL) return (void *)-ENOENT; - if (dentry->dir_inode->attribute == VFS_ATTR_DIR) + if (dentry->dir_inode->attribute == VFS_IF_DIR) return (void *)-ENOTDIR; filp = (struct vfs_file_t *)kmalloc(sizeof(struct vfs_file_t), 0); diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index de7ad2d1..338707f9 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -19,6 +19,7 @@ extern void syscall_int(void); extern uint64_t sys_clock(struct pt_regs *regs); extern uint64_t sys_mstat(struct pt_regs *regs); extern uint64_t sys_open(struct pt_regs *regs); +extern uint64_t sys_rmdir(struct pt_regs *regs); /** * @brief 导出系统调用处理函数的符号 @@ -415,7 +416,7 @@ uint64_t sys_chdir(struct pt_regs *regs) return -ENOENT; // kdebug("dentry->name=%s, namelen=%d", dentry->name, dentry->name_length); // 目标不是目录 - if (dentry->dir_inode->attribute != VFS_ATTR_DIR) + if (dentry->dir_inode->attribute != VFS_IF_DIR) return -ENOTDIR; return 0; @@ -602,5 +603,6 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = [19] = sys_clock, [20] = sys_pipe, [21] = sys_mstat, - [22 ... 254] = system_call_not_exists, + [22] = sys_rmdir, + [23 ... 254] = system_call_not_exists, [255] = sys_ahci_end_req}; diff --git a/kernel/syscall/syscall.h b/kernel/syscall/syscall.h index 225540ee..8015e4b7 100644 --- a/kernel/syscall/syscall.h +++ b/kernel/syscall/syscall.h @@ -15,6 +15,11 @@ extern void ret_from_system_call(void); // 导出从系统调用返回的函数 extern system_call_t system_call_table[MAX_SYSTEM_CALL_NUM]; +// 判断系统调用是否来自用户态 +#define SYSCALL_FROM_USER(regs) ((regs)->cs & USER_CS) +// 判断系统调用是否来自内核态 +#define SYSCALL_FROM_KERNEL(regs) (!SYSCALL_FROM_USER(regs)) + /** * @brief 初始化系统调用模块 * diff --git a/kernel/syscall/syscall_num.h b/kernel/syscall/syscall_num.h index 661132f6..e7e0bbdf 100644 --- a/kernel/syscall/syscall_num.h +++ b/kernel/syscall/syscall_num.h @@ -33,6 +33,7 @@ #define SYS_PIPE 20 #define SYS_MSTAT 21 // 获取系统的内存状态信息 +#define SYS_RMDIR 22 // 删除文件夹 #define SYS_AHCI_END_REQ 255 // AHCI DMA请求结束end_request的系统调用 \ No newline at end of file diff --git a/user/apps/shell/cmd.c b/user/apps/shell/cmd.c index 94689b49..6b5d6d1f 100644 --- a/user/apps/shell/cmd.c +++ b/user/apps/shell/cmd.c @@ -210,7 +210,7 @@ int shell_cmd_cd(int argc, char **argv) new_path[current_dir_len] = '/'; strcat(new_path, argv[1] + dest_offset); int x = chdir(new_path); - + if (x == 0) // 成功切换目录 { free(shell_current_path); @@ -257,12 +257,12 @@ int shell_cmd_ls(int argc, char **argv) break; int color = COLOR_WHITE; - if (buf->d_type & VFS_ATTR_DIR) + if (buf->d_type & VFS_IF_DIR) color = COLOR_YELLOW; - else if (buf->d_type & VFS_ATTR_FILE) + else if (buf->d_type & VFS_IF_FILE) color = COLOR_INDIGO; - else if(buf->d_type & VFS_ATTR_DEVICE) - color= COLOR_GREEN; + else if (buf->d_type & VFS_IF_DEVICE) + color = COLOR_GREEN; char output_buf[256] = {0}; @@ -405,7 +405,21 @@ int shell_cmd_mkdir(int argc, char **argv) * @return int */ // todo: -int shell_cmd_rmdir(int argc, char **argv) {} +int shell_cmd_rmdir(int argc, char **argv) +{ + const char *full_path = NULL; + int result_path_len = -1; + if (argv[1][0] == '/') + full_path = argv[1]; + else + full_path = get_target_filepath(argv[1], &result_path_len); + int retval = rmdir(full_path); + printf("rmdir: path=%s, retval=%d", full_path, retval); + if (argv != NULL) + free(argv); + + return retval; +} /** * @brief 执行新的程序的命令 @@ -483,7 +497,7 @@ int shell_cmd_free(int argc, char **argv) struct mstat_t mst = {0}; retval = mstat(&mst); - if(retval!=0) + if (retval != 0) { printf("Failed: retval=%d", retval); goto done; @@ -491,15 +505,15 @@ int shell_cmd_free(int argc, char **argv) printf("\ttotal\tused\tfree\tshared\tcache\tavailable\n"); printf("Mem:\t"); - if(argc==1) // 按照kb显示 + if (argc == 1) // 按照kb显示 { - printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total>>10,mst.used>>10,mst.free>>10, mst.shared>>10, mst.cache_used>>10, mst.available>>10); + printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 10, mst.used >> 10, mst.free >> 10, mst.shared >> 10, mst.cache_used >> 10, mst.available >> 10); } - else // 按照MB显示 + else // 按照MB显示 { - printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total>>20,mst.used>>20,mst.free>>20, mst.shared>>20, mst.cache_used>>20, mst.available>>20); + printf("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t\n", mst.total >> 20, mst.used >> 20, mst.free >> 20, mst.shared >> 20, mst.cache_used >> 20, mst.available >> 20); } - + done:; if (argv != NULL) free(argv); diff --git a/user/libs/libc/dirent.h b/user/libs/libc/dirent.h index 591fe2e9..9af88da9 100644 --- a/user/libs/libc/dirent.h +++ b/user/libs/libc/dirent.h @@ -3,12 +3,12 @@ /** - * @brief 目录项的属性(copy from vfs.h) + * @brief inode的属性(copy from vfs.h) * */ -#define VFS_ATTR_FILE (1UL << 0) -#define VFS_ATTR_DIR (1UL << 1) -#define VFS_ATTR_DEVICE (1UL << 2) +#define VFS_IF_FILE (1UL << 0) +#define VFS_IF_DIR (1UL << 1) +#define VFS_IF_DEVICE (1UL << 2) #define DIR_BUF_SIZE 256 /** diff --git a/user/libs/libc/unistd.c b/user/libs/libc/unistd.c index 7d07a4e0..e4919baa 100644 --- a/user/libs/libc/unistd.c +++ b/user/libs/libc/unistd.c @@ -142,7 +142,19 @@ int execv(const char *path, char *const argv[]) return -1; } int retval = syscall_invoke(SYS_EXECVE, (uint64_t)path, (uint64_t)argv, 0, 0, 0, 0, 0, 0); - if(retval != 0) + if (retval != 0) return -1; - else return 0; + else + return 0; +} + +/** + * @brief 删除文件夹 + * + * @param path 绝对路径 + * @return int 错误码 + */ +int rmdir(const char *path) +{ + return syscall_invoke(SYS_RMDIR, (uint64_t)path, 0, 0, 0, 0, 0, 0, 0); } \ No newline at end of file diff --git a/user/libs/libc/unistd.h b/user/libs/libc/unistd.h index 485c2717..3e4bc707 100644 --- a/user/libs/libc/unistd.h +++ b/user/libs/libc/unistd.h @@ -97,3 +97,11 @@ int execv(const char* path, char * const argv[]); * @return int */ extern int usleep(useconds_t usec); + +/** + * @brief 删除文件夹 + * + * @param path 绝对路径 + * @return int 错误码 + */ +int rmdir(const char* path); \ No newline at end of file diff --git a/user/libs/libsystem/syscall.h b/user/libs/libsystem/syscall.h index 1b379fff..e625dfbf 100644 --- a/user/libs/libsystem/syscall.h +++ b/user/libs/libsystem/syscall.h @@ -27,6 +27,7 @@ #define SYS_PIPE 20 #define SYS_MSTAT 21 // 获取系统的内存状态信息 +#define SYS_RMDIR 22 // 删除文件夹 /** * @brief 用户态系统调用函数