Browse Source

new: 将sys_rmdir更改为sys_unlink,.且完成删除文件操作的vfs部分 (#69)

login 2 years ago
parent
commit
8a080f3cce

+ 33 - 9
kernel/common/fcntl.h

@@ -10,22 +10,46 @@
  */
 #pragma once
 
-#define O_RDONLY 00000000 // Open Read-only
-#define O_WRONLY 00000001 // Open Write-only
-#define O_RDWR 00000002   // Open read/write
+#define O_RDONLY 00000000  // Open Read-only
+#define O_WRONLY 00000001  // Open Write-only
+#define O_RDWR 00000002    // Open read/write
 #define O_ACCMODE 00000003 // Mask for file access modes
 
-#define O_CREAT 00000100 // Create file if it does not exist
-#define O_EXCL 00000200 // Fail if file already exists
+#define O_CREAT 00000100  // Create file if it does not exist
+#define O_EXCL 00000200   // Fail if file already exists
 #define O_NOCTTY 00000400 // Do not assign controlling terminal
 
 #define O_TRUNC 00001000 // 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空
 
-#define O_APPEND 00002000   // 文件指针会被移动到文件末尾
+#define O_APPEND 00002000 // 文件指针会被移动到文件末尾
 
 #define O_NONBLOCK 00004000 // 非阻塞式IO模式
 
-#define O_EXEC 00010000 // 以仅执行的方式打开(非目录文件)
-#define O_SEARCH 00020000   // Open the directory for search only
+#define O_EXEC 00010000      // 以仅执行的方式打开(非目录文件)
+#define O_SEARCH 00020000    // Open the directory for search only
 #define O_DIRECTORY 00040000 // 打开的必须是一个目录
-#define O_NOFOLLOW 00100000 // Do not follow symbolic links
+#define O_NOFOLLOW 00100000  // Do not follow symbolic links
+
+/*
+ * The constants AT_REMOVEDIR and AT_EACCESS have the same value.  AT_EACCESS is
+ * meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
+ * unlinkat.  The two functions do completely different things and therefore,
+ * the flags can be allowed to overlap.  For example, passing AT_REMOVEDIR to
+ * faccessat would be undefined behavior and thus treating it equivalent to
+ * AT_EACCESS is valid undefined behavior.
+ */
+// 作为当前工作目录的文件描述符(用于指代cwd)
+#define AT_FDCWD -100
+#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links.  */
+#define AT_EACCESS 0x200          /* Test access permitted for effective IDs, not real IDs.  */
+#define AT_REMOVEDIR 0x200        /* Remove directory instead of unlinking file.  */
+#define AT_SYMLINK_FOLLOW 0x400   /* Follow symbolic links.  */
+#define AT_NO_AUTOMOUNT 0x800     /* Suppress terminal automount traversal */
+#define AT_EMPTY_PATH 0x1000      /* Allow empty relative pathname */
+
+#define AT_STATX_SYNC_TYPE 0x6000    /* Type of synchronisation required from statx() */
+#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
+#define AT_STATX_FORCE_SYNC 0x2000   /* - Force the attributes to be sync'd with the server */
+#define AT_STATX_DONT_SYNC 0x4000    /* - Don't sync attributes with the server */
+
+#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */

+ 7 - 0
kernel/common/user_namespace.h

@@ -0,0 +1,7 @@
+#pragma once
+
+// todo: 引入用户命名空间
+struct user_namespace
+{
+
+};

+ 177 - 37
kernel/filesystem/VFS/VFS.c

@@ -2,6 +2,7 @@
 #include "internal.h"
 #include "mount.h"
 #include <common/dirent.h>
+#include <common/err.h>
 #include <common/errno.h>
 #include <common/kprint.h>
 #include <common/string.h>
@@ -306,11 +307,8 @@ int64_t vfs_mkdir(const char *path, mode_t mode, bool from_userland)
         subdir_dentry->name_length = pathlen - last_slash - 1;
 
     for (int i = last_slash + 1, cnt = 0; i < pathlen && cnt < subdir_dentry->name_length; ++i, ++cnt)
-    {
         subdir_dentry->name[cnt] = path[i];
-    }
-    // kdebug("last_slash=%d", last_slash);
-    // kdebug("name=%s", path + last_slash + 1);
+    // 设置subdir的dentry的父路径
     subdir_dentry->parent = parent_dir;
 
     // kdebug("to mkdir, parent name=%s", parent_dir->name);
@@ -511,20 +509,7 @@ uint64_t do_open(const char *filename, int flags)
     else
         file_ptr->position = 0;
 
-    struct vfs_file_t **f = current_pcb->fds;
-
-    int fd_num = -1;
-
-    // 在指针数组中寻找空位
-    // todo: 当pcb中的指针数组改为动态指针数组之后,需要更改这里(目前还是静态指针数组)
-    for (int i = 0; i < PROC_MAX_FD_NUM; ++i)
-    {
-        if (f[i] == NULL) // 找到指针数组中的空位
-        {
-            fd_num = i;
-            break;
-        }
-    }
+    int fd_num = process_fd_alloc(file_ptr);
 
     // 指针数组没有空位了
     if (fd_num == -1)
@@ -533,8 +518,6 @@ uint64_t do_open(const char *filename, int flags)
         spin_unlock(&dentry->lockref.lock);
         return -ENFILE;
     }
