18 读书笔记:第4章 文件和目录 (1)

4.2 stat、fstat和lstat函数

       #include <sys/stat.h>
       int stat(const char *restrict path, struct stat *restrict buf);
       int fstat(int fildes, struct stat *buf);
       int lstat(const char *restrict path, struct stat *restrict buf);
       // 三个函数的返回值:若成功则返回0,若出错则返回-1

        stat函数获取指定路径上的文件的相关信息结构;

        fstat函数获取已在描述符filedes上打开的文件的有关信息;

        lstat函数类似于stat,但是当命名文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。

        第二个参数中,struct stat结构如下:

           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */
               mode_t    st_mode;    /* protection */
               nlink_t   st_nlink;   /* number of hard links */
               uid_t     st_uid;     /* user ID of owner */
               gid_t     st_gid;     /* group ID of owner */
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */
               blksize_t st_blksize; /* blocksize for filesystem I/O */
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
               time_t    st_atime;   /* time of last access */
               time_t    st_mtime;   /* time of last modification */
               time_t    st_ctime;   /* time of last status change */
           };

        该结构中的每一个成员都是基本系统数据类型。

4.3 文件类型

        UNIX系统的文件类型包括如下几种:

                (1) 普通文件(regular file)。

                (2) 目录文件(directory file)。只有内核可以直接写目录文件(什么意思?)。

                (3) 块特殊文件(block special file)。

                (4) 字符特殊文件(character special file)。

                (5) FIFO。

                (6) 套接字(socket)。

                (7) 符号链接(symbolic link)。

        文件类型信息包含在stat结构的st_mode成员中。可以使用如下的宏确定文件类型:

           S_ISREG(m)  is it a regular file?
           S_ISDIR(m)  directory?
           S_ISCHR(m)  character device?
           S_ISBLK(m)  block device?
           S_ISFIFO(m) FIFO (named pipe)?
           S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)
           S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)

        《UNIX环境高级编程》P73:程序清单4-1 对每个命令行参数打印文件类型

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>

int main(int argc, char *argv[])
{
    int             i;
    struct stat     buf;
    char            *ptr;

    for (i = 1; i < argc; i++) {
        printf("%s: ", argv[i]);
    
        // lstat能返回符号链接的相关信息,而不是由该符号链接引用文件的信息
        if (lstat(argv[i], &buf) == -1) {   
            fprintf(stderr, "lstat error:%s\n", strerror(errno));
            continue;
        }
        if (S_ISREG(buf.st_mode))
            ptr = "regular";
        else if (S_ISDIR(buf.st_mode))
            ptr = "directory";
        else if (S_ISCHR(buf.st_mode))
            ptr = "character special";
        else if (S_ISBLK(buf.st_mode))
            ptr = "block special";
        else if (S_ISFIFO(buf.st_mode))
            ptr = "fifo";
        else if (S_ISLNK(buf.st_mode))
            ptr = "symbolic link";
        else if (S_ISSOCK(buf.st_mode))
            ptr = "socket";
        else
            ptr = "** unknown mode **";
        printf("%s\n", ptr);
    }   
    exit(0);
}

        编译生成的文件名为01,运行程序:

$ ./01 /etc/passwd /etc /dev/fd/1 /dev/log /dev/tty /dev/sda1 /dev/cdrom 
/etc/passwd: regular
/etc: directory
/dev/fd/1: symbolic link
/dev/log: socket
/dev/tty: character special
/dev/sda1: block special
/dev/cdrom: symbolic link

        从中可以看出磁盘(/dev/sda1)是块特殊文件,而终端设备(/dev/tty)是字符特殊文件。

        /dev/log 是一个socket,莫非日志是通过socket的方式来记录的?

        早期的UNIX系统版本并不提供S_ISxxx宏,于是就需要将st_mode与屏蔽字S_IFMT进行逻辑"与"运算,然后与名为S_IFxxx的常量相比较。

你可能感兴趣的:(读书笔记,《UNIX环境高级编程》)