1,stuct stat
一个文件的常用信息,包括:权限、文件类型、文件所有者、文件大小、文件改动时间等信息都存储在一个结构体中,即struct stat。
这个结构体定义在stat.h头文件中。
基本形式如下:
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};
系统中的具体实现可能与之略有出入。比如我的电脑上,其实际的实现为:
struct stat {
unsigned long st_dev; /* Device. */
unsigned long st_ino; /* File serial number. */
unsigned int st_mode; /* File mode. */
unsigned int st_nlink; /* Link count. */
unsigned int st_uid; /* User ID of the file's owner. */
unsigned int st_gid; /* Group ID of the file's group. */
unsigned long st_rdev; /* Device number, if device. */
unsigned long __pad1;
long st_size; /* Size of file, in bytes. */
int st_blksize; /* Optimal block size for I/O. */
int __pad2;
long st_blocks; /* Number 512-byte blocks allocated. */
long st_atime; /* Time of last access. */
unsigned long st_atime_nsec;
long st_mtime; /* Time of last modification. */
unsigned long st_mtime_nsec;
long st_ctime; /* Time of last status change. */
unsigned long st_ctime_nsec;
unsigned int __unused4;
unsigned int __unused5;
};
2,获取该结构体
#include<sys/stat.h>
int stat(const char *path, struct stat *struct_stat);
int fstat(int fd, struct stat *buf);
int lstat(const char *path,struct stat *struct_stat);
int fstat(int fdp, struct stat *struct_stat); //通过文件描述符获取文件对应的属性。fdp为文件描述符
这4个函数可用于获取该结构体。stat和lstat的区别在于对符号链接的处理。lstat返回该符号链接的有关信息,而不是该符号链接所引用的文件的信息。
以上4个函数,执行成功时返回0,执行失败时返回-1.
具体的使用方法如下:
if((lstat(path, &file_info)) < 0)
{
printf("lstat error!\n");
continue;
}
3,文件类型
Linux上常用的文件类型包括:
- 普通文件
- 目录文件
- 块特殊文件(提供对设备带缓冲的访问)
- 字符特殊文件(提供对设备不带缓冲的访问)
- FIFO(用于进程间通信,又称为管道)
- 套接字(用于进程间网络通信)
- 符号链接
可用现成的宏定义判断文件类型:
S_ISREG() 普通文件
S_ISDIR() 目录文件
S_ISCHR() 字符特殊文件
S_ISBLK() 块特殊文件
S_ISFIFO() 管道
S_ISLNK() 符号链接
S_ISSOCK() 套接字
其在头文件中的具体实现如下:
#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)
IMFT即为 0XF000,13到16位全1
具体的使用方法如下:
if (S_ISREG(file_info.st_mode))
ptr = "regular";//普通文件
4,示例
int main(int argc, char* argv[])
{
// 4.3 lstat 通过st_mode获取文件类型
int i = 0; //输入的文件名编号
struct stat file_info;
char *ptr;
printf("S_IFMT = %d, S_IFREG = %d\n", S_IFMT, S_IFREG);
printf("argc = %d\n", argc);
for (i = 1; i < argc; i++)
{
printf("%s: ",argv[i]);
if((lstat(argv[i], &file_info)) < 0)
{
printf("lstat error!\n");
continue;
}
printf("st_mtime = %ld\n",file_info.st_mtime );
if (S_ISREG(file_info.st_mode))
ptr = "regular";//普通文件
else if(S_ISDIR(file_info.st_mode))
ptr = "direction";//目录文件
else if(S_ISCHR(file_info.st_mode))
ptr = "character special";//字符特殊文件
else if(S_ISBLK(file_info.st_mode))
ptr = "block special"; //块特殊文件
else if(S_ISFIFO(file_info.st_mode))
ptr = "FIFO";
else if(S_ISLNK(file_info.st_mode))
ptr = "link";
else if(S_ISSOCK(file_info.st_mode))
ptr = "sock";
else
ptr = "unknown mode";
printf("%s file\n", ptr);
}
}