#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 */ };
该结构中的每一个成员都是基本系统数据类型。
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的常量相比较。