stat(),lstat(),fstat() 获取文件/目录的相关信息
stat 的使用
Linux有个命令,ls -l,效果如下:
这个命令能显示文件的类型、操作权限、硬链接数量、属主、所属组、大小、修改时间、文件名。它是怎么获得这些信息的呢,请看下面的讲解。
stat 的基本使用
stat:返回一个与此命
需要包含的头文件: <sys/types.h>,<sys/stat.h>,<unistd.h>
函数原型:
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
参数:
对于stat() & lstat()来说path,是要查看属性的文件或目录的全路径名称
对于fstat,fd 是要查看属性文件的文件描述符
buf:指向用于存放文件属性的结构体,函数成功调用后,buf各个字段存放各个属性。
返回值 成:
功返回0; 错误返回 -1;
给定一个文件:
stat 函数获得一个与此命名文件有关的信息(到一个struct stat 类型的buf中) 。
fstat 函数获得文件描述符 fd 打开文件的相关信息(到一个struct stat 类型的buf中) 。
lstat 函数类似于 stat,但是当命名文件是一个符号连接时, lstat 获取该符号连接的有关信息,而不是由该符号连接引用文件的信息。
struct stat在系统头文件<stat.h>中,具体定义如下:
1 struct stat
2 {
3 dev_t st_dev; /* ID of device containing file -文件所在设备的ID*/
4 ino_t st_ino; /* inode number -inode节点号*/
5 mode_t st_mode; /* Protection -文件的类型和存取的权限*/
6 nlink_t st_nlink; /* number of hard links -链向此文件的连接数(硬连接)*/
7 uid_t st_uid; /* user ID of owner -user id*/
8 gid_t st_gid; /* group ID of owner - group id*/
9 dev_t st_rdev; /* device ID (if special file) -设备号,针对设备文件*/
10 off_t st_size; /* total size, in bytes -文件大小,字节为单位*/
11 blksize_t st_blksize; /* blocksize for filesystem I/O -系统块的大小*/ 12 blkcnt_t st_blocks; /* number of blocks allocated -文件所占块数*/
13 time_t st_atime; /* time of last access -最近存取时间*/
14 time_t st_mtime; /* time of last modification -最近修改时间*/
15 time_t st_ctime; /* time of last status change - */
16 };
st_mode是用特征位来表示文件类型以及操作权限的,特征位的定义如下:
1 S_IFMT 0170000 文件类型的位遮罩
2 S_IFSOCK 0140000 socket
3 S_IFLNK 0120000 符号链接(symbolic link)
4 S_IFREG 0100000 一般文件
5 S_IFBLK 0060000 区块装置(block device)
6 S_IFDIR 0040000 目录
7 S_IFCHR 0020000 字符装置(character device)
8 S_IFIFO 0010000 先进先出(fifo)
9 S_ISUID 0004000 文件的(set user-id on execution)位
10 S_ISGID 0002000 文件的(set group-id on execution)位
11 S_ISVTX 0001000 文件的sticky位
12 S_IRWXU 00700 文件所有者的遮罩值(即所有权限值)
13 S_IRUSR 00400 文件所有者具可读取权限
14 S_IWUSR 00200 文件所有者具可写入权限
15 S_IXUSR 00100 文件所有者具可执行权限
16 S_IRWXG 00070 用户组的遮罩值(即所有权限值)
17 S_IRGRP 00040 用户组具可读取权限
18 S_IWGRP 00020 用户组具可写入权限
19 S_IXGRP 00010 用户组具可执行权限
20 S_IRWXO 00007 其他用户的遮罩值(即所有权限值)
21 S_IROTH 00004 其他用户具可读取权限
22 S_IWOTH 00002 其他用户具可写入权限
23 S_IXOTH 00001 其他用户具可执行权限
POSIX定义了下面几种通过st_mode判断文件类型的宏:
1 The following POSIX macros are defined to check the file type using the st_mode field:
2 S_ISREG(m) /* is it a regular file? -普通文件 */
3 S_ISDIR(m) /* directory? -目录文件? */
4 S_ISCHR(m) /* character device? -字符设备文件? */
5 S_ISBLK(m) /* block device? -块设备文件? */
6 S_ISFIFO(m) /* FIFO (named pipe)? -管道文件? */
7 S_ISLNK(m) /* symbolic link? (Not in POSIX.1-1996.) -符号链接? */
8 S_ISSOCK(m) /* socket? (Not in POSIX.1-1996.) -套接口? */
1. stat()获取文件相关信息
1 #include <stdio.h> 2 #include <stat.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <unistd.h> 6 7 int main(int argc, char **argv) 8 { 9 struct stat buf; 10 if(argc != 2) { 11 printf("Usage: stat "); 12 exit(-1); 13 } 14 if(stat(argv[1], &buf) != 0) { 15 printf("stat error."); 16 exit(-1); 17 } 18 printf("#i-node: %ld\n", buf.st_ino); 19 printf("#link: %d\n", buf.st_nlink); 20 printf("UID: %d\n", buf.st_uid); 21 printf("GID: %d\n", buf.st_gid); 22 printf("Size %ld\n", buf.st_size); 23 exit(0); 24 }
2. 实现Linux ls命令
1 #include <stdio.h> 2 #include <dirent.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <unistd.h> 6 #include <pwd.h> 7 #include <grp.h> 8 #include <time.h> 9 #include <string.h> 10 11 char gettype(mode_t mod) 12 { 13 /* 14 if( S_ISREG(mod) ) return '-'; 15 if( S_ISDIR(mod) ) return 'd'; 16 if( S_ISCHR(mod) ) return 'c'; 17 if( S_ISBLK(mod) ) return 'b'; 18 if( S_ISLNK(mod) ) return 'l'; 19 if( S_ISSOCK(mod) ) return 's'; 20 if( S_ISFIFO(mod) ) return 'p'; 21 */ 22 switch(mod & S_IFMT) 23 { 24 case S_IFSOCK: return 's'; 25 case S_IFREG: return '-'; 26 case S_IFCHR: return 'c'; 27 case S_IFBLK: return 'b'; 28 case S_IFLNK: return 'l'; 29 case S_IFIFO: return 'p'; 30 case S_IFDIR: return 'd'; 31 } 32 } 33 34 char *getperm(mode_t mod) 35 { 36 static char buf[10]; 37 38 int i = 9; 39 while(i--) 40 { 41 if(mod & 1<<i) 42 { 43 switch((8-i)%3) 44 { 45 case 0: buf[8-i] = 'r'; break;// r/w/x; 46 case 1: buf[8-i] = 'w'; break;// r/w/x; 47 case 2: buf[8-i] = 'x'; break;// r/w/x; 48 } 49 } 50 else 51 buf[8-i] = '-'; 52 } 53 54 return buf; 55 } 56 57 char *getttt(time_t *t) 58 { 59 static char buf[50]; 60 61 strncpy(buf, ctime(t), 24); 62 63 return buf; 64 } 65 66 int main(int argc, char **argv) 67 { 68 DIR *dp = opendir((2==argc)?argv[1]:"."); 69 70 if(2 == argc) 71 chdir(argv[1]); 72 73 struct dirent *p; 74 75 struct stat s; 76 while( p = readdir(dp) ) 77 { 78 if(-1 == stat(p->d_name, &s) ) 79 { 80 perror("stat"); 81 return -1; 82 } 83 84 printf( "%c%s %5d %s %s %10ld %s\033[1;31;40m %s \033[0m\n", 85 gettype(s.st_mode), 86 getperm(s.st_mode), 87 s.st_nlink, 88 getpwuid(s.st_uid)->pw_name, 89 getgrgid(s.st_gid)->gr_name, 90 s.st_size, 91 getttt(&s.st_mtime), 92 p->d_name ); 93 } 94 }