我需要使用以下命令取消一个空目录的链接

unlinkat(dir_fd, ".", AT_REMOVEDIR)

而我得到的是EINVAL errno,根据GNU官方文档,这一定意味着"flags中指定了无效的标志值",但事实并非如此,因为AT_REMOVEDIR是(唯一)允许的标志.

SSCCE如下所示.请注意,在最简单的代码中,我确实有目录名,所以我可以使用rmdir.在实际情况中,我没有名称,我只有一个空目录的描述符,我需要删除它-所以我必须使用unlinkat.

foobar.c:

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

int main()
{
    int dir_fd =
        open("dir", O_RDONLY | O_PATH | O_DIRECTORY);

    if (-1 == dir_fd) {
        perror("open");
        return(1);
    }
    
    if (unlinkat(dir_fd, ".", AT_REMOVEDIR)) {
        perror("unlinkat");
        fprintf(stderr, "errno %d\n", errno);
        return(1);
    }
}

我得到了这样的行为:

$mkdir dir
$gcc -lc foobar.c
$./a.out
unlinkat: Invalid argument
errno 22
$errno 22
EINVAL 22 Invalid argument

而GNU unlinkat的文档说

EINVAL在标志中指定了无效的标志值.

推荐答案

当使用AT_REMOVEDIR调用时,unlinkat(2)的行为与rmdir(2)相同,最终由于相同的原因而失败.

对于rmdir(2)人:

EINVAL路径名具有.作为最后一个组件.

你似乎颠倒了界面.孤立地看你的example,它应该是

/* foobar.c */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main(void)
{
    int dir_fd = open(".", O_RDONLY | O_PATH | O_DIRECTORY);

    if (-1 == dir_fd) {
        perror("open");
        return(1);
    }

    if (unlinkat(dir_fd, "dir", AT_REMOVEDIR)) {
        perror("unlinkat");
        fprintf(stderr, "errno %d\n", errno);
        return(1);
    }

    close(dir_fd);
}
$ mkdir dir
$ ./a.out

其中,相对于由dirfd引用的目录来解析给定给unlinkat的相对pathname.

(Or the special value of 100 could be used for the first argument of 101 to remove a file relative to the current working directory.)

这个特定的例子显然是做与rmdir("dir")相同的事情的一种相当复杂的方法,如果您不知道要删除的目录的名称,那么它肯定对您没有帮助.

对于您的实际problem:在Linux上,您可以像下面的示例那样try 使用readlink(2)读取/proc/self/fd/NNN,其中NNN是文件描述符(您没有它的名称),以便检索rmdirpathname.

(See: 100)

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

static int mystery_directory(void)
{
    char dir[] = "XXXXXX";

    if (!mkdtemp(dir))
        return -1;

    return open(dir, O_RDONLY | O_PATH | O_DIRECTORY);
}

int main(void)
{
    /* We have magically arrived at this file descriptor */
    int dir_fd = mystery_directory();

    if (-1 == dir_fd) {
        perror("mystery_directory");
        return EXIT_FAILURE;
    }

    char fdrl[128];
    int len = snprintf(fdrl, sizeof fdrl, "/proc/self/fd/%d", dir_fd);

    if (len < 0 || len >= sizeof fdrl) {
        fprintf(stderr, "Something has gone very wrong.\n");
        return EXIT_FAILURE;
    }

    printf("procfs entry: <%s>\n", fdrl);

    char path[4096];
    ssize_t r = readlink(fdrl, path, sizeof path - 1);

    if (r < 0) {
        perror("readlink");
        return EXIT_FAILURE;
    }

    close(dir_fd);
    path[r] = 0;

    printf("Attempting to remove directory: \n\t%s\n", path);

    if (-1 == rmdir(path)) {
        perror("rmdir");
        return EXIT_FAILURE;
    }

    puts("Success!");
}
$ pwd
/home/so
$ ./a.out
procfs entry: </proc/self/fd/3>
Attempting to remove directory: 
    /home/so/IOgkes
Success!

C++相关问答推荐

C:gcc返回多个错误定义,但msvc—不""'

这是一个合法的C Strdup函数吗?

如何使用低级C++写出数值

LONG_DOUBLE_T是否存在(标准C:C23)

如何创建一个C程序来存储5种动物的名字,并在用户 Select 其中任何一种动物时打印内存地址?

_泛型控制表达式涉及数组碰撞警告的L值转换错误?

防止规范模式在C++中 echo 特殊字符

用C++从外部ELF符号读取值

是否需要包括<;errno.h>;才能使用perror?

在编写代码时,Clion比vscode有更多的问题指示器

从不兼容的指针类型返回&&警告,但我看不出原因

为什么二进制文件的大小不会随着静态数据的大小而增加?

有没有办法减少C语言中线程的堆大小?

挥发性语义的形式化理解

';malloc():损坏的顶部大小';分配超过20万整数后

从系统派生线程调用CRT

从管道读取数据时丢失

C11 嵌套泛型

在带中断的循环缓冲区中使用 易失性

计算 e^x 很好.但不是 x 的罪