-    // 保存文件描述符
-    f[fd_num] = file_ptr;
     spin_unlock(&dentry->lockref.lock);
     return fd_num;
 }
@@ -613,6 +596,7 @@ int vfs_may_delete(struct vfs_dir_entry_t *dentry, bool isdir)
 int64_t vfs_rmdir(const char *path, bool from_userland)
 {
     uint32_t pathlen;
+    int retval = 0;
     if (from_userland)
         pathlen = strnlen_user(path, PAGE_4K_SIZE - 1);
     else
@@ -650,47 +634,203 @@ int64_t vfs_rmdir(const char *path, bool from_userland)
 
     struct vfs_dir_entry_t *dentry = vfs_path_walk(buf, 0);
 
+    kfree(buf);
+
     if (dentry == NULL)
-        return -ENOENT;
+    {
+        retval = -ENOENT;
+        kdebug("noent");
+        goto out0;
+    }
+
+    // todo: 检查文件夹是否为空
 
-    int retval = vfs_may_delete(dentry, true);
+    spin_lock(&dentry->lockref.lock);
+    retval = vfs_may_delete(dentry, true);
     if (retval != 0)
-        return retval;
+        goto out1;
     // todo: 对dentry和inode加锁
-    spin_lock(&dentry->lockref.lock);
     retval = -EBUSY;
     if (is_local_mountpoint(dentry))
-        goto out;
+        goto out1;
     // todo:
     retval = dentry->dir_inode->inode_ops->rmdir(dentry->dir_inode, dentry);
     if (retval != 0)
-        goto out;
+    {
+        BUG_ON(1);
+        goto out1;
+    }
 
     dentry->dir_inode->attribute |= VFS_IF_DEAD; // 将当前inode标记为dead
     dont_mount(dentry);                          // 将当前dentry标记为不可被挂载
     detach_mounts(dentry);                       // 清理同样挂载在该路径的所有挂载点的挂载树
 
-    if (vfs_dentry_put(dentry) != 0)
-        goto out; // 释放dentry
+    // 释放dentry
+    retval = vfs_dentry_put(dentry);
+
+    if (retval != 0)
+        goto out1;
+    goto out0;
+out2:;
+    spin_unlock(&dentry->dir_inode->lockref.lock);
+out1:;
+    spin_unlock(&dentry->lockref.lock);
+out0:;
     return retval;
+}
+
+/**
+ * @brief unlink a filesystem object
+ *
+ * 调用者必须持有parent_inode->lockref.lock
+ *
+ * @param mnt_userns 暂时未使用 用户命名空间. 请置为NULL
+ * @param parent_inode 父目录项的inode
+ * @param dentry 要被删除的目录项
+ * @param delegated_inode 暂未使用,请置为NULL
+ * @return int
+ */
+int vfs_unlink(struct user_namespace *mnt_userns, struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dentry,
+               struct vfs_index_node_t **delegated_inode)
+{
+    // 暂时不支持用户命名空间,因此发出警告
+    if (unlikely(mnt_userns != NULL))
+    {
+        WARN_ON(1);
+        return -EINVAL;
+    }
+
+    int retval = 0;
+    struct vfs_index_node_t *target = dentry->dir_inode;
+
+    retval = vfs_may_delete(dentry, false);
+    if (unlikely(retval != 0))
+        return retval;
+
+    // 没有unlink方法,则不允许删除
+    if (!parent_inode->inode_ops->unlink)
+        return -EPERM;
+
+    // 对inode加锁
+    spin_lock(&target->lockref.lock);
+
+    if (is_local_mountpoint(dentry))
+        retval = -EBUSY;
+    else
+    {
+        retval = parent_inode->inode_ops->unlink(parent_inode, dentry);
+        if (retval == 0)
+        {
+            dont_mount(dentry);
+            detach_mounts(dentry);
+        }
+    }
+
+    spin_unlock(&target->lockref.lock);
+
+out:;
+    return retval;
+}
+/**
+ * @brief 取消dentry和inode之间的链接
+ *
+ * @param dfd 进程相对路径基准目录的文件描述符(fcntl.h)
+ * @param pathname 路径
+ * @param from_userland 请求是否来自用户态
+ * @return int 错误码
+ */
+int do_unlink_at(int dfd, const char *pathname, bool from_userland)
+{
+    // 暂时不支持相对路径,只支持绝对路径
+    if (dfd & AT_FDCWD)
+    {
+        kwarn("Not support: AT_FDCWD");
+        return -EINVAL;
+    }
+
+    uint32_t pathlen;
+    int retval = 0;
+    if (from_userland)
+        pathlen = strnlen_user(pathname, PAGE_4K_SIZE - 1);
+    else
+        pathlen = strnlen(pathname, PAGE_4K_SIZE - 1);
+
+    if (pathlen == 0)
+        return -ENOENT;
+
+    int last_slash = -1;
+
+    // 去除末尾的'/'
+    for (int i = pathlen - 1; i >= 0; --i)
+    {
+        if (pathname[i] != '/')
+        {
+            last_slash = i + 1;
+            break;
+        }
+    }
+
+    // 路径格式不合法
+    if (last_slash < 0)
+        return -ENOTDIR;
+    else if (pathname[0] != '/')
+        return -EINVAL;
+
+    char *buf = (char *)kzalloc(last_slash + 2, 0);
+
+    // 拷贝字符串(不包含要被创建的部分)
+    if (from_userland)
+        strncpy_from_user(buf, pathname, last_slash);
+    else
+        strncpy(buf, pathname, last_slash);
+    buf[last_slash + 1] = '\0';
+
+    struct vfs_dir_entry_t *dentry = vfs_path_walk(buf, 0);
+    kfree(buf);
+
+    if (dentry == NULL || dentry->parent == NULL)
+    {
+        retval = -ENOENT;
+        goto out;
+    }
+
+    struct vfs_index_node_t *p_inode = dentry->parent->dir_inode;
+    // 对父inode加锁
+    spin_lock(&p_inode);
+    retval = vfs_unlink(NULL, dentry->parent->dir_inode, dentry, NULL);
+
+    spin_lock(&dentry->lockref.lock);
+    retval = vfs_dentry_put(dentry);
+    spin_unlock(&p_inode);
+
+    if (IS_ERR(retval))
+        kwarn("In do_unlink_at: dentry put failed; retval=%d", retval);
+    else
+        retval = 0;
 out:;
-    spin_unlock(&dentry->lockref.lock);
-    // todo: 对dentry和inode放锁
     return retval;
 }
 
 /**
- * @brief 删除文件夹的系统调用函数
+ * @brief 删除文件夹、取消文件的链接、删除文件的系统调用
  *
- * @param r8 文件夹路径
+ * @param regs->r8 dfd 进程相对路径基准目录的文件描述符(见fcntl.h)
+ * @param regs->r9 路径名称字符串
+ * @param regs->r10 flag 预留的标志位,暂时未使用,请置为0。
  * @return uint64_t 错误码
  */
