如何让 unlinkat(dir_fd, ".", AT_REMOVEDIR) 工作?

问题描述 投票:0回答:1

我需要取消空目录的链接

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 在标志中指定了无效的标志值。

c linux unlink
1个回答
1
投票

当使用

AT_REMOVEDIR
调用时,
unlinkat(2)
的行为与
rmdir(2)
相同,最终会因为同样的原因而失败。

对于

rmdir(2)

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

你貌似把界面翻了,真的应该用做

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

或者

AT_FDCWD
的特殊值应该用于
unlinkat
的第一个参数来删除相对于当前工作目录的文件。

如果您不知道要删除的目录的名称,这显然对您没有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.