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 }