-uint64_t sys_rmdir(struct pt_regs *regs)
+uint64_t sys_unlink_at(struct pt_regs *regs)
 {
-    if (SYSCALL_FROM_USER(regs))
-        return vfs_rmdir((char *)regs->r8, true);
-    else
-        return vfs_rmdir((char *)regs->r8, false);
+    int dfd = regs->r8;
+    const char *pathname = regs->r9;
+    int flag = regs->r10;
+    bool from_user = SYSCALL_FROM_USER(regs) ? true : false;
+    if ((flag & (~AT_REMOVEDIR)) != 0)
+        return -EINVAL;
+    if (flag & AT_REMOVEDIR)
+        return vfs_rmdir(pathname, from_user);
+
+    return do_unlink_at(dfd, pathname, from_user);
 }
 
 /**

+ 15 - 1
kernel/filesystem/VFS/VFS.h

@@ -15,6 +15,7 @@
 #include <common/fcntl.h>
 #include <common/glib.h>
 #include <common/lockref.h>
+#include <common/user_namespace.h>
 #include <mm/slab.h>
 
 extern struct vfs_superblock_t *vfs_root_sb;
@@ -156,6 +157,14 @@ struct vfs_inode_operations_t
                    struct vfs_index_node_t *new_inode, struct vfs_dir_entry_t *new_dEntry);
     long (*getAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr);
     long (*setAttr)(struct vfs_dir_entry_t *dEntry, uint64_t *attr);
+    
+    /**
+     * @brief 取消inode和dentry之间的链接关系(删除文件)
+     * 
+     * @param inode 要被取消关联关系的目录项的【父目录项】
+     * @param dentry 要被取消关联关系的子目录项
+     */
+    long (*unlink)(struct vfs_index_node_t * inode, struct vfs_dir_entry_t * dentry);
 };
 
 struct vfs_dir_entry_operations_t
