03.14 用 fcntl 检查文件属性

抄的书上的代码。

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/syscall.h>
#include <sys/times.h>
#include <unistd.h>

extern int errno;

void
perror_and_exit (const char *msg)
{
    perror (msg);
    exit (errno);
}

int
main (int argc, char **argv)
{
    int val;
    if (argc != 2)
        {
            fputs ("usage: a.out <descriptor#>\n", stderr);
            exit (1);
        }
    if ((val = fcntl (atoi (argv[1]), F_GETFL, 0)) < 0)
        {
            int ec = errno;
            fprintf (stderr, "fcntl error for fd %d: %s", atoi (argv[1]),
                     strerror (ec));
            exit (ec);
        }
    switch (val & O_ACCMODE)
        {
        case O_RDONLY:
            printf ("read only");
            break;
        case O_WRONLY:
            printf ("write only");
            break;
        case O_RDWR:
            printf ("read write");
            break;
        default:
            perror_and_exit ("unknown access mode");
        }
    if (val & O_APPEND)
        printf (", append");
    if (val & O_NONBLOCK)
        printf (", nonblocking");
    if (val & O_SYNC)
        printf (", synchronous writes");
#if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC) && (O_FSYNC != O_SYNC)
    if (val & O_FSYNC)
        printf (", synchronous writes");
#endif
    putchar ('\n');
    exit (0);
}

非常惊讶的是,Linux 上 Bash 给应用程序分配的标准输入、输出、错误流都是可读可写的。似乎 Bash 是把当前的打字机设备(tty)打开并分配给了应用程序的三个标准流,因为 /proc/<pid>/fd/0 (和其他两个)都是链接到了 /dev/pts/5 上,而这个设备是我当前的终端。


$ /data/apue/build/apue 0
read write
$ /data/apue/build/apue 1
read write
$ /data/apue/build/apue 2
read write
$ /data/apue/build/apue 0 <A.txt
read only
$ /data/apue/build/apue 0 <>A.txt
read write
$ /data/apue/build/apue 5 5<>B.txt
read write

注意 Bash 中 /data/apue/build/apue 5 5<>B.txt 这种重定向,它把 5 号文件描述符分配给了 B.txt 文件,而且是用可写的方式打开。因为这里有写方式打开,所以 B.txt 不存在时会自动创建,如果是只读方式打开,那么 B.txt 不存在就会报错。