I need to unlink an empty directory with
unlinkat(dir_fd, ".", AT_REMOVEDIR)
and I am getting EINVAL errno, which, according to official GNU documentation, must mean "An invalid flag value was specified in flags", which is not the case, as AT_REMOVEDIR is (the only) allowed flag.
SSCCE is as follows. Note, that in the simplest code, I do have the directory name, so I could have used rmdir. In the real situation, I don't have the name, I only have the descriptor, to an empty directory, and I need to remove it - so I have to use 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);
}
}
and I get this behaviour:
$mkdir dir
$gcc -lc foobar.c
$./a.out
unlinkat: Invalid argument
errno 22
$errno 22
EINVAL 22 Invalid argument
and GNU documentation for unlinkat says
EINVAL An invalid flag value was specified in flags.
When called with
AT_REMOVEDIR,unlinkat(2)behaves asrmdir(2), and ultimately fails to the same reasons.For
rmdir(2):You have seemingly flipped the interface. Looking at your example in isolation, it should be
where a relative pathname given to
unlinkatis resolved relative to the directory referred to by dirfd.(Or the special value of
AT_FDCWDcould be used for the first argument ofunlinkatto remove a file relative to the current working directory.)This particular example is obviously a rather complex way of doing the same thing
rmdir("dir")does, and it certainly does not help you if you do not know the name of the directory to be removed.For your actual problem: On Linux, you can try something along the lines of the following example, that uses
readlink(2)to read /proc/self/fd/NNN, where NNN is the file descriptor (for which you do not have a name), in order to retrieve a pathname forrmdir.(See: Retrieve filename from file descriptor in C)