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;
}
 
————————————————
版權聲明:本文爲CSDN博主「luciusvorenus」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_33883085/article/details/88695946

發佈了4 篇原創文章 · 獲贊 167 · 訪問量 60萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章