2

What is the meaning of F_GETFD in fcntl() function in unix ?, From what I understand it should return -1 if there is no file descriptor in the position specified.. If that's true, when would it happen ? when doing close to a file descriptor in that posstion, F_GETFD doesn't return -1 either..

This is a part of a program using F_GETFD and it will not return -1 if I close the x fd (thid fd entered 0 in the fd table since we closed 0 beforehand and did dup(x)):

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>


void try(){
printf("got_sig\n");
}
int main(int argc, char *argv[]){
int x, stdout=1;
signal(SIGUSR1,&try);
x = open("t1.txt",O_RDWR|O_CREAT, 0666);
close(0);
dup(x);
close(x);
if (fcntl(0,F_GETFD)==-1)
printf("false\n");
kill(getpid(),SIGUSR1);
//close(x);
write(stdout,"BYE\n",4);
exit(0);
}

When will F_GETFD return -1 ?

Ben J
  • 147
  • 2
  • 14

2 Answers2

2

From the man page of fcntl():

File descriptor flags
The following commands manipulate the flags associated with a file descriptor. Currently, only one such flag is defined: FD_CLOEXEC, the close-on-exec flag. If the FD_CLOEXEC bit is set, the file descriptor will automatically be closed during a successful execve(2).

F_GETFD (void)
Return (as the function result) the file descriptor flags; arg is ignored.

(Or see the POSIX standard text for fctnl(), if you care.)

So, fnctl(fd, F_GETFD) tells you if the file descriptor stays open over an execve() or not.

The usual error cases for fcntl() apply, so it would e.g. return -1 and set errno to EBADF if the fd you gave wasn't open. In your code, you called fcntl() on fd 0, which holds the dup'ed copy of x, and so is open. fcntl() would return -1 for the fd x, though, that's the one you explicitly closed.

ilkkachu
  • 6,221
  • 16
  • 30
0

Inspecting the implementation of do_fcntl in the Linux kernel, we can see that:

static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
        struct file *filp)
{
    long err = -EINVAL;
    switch (cmd) {
    ...
    case F_GETFD:
        err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;
        break;
    ...
    }
    return err;
}

do_fcntl(F_GETFD) may return only FD_CLOEXEC or 0.

The syscall definition from here can return -EBADF in case of a bad file descriptor or the file descriptor was opened with O_PATH.

Judging from that, the fcntl(F_GETFD) will return only -1 with errno set to -9 (-EBADF), or return 0 or 1 (FD_CLOEXEC) on Linux 4.20. So the fcntl(F_GETFD) will return -1 in case of a bad file descriptor or file descriptor opened with O_PATH. Note that for other kernels it may be different and note that it can change over time.

ilkkachu
  • 6,221
  • 16
  • 30
KamilCuk
  • 120,984
  • 8
  • 59
  • 111