You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何unlinkat(dir_fd, ".", AT_REMOVEDIR)返回EINVAL错误?如何解决?

问题原因

你的代码返回EINVAL,是因为当dir_fd指向要删除的目录本身时,不能用unlinkat(dir_fd, ".", AT_REMOVEDIR)来删除它。unlinkat搭配AT_REMOVEDIR使用时,要求pathname必须是dir_fd所指向目录的子项,而非目录自身——这和rmdir无法删除当前工作目录的逻辑一致。

解决方案

由于你仅持有目标目录的文件描述符,需要先获取它的父目录描述符,再通过父目录完成删除操作。以下是可运行的修正代码:

#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    int dir_fd = open("dir", O_RDONLY | O_PATH | O_DIRECTORY);
    if (-1 == dir_fd) {
        perror("open");
        return 1;
    }

    // 获取目标目录的绝对路径
    char dir_path[PATH_MAX];
    if (fcntl(dir_fd, F_GETPATH, dir_path) == -1) {
        perror("fcntl F_GETPATH");
        close(dir_fd);
        return 1;
    }

    // 提取父目录路径与目标目录名称
    char* last_slash = strrchr(dir_path, '/');
    if (!last_slash || last_slash == dir_path) {
        fprintf(stderr, "无法获取父目录路径\n");
        close(dir_fd);
        return 1;
    }
    *last_slash = '\0'; // 截断字符串得到父目录路径
    const char* child_name = last_slash + 1; // 目标目录的名称

    // 打开父目录
    int parent_fd = open(dir_path, O_RDONLY | O_PATH | O_DIRECTORY);
    if (-1 == parent_fd) {
        perror("open parent dir");
        close(dir_fd);
        return 1;
    }

    // 通过父目录删除目标目录
    if (unlinkat(parent_fd, child_name, AT_REMOVEDIR)) {
        perror("unlinkat");
        fprintf(stderr, "errno %d\n", errno);
        close(parent_fd);
        close(dir_fd);
        return 1;
    }

    close(parent_fd);
    close(dir_fd);
    printf("目录删除成功\n");
    return 0;
}

关键逻辑说明

  • fcntl(dir_fd, F_GETPATH, dir_path):通过文件描述符获取目录的绝对路径,需定义_GNU_SOURCE启用该扩展功能。
  • 路径拆分:通过查找最后一个/截断路径,分离出父目录路径和目标目录的名称。
  • 父目录删除:打开父目录后,用unlinkat删除父目录下的目标目录项,完全符合AT_REMOVEDIR的使用规则。

替代方案(依赖Proc文件系统)

如果系统支持Proc文件系统,也可以通过读取符号链接获取目录路径,替换上述代码中的路径获取部分:

// 替换fcntl相关代码
char proc_link[PATH_MAX];
snprintf(proc_link, sizeof(proc_link), "/proc/self/fd/%d", dir_fd);
ssize_t len = readlink(proc_link, dir_path, sizeof(dir_path)-1);
if (len == -1) {
    perror("readlink");
    close(dir_fd);
    return 1;
}
dir_path[len] = '\0';
// 后续路径拆分逻辑保持不变

内容的提问来源于stack exchange,提问作者Mark Galeck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:30:05