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

This commit is contained in:
login 2022-10-25 23:02:35 +08:00 committed by GitHub
parent e002152383
commit 8a080f3cce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 304 additions and 76 deletions

View File

@ -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 */

View File

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

View File

@ -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);
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);
}
/**

View File

@ -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);

View File

@ -6,7 +6,7 @@
* @brief dentryinode. 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

View File

@ -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;

View File

@ -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;
}

View File

@ -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,
};

View File

@ -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的系统调用

View File

@ -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

View File

@ -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);
}
/**

View File

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