@@ -276,4 +285,9 @@ int64_t vfs_rmdir(const char *path, bool from_userland);
  * @return 错误码
  *          注意,当dentry指向文件时,如果返回值为正数,则表示在释放了该dentry后,该dentry指向的inode的引用计数。
  */
-int vfs_dentry_put(struct vfs_dir_entry_t *dentry);
+int vfs_dentry_put(struct vfs_dir_entry_t *dentry);
+
+int vfs_unlink(struct user_namespace *mnt_userns, struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_t *dentry,
+               struct vfs_index_node_t **delegated_inode);
+
+int do_unlink_at(int dfd, const char *pathname, bool name);

+ 8 - 5
kernel/filesystem/VFS/dcache.c

@@ -6,7 +6,7 @@
  * @brief 释放dentry,并视情况自动释放inode. 在调用该函数前,需要将dentry加锁。
  *
  * @param dentry 目标dentry
- * 
+ *
  * @return 错误码
  *          注意,当dentry指向文件时,如果返回值为正数,则表示在释放了该dentry后,该dentry指向的inode的引用计数。
  */
@@ -15,9 +15,10 @@ int vfs_dentry_put(struct vfs_dir_entry_t *dentry)
     int retval = 0;
     uint64_t in_value = 0;
     struct kfifo_t fifo = {0};
+    const struct vfs_dir_entry_t *start_dentry = dentry;
 
     // 引用计数大于1时,尝试释放dentry的话,抛出错误信息
-    if (unlikely(dentry->lockref.lock_count > 1))
+    if (unlikely(dentry->lockref.count > 1))
     {
         BUG_ON(1);
         retval = -EBUSY;
@@ -58,10 +59,12 @@ int vfs_dentry_put(struct vfs_dir_entry_t *dentry)
 
                 } while (list_next(list) != (&dentry->subdirs_list));
             }
