stat函数(stat、fstat、lstat)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>???? //需包含頭文件
有如下三個函數的函數原型:
int stat(const char *path, struct stat *buf);
第一個形參:指出文件(文件路徑); 第二個形參:出參數(函數對該參數操作,然后傳出)。
int fstat(int fd, struct stat *buf);
fstat函數與stat函數的功能一樣,只是第一個形參是文件描述符。
int lstat(const char *path, struct stat *buf);
lstat函數的形參跟stat函數的形參一樣。其功能也跟stat函數功能一樣,僅有一點不同:stat函數是穿透(追蹤)函數,即對軟鏈接文件進行操作時,操作的是鏈接到的那一個文件,不是軟鏈接文件本身;而lstat函數是不穿透(不追蹤)函數,對軟鏈接文件進行操作時,操作的是軟鏈接文件本身。
以上三個函數:成功返回0,失敗返回-1,并且將詳細錯誤信息賦值給errno全局變量。
其它Linux系統函數類似,帶l表示不追蹤,不帶l表示追蹤(穿透)。如:ls –l命令查看的文件屬性,是不追蹤(不穿透)的;rm刪除文件時,是不追蹤的;Vi和Vim是穿透的;對于穿透的命令,是無法判斷文件是不是軟鏈接文件,比如ls –l命令,其是不穿透的,因此可以判斷是否是軟鏈接文件;如果是用stat函數實現的ls –l命令,則是穿透的,對于查看原文件和鏈接文件的屬性是一樣的,無法區別兩者,因此可以考慮用lstat函數來實現ls –l命令的功能。
注意:創建軟鏈接最好用絕對路徑? ln –s 原文件 軟鏈接文件(采用絕對路徑)
stat、lstat和fstat函數中 struct stat類型的說明:
struct stat {
?????????????? dev_t???? st_dev;???? /* 文件的設備編號 */
????????????? ?ino_t???? st_ino;???? /* 索引結點編號 */
?????????????? mode_t??? st_mode;??? /* 文件類型和權限*/
?????????????? nlink_t?? st_nlink;?? /*硬鏈接數 */
?????????????? uid_t???? st_uid;???? /*用戶ID*/
?????????????? gid_t???? st_gid;???? /* 組ID*/
????? ?????????dev_t???? st_rdev;??? /* 設備類型(若此文件為設備文件,則為設備編號*/
???????????? ??off_t??? ??st_size;??? /* 文件大小*/
?????????????? blksize_t ??st_blksize; /*文件系統的I/O緩沖區大小*/
???????????? ??blkcnt_t ??st_blocks;? /* 塊數 */
?????????????? time_t??? st_atime;?? /* 訪問時間 */
?????????????? time_t??? st_mtime;?? /* 修改時間 */
?????????????? time_t??? st_ctime;?? /* 更改時間 */
???????? };? //標紅為重點內容
struct stat結構體位于inode(索引結點)中,但是其內部不包含文件名。文件名位于位于文件的目錄項dentry中(即簡化的FCB),其包含文件名和inode編號。通過denty的inode編號可以找到inode,進一步找到文件本身。硬鏈接就是denty(目錄項)。
上述結構體中,對st_mode成員做一個詳細的介紹:
mode_t??? st_mode;??? /* 文件類型和權限*/
st_mode變量(mode_t類型):該變量占 2byte共16位,為16位的整型值。用于儲存文件類型和權限。 如下圖所示:
每一位均為二進制數。r代表4,即100;w代表2,即010;x代表1,即001。由于總共16位二進制數,因此需要6位8進制數來進行表示,其中8進制數以0開頭,共7位。
其他人權限(0~2位)。讀權限:0000004,在所給函數頭文件中進行了宏定義為:S_IROTH;寫:0000002,S_IWOTH;執行:0000001,S_IXOTH。 掩碼為:0000007,S_IRWXO ?掩碼的作用:st_mode & 掩碼 就可以過濾st_mode中除其他人權限以外的信息,所得結果直接是其他人的權限信息,下面原理相同。
所屬組權限(3~5位)。讀權限:0000040, S_IRGRP;寫:0000020,S_IWGRP;執行:0000010,S_IXGRP。 掩碼為:0000070,S_IRWXG。
所屬主權限(6~8位)。讀權限:0000400, S_IRUSR;寫:0000200,S_IWUSR;執行:0000100,S_IXUSR。 掩碼為:0000700,S_IRWXU。
特殊權限位(9~11位)。SUID:0004000, S_ISUID;SGID:0002000,S_ISGID;SBIT:0001000,S_ISVTX。 //特殊權限位很少用
文件類型(12~15位,共7種類型文件)。套接字(socket)文件s:0140000,S_IFSOCK;鏈接文件(軟鏈接)l:0120000,S_IFLNK;普通文件-:0100000,S_IFREG;塊設備文件b:0060000,S_IFBLK;目錄文件d:0040000,S_IFDIR;字符設備文件c:0020000,S_IFCHR;管道文件p:0010000,S_IFIFO。? ??掩碼:0170000? 作用一樣,st_mode & 掩碼 的結果與七種類型的宏相比較,就可以判斷是哪一種文件。
強調一下特殊權限位SBIT(粘滯位)的功能:1.對目錄設置粘滯位,則該目錄內的文件只能被文件所有者、超級用戶和目錄所有者這三類用戶刪除,其他用戶都沒有刪除的權限;2.對文件設置了粘滯位,那么在內存資源十分緊張的情況下,也不會把該文件放回到磁盤上。如磁盤的對換區SWAP,當內存緊張,優先級別低的進程會被暫時放回到對換區中,但是一旦設置了粘滯位,則不會放回磁盤,依然處于內存。
下面是說明stat函數的使用的代碼:
//運用stat函數實現查看文件大小屬性的功能
[root@localhost work]# vim statuse.c
#include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h>int main( int argc,char *argv[ ] ) //命令行參數 {if( argc < 2 )printf("./statuse filename1 filename2 ...\n");struct stat zsx;int ret;int i=1;for( i=1;i<argc;i++ ){ret = stat( argv[i],&zsx); //stat函數獲取文件的屬性,穿透的if( ret == -1 ){perror("stat filename");exit(1);}int size = (int)zsx.st_size; //注意,必須強制轉換,后者變量是off_t類型printf("%s %d\n",argv[i],size);}return 0; }[root@localhost work]# gcc -pipe -ggdb3 -pedantic -Wall statuse.c -o statuse
[root@localhost work]# ls
english.txt? ls-l.c? stat.c? statuse? statuse.c
[root@localhost work]# ./statuse english.txt ls-l.c stat.c statuse statuse.c
english.txt????? 109055
ls-l.c?????? 2204
stat.c?????? 416
statuse???? 57468
statuse.c? 535
?[root@localhost work]# ll english.txt
-rwxrwxrwx. 1 root root 109055 Mar 19 10:30 english.txt
//運用stat函數實現ls –l 命令的功能
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <time.h> #include <pwd.h> #include <grp.h>int main(int argc, char* argv[]) {if(argc < 2)int main(int argc, char* argv[]) {if(argc < 2){printf("./a.out filename\n");exit(1);}struct stat st;int ret = stat(argv[1], &st);if(ret == -1){perror("stat");exit(1);}// 存儲文件類型和訪問權限char perms[11] = {0};// 判斷文件類型switch(st.st_mode & S_IFMT){case S_IFLNK:perms[0] = 'l';break;case S_IFDIR:perms[0] = 'd';break;case S_IFREG:perms[0] = '-';break;case S_IFBLK:perms[0] = 'b';break;case S_IFCHR:perms[0] = 'c';break;case S_IFSOCK:perms[0] = 's';break;case S_IFIFO:perms[0] = 'p';break;default:perms[0] = '?';break;}// 判斷文件的訪問權限// 文件所有者perms[1] = (st.st_mode & S_IRUSR) ? 'r' : '-';perms[2] = (st.st_mode & S_IWUSR) ? 'w' : '-';perms[3] = (st.st_mode & S_IXUSR) ? 'x' : '-';// 文件所屬組perms[4] = (st.st_mode & S_IRGRP) ? 'r' : '-';perms[5] = (st.st_mode & S_IWGRP) ? 'w' : '-';perms[6] = (st.st_mode & S_IXGRP) ? 'x' : '-';// 其他人perms[7] = (st.st_mode & S_IROTH) ? 'r' : '-';perms[8] = (st.st_mode & S_IWOTH) ? 'w' : '-';perms[9] = (st.st_mode & S_IXOTH) ? 'x' : '-';// 硬鏈接計數int linkNum = st.st_nlink;// 文件所有者char* fileUser = getpwuid(st.st_uid)->pw_name;// 文件所屬組char* fileGrp = getgrgid(st.st_gid)->gr_name;// 文件大小int fileSize = (int)st.st_size;// 修改時間char* time = ctime(&st.st_mtime);char mtime[512] = {0};strncpy(mtime, time, strlen(time)-1);char buf[1024];sprintf(buf, "%s %d %s %s %d %s %s", perms, linkNum, fileUser, fileGrp, fileSize, mtime, argv[1]);printf("%s\n", buf);return 0; }?
總結
以上是生活随笔為你收集整理的stat函数(stat、fstat、lstat)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成都欢乐谷雨天开放吗
- 下一篇: 地下城堡3魂之诗手游萨古罗斯怎么打