diff --git a/kernel/common/fcntl.h b/kernel/common/fcntl.h index 19387931..1c0226b8 100644 --- a/kernel/common/fcntl.h +++ b/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 */ \ No newline at end of file diff --git a/kernel/common/user_namespace.h b/kernel/common/user_namespace.h new file mode 100644 index 00000000..bf49b29a --- /dev/null +++ b/kernel/common/user_namespace.h @@ -0,0 +1,7 @@ +#pragma once + +// todo: 引入用户命名空间 +struct user_namespace +{ + +}; \ No newline at end of file diff --git a/kernel/filesystem/VFS/VFS.c b/kernel/filesystem/VFS/VFS.c index 010dd9c0..9f4f98cb 100644 --- a/kernel/filesystem/VFS/VFS.c +++ b/kernel/filesystem/VFS/VFS.c @@ -2,6 +2,7 @@ #include "internal.h" #include "mount.h" #include +#include #include #include #include @@ -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); - if (dentry == NULL) - return -ENOENT; + kfree(buf); + + if (dentry == NULL) + { + retval = -ENOENT; + kdebug("noent"); + goto out0; + } + + // todo: 检查文件夹是否为空 - int retval = vfs_may_delete(dentry, true); - if (retval != 0) - return retval; - // todo: 对dentry和inode加锁 spin_lock(&dentry->lockref.lock); + retval = vfs_may_delete(dentry, true); + if (retval != 0) + goto out1; + // todo: 对dentry和inode加锁 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 - return retval; -out:; + // 释放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); - // todo: 对dentry和inode放锁 +out0:; return retval; } /** - * @brief 删除文件夹的系统调用函数 + * @brief unlink a filesystem object * - * @param r8 文件夹路径 + * 调用者必须持有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:; + return retval; +} + +/** + * @brief 删除文件夹、取消文件的链接、删除文件的系统调用 + * + * @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); } /** diff --git a/kernel/filesystem/VFS/VFS.h b/kernel/filesystem/VFS/VFS.h index 7c88f944..9be08e42 100644 --- a/kernel/filesystem/VFS/VFS.h +++ b/kernel/filesystem/VFS/VFS.h @@ -15,6 +15,7 @@ #include #include #include +#include #include 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); \ No newline at end of file +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); \ No newline at end of file diff --git a/kernel/filesystem/VFS/dcache.c b/kernel/filesystem/VFS/dcache.c index 13ad3032..609851c5 100644 --- a/kernel/filesystem/VFS/dcache.c +++ b/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 diff --git a/kernel/filesystem/fat32/fat32.c b/kernel/filesystem/fat32/fat32.c index 78529fb2..e5d47715 100644 --- a/kernel/filesystem/fat32/fat32.c +++ b/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; diff --git a/kernel/filesystem/fat32/fat_ent.c b/kernel/filesystem/fat32/fat_ent.c index 8ce57796..270c5d06 100644 --- a/kernel/filesystem/fat32/fat_ent.c +++ b/kernel/filesystem/fat32/fat_ent.c @@ -1,9 +1,10 @@ #include "fat_ent.h" -#include #include +#include #include -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; } diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index c9083c7b..1c16d8a0 100644 --- a/kernel/syscall/syscall.c +++ b/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, }; diff --git a/kernel/syscall/syscall_num.h b/kernel/syscall/syscall_num.h index e7e0bbdf..1ffbe9b7 100644 --- a/kernel/syscall/syscall_num.h +++ b/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的系统调用 \ No newline at end of file diff --git a/user/libs/libc/fcntl.h b/user/libs/libc/fcntl.h index bb797cac..134ac8e8 100644 --- a/user/libs/libc/fcntl.h +++ b/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 打开文件的接口 diff --git a/user/libs/libc/unistd.c b/user/libs/libc/unistd.c index de88bf6d..fff215cf 100644 --- a/user/libs/libc/unistd.c +++ b/user/libs/libc/unistd.c @@ -4,6 +4,7 @@ #include #include #include +#include /** * @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); } /** diff --git a/user/libs/libsystem/syscall.h b/user/libs/libsystem/syscall.h index e625dfbf..ef13f3c3 100644 --- a/user/libs/libsystem/syscall.h +++ b/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 用户态系统调用函数