stat,fstate,lstat函数
首先看一下函数定义
#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);
下面来看一下GNU C中的定义
To examine the attributes of files, use the functions stat, fstat and lstat. They return
the attribute information in a struct stat object. All three functions are declared in the
header file ‘sys/stat.h’.
可知stat, fstat and lstat是用来检查文件属性的。他们将文件属性信息通过a struct stat object 返回。
int stat (const char *filename, struct stat *buf) [Function]
The stat function returns information about the attributes of the file named by
filename in the structure pointed to by buf.
If filename is the name of a symbolic link, the attributes you get describe the file
that the link points to. If the link points to a nonexistent file name, then stat fails
reporting a nonexistent file.
The return value is 0 if the operation is successful, or -1 on failure. In addition to the
usual file name errors (see Section 11.2.3 [File Name Errors], page 224, the following
errno error conditions are defined for this function:
ENOENT The file named by filename doesn’t exist.
When the sources are compiled with _FILE_OFFSET_BITS == 64 this function is in fact
stat64 since the LFS interface transparently replaces the normal implementation.
int fstat (int filedes, struct stat *buf) [Function]
The fstat function is like stat, except that it takes an open file descriptor as an
argument instead of a file name. See Chapter 13 [Low-Level Input/Output], page 296.
Like stat, fstat returns 0 on success and -1 on failure. The following errno error
conditions are defined for fstat:
EBADF The filedes argument is not a valid file descriptor.
When the sources are compiled with _FILE_OFFSET_BITS == 64 this function is in fact
fstat64 since the LFS interface transparently replaces the normal implementation.
int lstat (const char *filename, struct stat *buf) [Function]
The lstat function is like stat, except that it does not follow symbolic links. If
filename is the name of a symbolic link, lstat returns information about the link
itself; otherwise lstat works like stat. See Section 14.5 [Symbolic Links], page 357.
When the sources are compiled with _FILE_OFFSET_BITS == 64 this function is in fact
lstat64 since the LFS interface transparently replaces the normal implementation.
一旦给出pathname,stat函数就返回与此命名有关的信息结构,fstat函数获取已在描述符filedes上打开文件的有关信息。lstat函数类似于stat,但是当命名文件时一个符号链接,lstat返回该符号链接的有关信息。而不是有该符号引用文的信息。
第二个参数是buf,指针。指向我们必须提供的结构。
下面给出strut 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 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 */
- };
下面一个 对strut stat的应用是转自互联网。
判断文件(文件夹)是否可读的函数:
函数的过程很简单,判断逻辑在注释中也写的很清楚了,需要包含的头文件:
#include <sys/unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
利用这个思路,判断可写,判断可运行的函数就很容易写出了。
下面是判断文件(文件夹)是否可写的函数:
下面是判断文件(文件夹)是否可运行的函数:
对于普通文件来说,获取文件占用的大小很简单,只需要返回结构体stat的st_sizee即可。但是对于文件夹来说,结构体stat的st_size表明的是文件夹本身占用的空间大小(在Linux文件体系中,对于文件夹来说是需要空间来存储自身文件夹下的文件或文件夹的inode号的),与我们普遍意义上理解的文件夹应该返回的是其包含文件或文件夹的总容量不同,因此需要设计一个函数来获得文件夹下所有文件(文件夹)的总容量:
其实更加通用的遍历目录函数可以这样设计:用注册回调函数的方法来实现,这个回调函数的参数就是每个遍历项的路径(最好是绝对路径),那么以后遍历目录就不需要改变了 只需要在应用中注册不同的回调函数就可以了。实现如下:
这种实现方式的优势是利用回调函数,遍历文件夹的操作可以复用,缺点是如果需要统计每次回调函数的结果就需要额外的一个全局参数(当然可以用命名空间的方式局部化。。。)。利用这种方式,还能方便的实现出统计文件夹下各种文件类型的数量,属于某个用户ID文件的数量等等(改改两个回调函数就行了)。
在项目中,我们经常会需要获得文件(文件夹)的最后访问(读)时间、最后修改(写)时间、创建时间或最后更改(属性更改)时间这三种时间,在Linux中,触发这三种时间改变的条件分别是:
最后访问(读)时间:文件(文件夹)最后一次被存取或执行的时间;
最后修改(写)时间:文件(文件夹)最后一次被修改的时间,这里指的修改是内容上的;
创建时间或最后更改(属性更改)时间:文件(文件夹)最后一次被更改的时间,这里指的修改是属性上的,如所有者、权限等;
对应到结构体stat上就是:
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 */
值得一提的是,以上三种时间在Linux中是用UTC表示的,单位是秒,举个例子:1285328411表示的是从1970年1月1日开始所经过的秒数,值得注意的是这里的时间是UTC时间。
这里仅用最后访问(读)时间为例:
另外两种时间的获取方式,就当作小练习吧。
最后来谈谈如何根据st_mode来判断文件(文件夹)的类型,这里可以利用库本身就定义好的一些宏:
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) /**文件夹的判断*/
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) /**管道文件的判断*/
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) /**字符设备的判断*/
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) /**块设备的判断*/
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) /**普通文件的判断*/
实例如下:
当然在项目中一般是不用硬编码的,可以定义相关的enum。