Non blocking pipe descriptor flag value interpretation

101 Views Asked by At

I am trying to code a nonblocking pipe, my code is as follow

int fd = open(fifo_path, O_RDONLY | O_NONBLOCK );
int flag = fcntl(fd, F_GETFL, 0);
printf("flag is %d \n", flag);

The flag printout is 34816 in decimal (or 8800 in hex). I have checked the fcntl-Linux.h, I have found the value should be 04000 in hex (O_RDONLY | O_NONBLOCK. is 0 | 04000)

Is my calculation rite? Just trying to check the numbers

Thanks Regards

1

There are 1 best solutions below

0
Jonathan Leffler On

Using the information from the POSIX specifications of fcntl() and <fcntl.h>, you might come up with this code. It uses some error reporting code that is available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c and stderr.h in the src/libsoq sub-directory.

/* SO 7574-0162 */
#include <fcntl.h>      /* fcntl() */
#include <stdio.h>      /* printf() */
#include <unistd.h>     /* unlink() */
#include <sys/stat.h>   /* mkfifo() */
#include "stderr.h"     /* err_setarg0(), err_syserr() */

int main(void)
{
    err_setarg0("fcntl13");
    const char fifo_path[] = "tmp.fifo";

    if (mkfifo(fifo_path, 0666) != 0)
        err_syserr("failed to create FIFO %s: ", fifo_path);

    int fd = open(fifo_path, O_RDONLY | O_NONBLOCK);
    if (fd < 0)
        err_syserr("failed to open FIFO %s: ", fifo_path);
    int flag = fcntl(fd, F_GETFL, 0);
    if (flag < 0)
        err_syserr("fcntl() failed: ");

    printf("flag = %6d = 0x%.4X (%#.6o)\n", flag, flag, flag);

    int accmode = flag & O_ACCMODE;
    if (accmode == O_EXEC)
        printf("mode => %-10s (0x%.4X)\n", "O_EXEC", O_EXEC);
    if (accmode == O_RDONLY)
        printf("mode => %-10s (0x%.4X)\n", "O_RDONLY", O_RDONLY);
    if (accmode == O_RDWR)
        printf("mode => %-10s (0x%.4X)\n", "O_RDWR", O_RDWR);
    if (accmode == O_SEARCH)
        printf("mode => %-10s (0x%.4X)\n", "O_SEARCH", O_SEARCH);
    if (accmode == O_WRONLY)
        printf("mode => %-10s (0x%.4X)\n", "O_WRONLY", O_WRONLY);

    if (flag & O_APPEND)
        printf("flag => %-10s (0x%.4X)\n", "O_APPEND", O_APPEND);
    if (flag & O_DSYNC)
        printf("flag => %-10s (0x%.4X)\n", "O_DSYNC", O_DSYNC);
    if (flag & O_NONBLOCK)
        printf("flag => %-10s (0x%.4X)\n", "O_NONBLOCK", O_NONBLOCK);
#ifdef O_RSYNC      /* Not present on macOS Ventura 13.2.1 */
    if (flag & O_RSYNC)
        printf("flag => %-10s (0x%.4X)\n", "O_RSYNC", O_RSYNC);
#endif
    if (flag & O_SYNC)
        printf("flag => %-10s (0x%.4X)\n", "O_SYNC", O_SYNC);

    /* There's nothing you can do if the close fails */
    /* The code could report if it fails to unlink the FIFO, but ... */
    close(fd);
    unlink(fifo_path);
    return 0;
}

When run on a MacBook Pro running macOS Ventura 13.2.1, I get the output:

flag =      4 = 0x0004 (000004)
mode => O_RDONLY   (0x0000)
flag => O_NONBLOCK (0x0004)

Clearly, the code could/should be revised to take a file type and file name as an argument, a value for the open mode, and a value for the file permissions. It might be commanded to create the file (like it creates the temporary FIFO), but would not create the file by default, and so on — the design requires a bit of thought, especially if the open modes and permissions are to be strings rather than just numbers.