1.函数功能:
通过文件名filename获取文件信息,并保存在buf所指的结构体stat中。
2.函数原型
函数头文件
#include <sys/stat.h>
#include <unistd.h>
函数
int stat(const char *file_name, struct stat *buf )
返回值:
执行成功则返回0,失败返回-1,错误代码存于errno
错误代码 | 说明 |
---|---|
ENOENT | 参数file_name指定的文件不存在 |
ENOTDIR | 路径中的目录存在但却非真正的目录 |
ELOOP | 欲打开的文件有过多符号连接问题,上限为16符号连接 |
EFAULT | 参数buf为无效指针,指向无法存在的内存空间 |
EACCESS | 存取文件时被拒绝 |
ENOMEM | 核心内存不足 |
ENAMETOOLONG | 参数file_name的路径名称太长 |
相关结构体
struct stat {
dev_t st_dev; //文件的设备编号
ino_t st_ino; //节点
mode_t st_mode; //文件的类型和存取的权限
nlink_t st_nlink; //连到该文件的硬连接数目,刚建立的文件值为1
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
dev_t st_rdev; //(设备类型)若此文件为设备文件,则为其设备编号
off_t st_size; //文件字节数(文件大小)
unsigned long st_blksize; //块大小(文件系统的I/O 缓冲区大小)
unsigned long st_blocks; //块数
time_t st_atime; //最后一次访问时间
time_t st_mtime; //最后一次修改时间
time_t st_ctime; //最后一次改变时间(指属性)
};
其中的st_mode(32位整型变量,不过现在的Linux操作系统只用了低16位。),该成员描述了文件的类型和权限两个属性。
S_IFMT 0170000 文件类型的位遮罩
S_IFSOCK 0140000 scoket文件(套接口文件)
S_IFLNK 0120000 符号连接(符号链接文件)
S_IFREG 0100000 一般文件(普通文件)
S_IFBLK 0060000 区块装置(块设备)
S_IFDIR 0040000 目录
S_IFCHR 0020000 字符装置(字符设备)
S_IFIFO 0010000 先进先出(管道)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
S_ISUID 04000 文件的(set user-id on execution)位
S_ISGID 02000 文件的(set group-id on execution)位
S_ISVTX 01000 文件的sticky位
S_IRUSR(S_IREAD) 00400 文件所有者具可读取权限
S_IWUSR(S_IWRITE)00200 文件所有者具可写入权限
S_IXUSR(S_IEXEC) 00100 文件所有者具可执行权限
S_IRGRP 00040 用户组具可读取权限
S_IWGRP 00020 用户组具可写入权限
S_IXGRP 00010 用户组具可执行权限
S_IROTH 00004 其他用户具可读取权限
S_IWOTH 00002 其他用户具可写入权限
S_IXOTH 00001 其他用户具可执行权限
File type属性区域,位于bit12-bit15占4位,在现代Linux操作系统上文件类型共分为7中,分别是:
普通文件(regular file)
目录(directory)
字符设备(character device)
块设备(block device)
管道(FIFO)
符号链接文件(symbolic link)
套接口文件(socket)
所以File type属性只需3bit就够了,估计也是考虑到了以后的扩展问题。
首先S_IFMT是一个掩码,它的值是0170000(注意这里使用的是八进制),可以用来过滤出12-15位的文件类型。
现在假设我们要判断一个文件是不是目录,我们怎么做呢?
很简单,首先通过掩码S_IFMT把其它无关的部分置0,再与表示目录的数值比较,从而判断这是否是一个目录,下面的代码:
if ((info.st_mode & S_IFMT) == S_IFDIR)
printf("this is a directory");
为了便于操作,<sys/stat.h>
中提供了宏来代替上述代码,所以如果需要判断文件是不是目录也可以这样:
if (S_ISDIR(info.st_mode))
printf("this is a directory");
接着来看Permission属性区域的bit0-bit8,也即st_mode字段的最低9位,代表文件的许可权限,它标示了文件所有者(owner)、组用户(group)、其它用户(other)的读(r)、写(w)、执行(x)权限。
在<sys/stat.h>
有如下定义:
#define S_IRWXU 00700 /* mask for file owner permissions */
#define S_IRUSR 00400 /* owner has read permission */
#define S_IWUSR 00200 /* owner has write permission */
#define S_IXUSR 00100 /* owner has execute permission */
#define S_IRWXG 00070 /* mask for group permissions */
#define S_IRGRP 00040 /* group has read permission */
#define S_IWGRP 00020 /* group has write permission */
#define S_IXGRP 00010 /* group has execute permission */
#define S_IRWXO 00007 /* mask for permissions for others (not in group) */
#define S_IROTH 00004 /* others have read permission */
#define S_IWOTH 00002 /* others have write permission */
#define S_IXOTH 00001 /* others have execute permission */
程序中可以自由组合使用它们。
值得一提的是,目录的权限与普通文件的权限是不同的。目录的读、写、执行权限含义分别如下:
1. 读权限。读权限允许我们通过opendir()函数读取目录,进而可以通过readdir()函数获得目录内容,即目录下的文件列表。
2. 写权限。写权限代表的是可以在目录内创建、删除文件,而不是值的写目录本身。
3. 执行权限。可访问目录中的文件。
if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH))//若具有用户执行权限或组执行权限或其它用户执行权限
var = 1;
最后来看Permission属性区域的bit9-bit11,这三个bit比较特殊,代表文件的特殊属性,分别为set-user-ID位、set-group-ID位和sticky位。
stat,fstat,lstat函数的区别和相同点
函数原型:
#include<sys/types.h>
#include<sys/stat.h>
int stat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *restrict pathname, struct stat *restrict buf);
三个函数的返回值,若成功则为0,若出错则为-1。给定一个pathname,stat函数返回一个与此命名文件有关的信息结构,fstat函数获得已在描述符filedes上打开的文件的有关信息。lstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息。