-            spin_lock(&dentry->lockref.lock);
-            if(dentry->lockref.count>1)
+            if (unlikely(dentry != start_dentry))
+                spin_lock(&dentry->lockref.lock);
+            if (dentry->lockref.count > 1)
             {
-                spin_unlock(&dentry->lockref.lock);
+                if (unlikely(dentry != start_dentry))
+                    spin_unlock(&dentry->lockref.lock);
                 continue;
             }
             // 释放inode

+ 0 - 2
kernel/filesystem/fat32/fat32.c

@@ -969,8 +969,6 @@ int64_t fat32_mkdir(struct vfs_index_node_t *parent_inode, struct vfs_dir_entry_
     // todo: 填写完全fat32_inode_info的信息
 
     // 初始化dentry信息
-    list_init(&dEntry->child_node_list);
-    list_init(&dEntry->subdirs_list);
     dEntry->dir_ops = &fat32_dEntry_ops;
     dEntry->dir_inode = inode;
 

+ 32 - 14
kernel/filesystem/fat32/fat_ent.c

@@ -1,9 +1,10 @@
 #include "fat_ent.h"
-#include <driver/disk/ahci/ahci.h>
 #include <common/errno.h>
+#include <driver/disk/ahci/ahci.h>
 #include <mm/slab.h>
 
-static const char unavailable_character_in_short_name[] = {0x22, 0x2a, 0x2b, 0x2c, 0x2e, 0x2f, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x5b, 0x5c, 0x5d, 0x7c};
+static const char unavailable_character_in_short_name[] = {0x22, 0x2a, 0x2b, 0x2c, 0x2e, 0x2f, 0x3a, 0x3b,
+                                                           0x3c, 0x3d, 0x3e, 0x3f, 0x5b, 0x5c, 0x5d, 0x7c};
 /**
  * @brief 请求分配指定数量的簇
  *
@@ -133,8 +134,8 @@ uint32_t fat32_read_FAT_entry(struct block_device *blk, fat32_sb_info_t *fsbi, u
     memset(buf, 0, fsbi->bytes_per_sec);
 
     // 读取一个sector的数据,
-    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, fsbi->FAT1_base_sector + (cluster / fat_ent_per_sec), 1,
-                                 (uint64_t)&buf);
+    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT,
+                                 fsbi->FAT1_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)&buf);
 
     // 返回下一个fat表项的值(也就是下一个cluster)
     return buf[cluster & (fat_ent_per_sec - 1)] & 0x0fffffff;
@@ -156,15 +157,15 @@ uint32_t fat32_write_FAT_entry(struct block_device *blk, fat32_sb_info_t *fsbi,
     uint32_t fat_ent_per_sec = (fsbi->bytes_per_sec >> 2); // 该值应为2的n次幂
     uint32_t *buf = kzalloc(fsbi->bytes_per_sec, 0);
 
-    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT, fsbi->FAT1_base_sector + (cluster / fat_ent_per_sec), 1,
-                                 (uint64_t)buf);
+    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_READ_DMA_EXT,
+                                 fsbi->FAT1_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)buf);
 
     buf[cluster & (fat_ent_per_sec - 1)] = (buf[cluster & (fat_ent_per_sec - 1)] & 0xf0000000) | (value & 0x0fffffff);
     // 向FAT1和FAT2写入数据
-    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, fsbi->FAT1_base_sector + (cluster / fat_ent_per_sec), 1,
-                                 (uint64_t)buf);
-    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, fsbi->FAT2_base_sector + (cluster / fat_ent_per_sec), 1,
-                                 (uint64_t)buf);
+    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT,
+                                 fsbi->FAT1_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)buf);
+    blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT,
+                                 fsbi->FAT2_base_sector + (cluster / fat_ent_per_sec), 1, (uint64_t)buf);
 
     kfree(buf);
     return 0;
@@ -179,9 +180,12 @@ uint32_t fat32_write_FAT_entry(struct block_device *blk, fat32_sb_info_t *fsbi,
  * @param res_sector 返回信息:缓冲区对应的扇区号
  * @param res_cluster 返回信息:缓冲区对应的簇号
  * @param res_data_buf_base 返回信息:缓冲区的内存基地址(记得要释放缓冲区内存!!!!)
- * @return struct fat32_Directory_t* 符合要求的entry的指针(指向地址高处的空目录项,也就是说,有连续num个≤这个指针的空目录项)
+ * @return struct fat32_Directory_t*
+ * 符合要求的entry的指针(指向地址高处的空目录项,也就是说,有连续num个≤这个指针的空目录项)
  */
-struct fat32_Directory_t *fat32_find_empty_dentry(struct vfs_index_node_t *parent_inode, uint32_t num, uint32_t mode, uint32_t *res_sector, uint64_t *res_cluster, uint64_t *res_data_buf_base)
+struct fat32_Directory_t *fat32_find_empty_dentry(struct vfs_index_node_t *parent_inode, uint32_t num, uint32_t mode,
+                                                  uint32_t *res_sector, uint64_t *res_cluster,
+                                                  uint64_t *res_data_buf_base)
 {
     // kdebug("find empty_dentry");
     struct fat32_inode_info_t *finode = (struct fat32_inode_info_t *)parent_inode->private_inode_info;
@@ -251,7 +255,8 @@ struct fat32_Directory_t *fat32_find_empty_dentry(struct vfs_index_node_t *paren
             // 将这个新的簇清空
             sector = fsbi->first_data_sector + (cluster - 2) * fsbi->sec_per_clus;
             void *tmp_buf = kzalloc(fsbi->bytes_per_clus, 0);
-            blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus, (uint64_t)tmp_buf);
+            blk->bd_disk->fops->transfer(blk->bd_disk, AHCI_CMD_WRITE_DMA_EXT, sector, fsbi->sec_per_clus,
+                                         (uint64_t)tmp_buf);
             kfree(tmp_buf);
         }
     }
