在Linux中,可以利用stat()函数来获取一个文件的状态
#include
#include
int stat(const char *file_name, struct stat *buf);
这个函数执行成功返回0,失败返回-1。取得的文件状态存放在buf指针指向的struct stat结构提中, struct stat的定义如下:
struct stat
{
dev_t st_dev;/* ID of device containing file -文件所在设备的ID*/
ino_t st_ino;/* inode number -inode节点号*/
mode_t st_mode;/* 文件的类型和存取的权限*/
nlink_t st_nlink;/* number of hard links -链向此文件的连接数(硬连接)*/
uid_t st_uid;/* user ID of owner -user id*/
gid_t st_gid;/* group ID of owner - group id*/
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 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 - */
};
其中, st_mode这个变量用来判断文件类型。
st_mode是用特征位来表示文件类型的,特征位的定义如下:
S_IFMT 0170000 文件类型的位遮罩
S_IFSOCK 0140000 socket
S_IFLNK 0120000 符号链接(symbolic link)
S_IFREG 0100000 一般文件
S_IFBLK 0060000 区块装置(block device)
S_IFDIR 0040000 目录
S_IFCHR 0020000 字符装置(character device)
S_IFIFO 0010000 先进先出(fifo)
S_ISUID 0004000 文件的(set user-id on execution)位
S_ISGID 0002000 文件的(set group-id on execution)位
S_ISVTX 0001000 文件的sticky位
S_IRWXU 00700 文件所有者的遮罩值(即所有权限值)
S_IRUSR 00400 文件所有者具可读取权限
S_IWUSR 00200 文件所有者具可写入权限
S_IXUSR 00100 文件所有者具可执行权限
S_IRWXG 00070 用户组的遮罩值(即所有权限值)
S_IRGRP 00040 用户组具可读取权限
S_IWGRP 00020 用户组具可写入权限
S_IXGRP 00010 用户组具可执行权限
S_IRWXO 00007 其他用户的遮罩值(即所有权限值)
S_IROTH 00004 其他用户具可读取权限
S_IWOTH 00002 其他用户具可写入权限
S_IXOTH 00001 其他用户具可执行权限
摘自《Linux C 函数库参考手册》
判断文件类型时,用对文件的st_mode的值与上面给出的值相与,再比较。比如:
#include#include#includeint main()
{
int abc;
struct stat buf;
stat("/home", &buf);
abc = buf.st_mode & S_IFDIR;//与对应的标志位相与
if(abc == S_IFDIR) //结果与标志位比较
printf("It's a directory.\n");
return 0;
}
运行结果:
It's a directory.
其实还有一个简单的方法,文件类型在POSIX中定义了检查这些类型的宏定义:
S_ISLINGK(st_mode) 判断是否位符号链接
S_ISREG(st_mode) 是否为一般文件
S_ISDIR(st_mode) 是否为目录
S_ISCHR(st_mode) 是否位字符装置文件
S_ISBLK(s3e) 是否先进先出
S_ISSOCK(st_mode) 是否为socket
可以根据这些函数的返回值判断,如果是,则返回1。(我试了一下,好像是这样的)
cuole!!!!!!
在中定义的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 file system 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 */
};
本文着眼于st_mode成员,该成员描述了文件的类型和权限两个属性。
st_mode是个32位的整型变量,不过现在的linux操作系统只用了低16位(估计是鉴于以后拓展的考虑)。
===============================================================================================================
先看File type属性区域,位于bit12 ~ bit15.
在现代linux操作系统上文件类型共分为7种,分别是:
普通文件(regular file)
目录(directory)
字符设备(character device)
块设备(block device)
管道(FIFO)
符号链接文件(symbolic link)
套接口文件(socket)
所以File type属性只需3bit就够了,估计也是考虑到了以后的扩展问题。
在中有如下定义:
#define S_IFMT 00170000
#define S_IFSOCK 0140000
#define S_IFLNK 0120000
#define S_IFREG 0100000
#define S_IFBLK 0060000
#define S_IFDIR 0040000
#define S_IFCHR 0020000
#define S_IFIFO 0010000
#define S_ISUID 0004000
#define S_ISGID 0002000
#define S_ISVTX 0001000
#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_IFMT是一个掩码,它的值是017000(注意这里用的是八进制), 可以用来过滤出前四位表示的文件类型。
其后的连续七个分别对应套接口文件、符号链接文件、普通文件、块设备、目录、字符设备、管道,它们分别对应一个不同的值。
现在假设我们要判断一个文件是不是目录,我们怎么做呢?
很简单,首先通过掩码S_IFMT把其他无关的部分置0,再与表示目录的数值比较,从而判断这是否是一个目录,下面的代码:
if ((info.st_mode & S_IFMT) == S_IFDIR)
printf("this is a directory");
为了简便操作,中提供了宏来代替上述代码,所以如果需要判断文件是不是目录就可以这样:
if (S_ISDIR(info.st_mode))
printf("this is a directory");
===============================================================================================================
接着来看Permission属性区域的bit0~bit8,也即st_mode字段的最低9位,代表文件的许可权限,它标识了文件所有者(owner)、组用户(group)、其他用户(other)的读(r)、写(w)、执行(x)权限。
在有如下定义:
#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)执行权限。可访问目录中的文件。
===============================================================================================================
最后来看Permission属性区域的bit9 ~ bit11,这三个bit比较特殊,代表文件的特殊属性,分别为set-user-ID位、set-group-ID位和sticky位,下面一一介绍每个位的含义。
网友评论