1. 程式人生 > >linux系統呼叫函式 lstat--獲取檔案屬性

linux系統呼叫函式 lstat--獲取檔案屬性

所需標頭檔案:

#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>

函式功能:用來獲取linux作業系統下檔案的屬性。
函式原型: int stat(const char *pathname,struct stat *buf);

引數:第一個引數為傳入引數,pathname為檔案的絕對路徑相對路徑。第二引數為傳出引數,一個struct stat型別的結構體指標。傳出引數可以採用下邊兩種方法,定義結構體變數struct stat st,或定義結構體指標變數strut stat *st = &st

(注意這裡一定要進行初始化,說明其為一塊有效的記憶體空間),相對而言,使用結構體變數更為方便。

注意,在linux作業系統下,一切皆檔案。檔案共有七種型別,分別是普通檔案、目錄檔案、管道檔案、可執行檔案、壓縮檔案、裝置檔案(字元、管道和塊)和其他檔案。

下面介紹一下struct stat結構體:

這裡寫圖片描述

struct stat {
    dev_t     st_dev;      檔案的裝置編號
    ino_t     st_ino;      節點
    mode_t    st_mode;     檔案的型別和許可權
    nlink_t   st_nlink;    連到該檔案的硬連結數目,剛建立的檔案值為1
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; 最後一次改變時間(指屬性) };

下面舉例使用stat函式獲取檔案的屬性:
在linux的shell直譯器中,輸入這樣的命令stat + 檔名即可獲取檔案的屬性。如:
這裡寫圖片描述
那麼如何在函式中獲取檔案屬性並將其打印出來呢?下面應用stat函式獲取main.c檔案的屬性。

#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>

int main()
{
    struct stat st;//定義結構體變數,儲存所獲取的檔案屬性
    int res = stat("/home/lsc/Desktop/linux/k0512/test/main.c",&st);
    if(res == -1)//獲取檔案屬性失敗,errno設定為合適的值
    {
        perror("stat fail");
        exit(1);
    }
    printf("大小:%d    ",st.st_size);
    printf("裝置:%d    ",st.st_dev);
    printf("塊:%d   ",st_st_blocks);
    printf("Inode:%d   ",st.st_ino);
    printf("硬連結:%d   ",st.st_nlink);
    printf("uid:%d   ",st.st_uid);
    printf("gid:%   ",st.st_gid);
    return 0;
}

執行結果:
和我們用stat + 檔名命令獲取到檔案的屬性資訊是一致的。
這裡寫圖片描述

大家可能注意到,在程式碼中併為涉及輸出st_mode屬性相關的資訊。
重點:下面著重深入的研究一下st_mode這屬性,可以通過它來獲取檔案的檔案型別以及許可權。

mode_t st_mode是一個16位的short型別,對應16個標誌位,其組成如下:

這裡寫圖片描述
而其,通常情況下特殊許可權位不使用。
那麼如何取出對應的位置的位獲取相關的資訊呢,Linux系統呼叫給我們提供了一系列的巨集,可以檢視man文件 man 2 stat

S_IFMT     0170000   //掩碼,過濾st_mode中除檔案型別以外的資訊
S_IFSOCK   0140000   //套接字
S_IFLNK    0120000   //符號連結(軟連結)
S_IFREG    0100000   //普通檔案
S_IFBLK    0060000   //塊裝置
S_IFDIR    0040000   //目錄檔案
S_IFCHR    0020000   //字元裝置
S_IFIFO    0010000   //管道
S_ISUID    0004000   //設定使用者ID
S_ISGID    0002000   //設定組ID
S_ISVTX    0001000   //粘住位
S_IRWXU    00700     //掩碼,過濾st_mode除檔案所有者許可權以外的資訊
S_IRUSR    00400     //使用者讀許可權
S_IWUSR    00200     //使用者寫許可權
S_IXUSR    00100     //使用者執行許可權
S_IRWXG    00070     //掩碼,過濾st_mode除所屬組許可權以外的資訊
S_IRGRP    00040     //讀許可權
S_IWGRP    00020     //寫許可權
S_IXGRP    00010     //執行許可權
S_IRWXO    00007     //掩碼,過濾st_mode除其他人許可權以外的資訊
S_IROTH    00004     //讀許可權
S_IWOTH    00002     //寫許可權
S_IXOTH    00001     //執行許可權

下面舉一個簡單例子,驗證一個檔案是否為普通檔案。
在當前目錄下有一個普通檔案:
這裡寫圖片描述

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#incude<sys/stat.h>
#include<sys/types.h>

int main()
{
    struct stat st;
    int res = stat("./test.c",&st);
    if(-1 == res)
    {
        perror("stat fail");
        exit(1);
    }
    if((st.st_mode & S_IFMT) == S_IFREG)
    {
        printf("regular file\n");
    }
    return 0;
}

這裡寫圖片描述

相信完全理解了系統呼叫函式stat之後,實現一個ls -l的命令也會變得簡單,大家可以試試。