@@ -327,6 +332,12 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory
             else
                 target->DIR_Name[tmp_index] = 0x20;
         }
+        // 在字符串末尾加入\0
+        if (tmp_index < 8 && tmp_index == dEntry->name_length)
+        {
+            target->DIR_Name[tmp_index] = '\0';
+            ++tmp_index;
+        }
 
         // 不满的部分使用0x20填充
         while (tmp_index < 8)
@@ -373,7 +384,8 @@ void fat32_fill_shortname(struct vfs_dir_entry_t *dEntry, struct fat32_Directory
  * @param checksum 短目录项的校验和
  * @param cnt_longname 总的长目录项的个数
  */
-void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirectory_t *target, uint8_t checksum, uint32_t cnt_longname)
+void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirectory_t *target, uint8_t checksum,
+                         uint32_t cnt_longname)
 {
     uint32_t current_name_index = 0;
     struct fat32_LongDirectory_t *Ldentry = (struct fat32_LongDirectory_t *)(target + 1);
@@ -387,6 +399,8 @@ void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirect
         {
             if (current_name_index < dEntry->name_length)
                 Ldentry->LDIR_Name1[j] = dEntry->name[current_name_index];
+            else if (current_name_index == dEntry->name_length)
+                Ldentry->LDIR_Name1[j] = '\0';
             else
                 Ldentry->LDIR_Name1[j] = 0xffff;
         }
@@ -394,6 +408,8 @@ void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirect
         {
             if (current_name_index < dEntry->name_length)
                 Ldentry->LDIR_Name2[j] = dEntry->name[current_name_index];
+            else if (current_name_index == dEntry->name_length)
+                Ldentry->LDIR_Name1[j] = '\0';
             else
                 Ldentry->LDIR_Name2[j] = 0xffff;
         }
@@ -401,6 +417,8 @@ void fat32_fill_longname(struct vfs_dir_entry_t *dEntry, struct fat32_LongDirect
         {
             if (current_name_index < dEntry->name_length)
                 Ldentry->LDIR_Name3[j] = dEntry->name[current_name_index];
+            else if (current_name_index == dEntry->name_length)
+                Ldentry->LDIR_Name1[j] = '\0';
             else
                 Ldentry->LDIR_Name3[j] = 0xffff;
         }

+ 2 - 2
kernel/syscall/syscall.c

@@ -18,7 +18,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);
+extern uint64_t sys_unlink_at(struct pt_regs *regs);
 
 /**
  * @brief 导出系统调用处理函数的符号
@@ -607,7 +607,7 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NUM] = {
     [19] = sys_clock,
     [20] = sys_pipe,
     [21] = sys_mstat,
-    [22] = sys_rmdir,
+    [22] = sys_unlink_at,
     [23 ... 254] = system_call_not_exists,
     [255] = sys_ahci_end_req,
 };

+ 1 - 1
kernel/syscall/syscall_num.h

@@ -33,7 +33,7 @@
 #define SYS_PIPE 20
 
 #define SYS_MSTAT 21    // 获取系统的内存状态信息
-#define SYS_RMDIR 22    // 删除文件夹
+#define SYS_UNLINK_AT 22    // 删除文件夹/删除文件链接
 
 
 #define SYS_AHCI_END_REQ 255    // AHCI DMA请求结束end_request的系统调用

+ 23 - 0
user/libs/libc/fcntl.h

@@ -30,6 +30,29 @@
 #define O_DIRECTORY 00040000 // 打开的必须是一个目录
 #define O_NOFOLLOW 00100000 // Do not follow symbolic links
 
+/*
+ * The constants AT_REMOVEDIR and AT_EACCESS have the same value.  AT_EACCESS is
+ * meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
+ * unlinkat.  The two functions do completely different things and therefore,
+ * the flags can be allowed to overlap.  For example, passing AT_REMOVEDIR to
+ * faccessat would be undefined behavior and thus treating it equivalent to
+ * AT_EACCESS is valid undefined behavior.
+ */
+// 作为当前工作目录的文件描述符(用于指代cwd)
+#define AT_FDCWD -100
+#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links.  */
+#define AT_EACCESS 0x200          /* Test access permitted for effective IDs, not real IDs.  */
+#define AT_REMOVEDIR 0x200        /* Remove directory instead of unlinking file.  */
+#define AT_SYMLINK_FOLLOW 0x400   /* Follow symbolic links.  */
+#define AT_NO_AUTOMOUNT 0x800     /* Suppress terminal automount traversal */
+#define AT_EMPTY_PATH 0x1000      /* Allow empty relative pathname */
+
+#define AT_STATX_SYNC_TYPE 0x6000    /* Type of synchronisation required from statx() */
+#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
+#define AT_STATX_FORCE_SYNC 0x2000   /* - Force the attributes to be sync'd with the server */
+#define AT_STATX_DONT_SYNC 0x4000    /* - Don't sync attributes with the server */
+
+#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
 
 /**
  * @brief 打开文件的接口

+ 2 - 1
user/libs/libc/unistd.c

@@ -4,6 +4,7 @@
 #include <libc/stdio.h>
 #include <libc/stddef.h>
 #include <libc/string.h>
+#include <libc/fcntl.h>
 
 /**
  * @brief 关闭文件接口
@@ -157,7 +158,7 @@ int execv(const char *path, char *const argv[])
  */
 int rmdir(const char *path)
 {
-    return syscall_invoke(SYS_RMDIR, (uint64_t)path, 0, 0, 0, 0, 0, 0, 0);
+    return syscall_invoke(SYS_UNLINK_AT, 0, (uint64_t)path, AT_REMOVEDIR, 0, 0, 0, 0, 0);
 }
 
 /**

+ 1 - 1
user/libs/libsystem/syscall.h

@@ -27,7 +27,7 @@
 #define SYS_PIPE 20
 
 #define SYS_MSTAT 21    // 获取系统的内存状态信息
-#define SYS_RMDIR 22    // 删除文件夹
+#define SYS_UNLINK_AT 22    // 删除文件夹/删除文件链接
 
 /**
  * @brief 用户态系统调用函数