Linux下檔案屬性

來源:互聯網
上載者:User

++++++++++++++++++++++++++++++++++++++++++

本文系本站原創,歡迎轉載! 轉載請註明出處:

http://blog.csdn.net/mr_raptor/article/details/6844692

++++++++++++++++++++++++++++++++++++++++++

 

   當我們用ls –l filename,這個shell命令時,會列印出,檔案的詳細資料,如:

這些檔案的詳細資料是存放在一個結構體stat裡面的,當檔案系統運行起來後,它從磁碟裡面將檔案詳細資料載入到核心空間記憶體裡,使用者空間可以通過系統調用函數stat(),fstat()來取得這個結構體的資訊。

Stat結構體:

struct stat {

              dev_t     st_dev;       /* 檔案系統裝置號 */

              ino_t     st_ino;        /* i結點號 */

              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;      /* 塊大小 */

              blkcnt_t  st_blocks;      /* 檔案所佔塊個數 */

              time_t    st_atime;      /* 上次訪問時間 */

              time_t    st_mtime;     /* 上次修改時間 */

              time_t    st_ctime;       /* 上次檔案狀態修改時間 */

};   

首先,其類型被typedef過了,因此看不出其類型來,可以通過grep命令來查看(具體操作看第一節),我們對比著檔案資訊來看,基本上這一個結構體,將整個的檔案的基本資料都包含了,通過讀取這個結構體,就能實現一個簡單的ls –l的shell命令了。

 

Stat函數

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

int stat(const char *path, struct stat *buf);

功能:查看檔案或目錄屬性

參數:path是檔案的路徑, buf就是stat結構體的指標。

傳回值:成功返回0,錯誤返回-1

現在通過這個函數我們可以取得stat結構體了,那麼通過讀結構體就能得到ls –l 一樣的效果了。

我們來看一個例子:

#include <stdio.h>

#include <sys/stat.h>

int main(int argc, char * argv[])

{

        if(argc != 2) {

                printf("Usage: <pathname>\n");

        }

        int i = 0;

        struct stat buf;

        if(stat(argv[1], &buf) < 0) {

                perror("stat");

        }

        printf("%d %d %d %d %d %d %s\n", buf.st_mode,

                buf.st_nlink, buf.st_uid, buf.st_gid,

                buf.st_size, buf.st_atime, argv[1]);

        return 0;

}

運行結果:

我們發現,除了永久連結數,檔案大小,檔案名稱一樣,其它全部都不一樣。

看來還有很多東西要處理下,我們來分析下。

首先是st_mode,它是一個int型的成員,而ls –l顯示出來是字串

st_uid, st_gid這兩個也是int型成員,而ls是使用者名稱

日期就更沒有譜了,完全不一樣。這些問題我們一一解決。

 

先來看st_mode。

S_ISUID              執行時設定-使用者- I D

S_ISGID              執行時設定-組- I D

S_ISVTX             儲存本文

 

S_IRWXU            使用者(所有者)讀、寫和執行

S_IRUSR             使用者(所有者)讀

S_IWUSR            使用者(所有者)寫

S_IXUSR             使用者(所有者)執行

 

S_IRWXG            組讀、寫和執行

S_IRGRP              組讀

S_IWGRP             組寫

S_IXGRP             組執行

 

S_IRWXO            其他讀、寫和執行

S_IROTH             其他讀

S_IWOTH            其他寫

S_IXOTH             其他執行

這些許可權在前面的open時,就有學過,它們都是用的一套宏定義。

我們用grep得到其值,再轉化成二進位分別為:

 

 

由此圖我們可以輕易的看出,其實每一個許可權位對應一個bit,當該位元為1證明擁有此許可權,為0,沒有許可權,這也能說明,當時為什麼我們用chomod 修改使用者權限時,加上777表示擁有全部許可權。

因此我們要想實現ls –l顯示檔案許可權功能,只要將其mode值和對應標誌相與即可判斷出是否具有許可權。

if( buf.st_mode & S_IRUSR )

       putchar(‘r’);

else

       putchar(‘-‘);

 

我們要注意下,如果用ls –l 目錄名,那麼許可權位第一位上顯示是d,如果是檔案其顯示的是-,這也說明,我們還要去判斷一個檔案的類型。其原理和上面檔案許可權非常相似。

 

 

因此我們也可以用類似的方法得到其類型:

       if( buf.st_mode & S_IFREG )

              putchar(‘-’);

if( buf.st_mode & S_IFDIR )

              putchar(‘d‘);

但是系統給我們已經提供了幾個宏,如下:

 

 

因此可以通過這幾個宏來代替我們的與運算:

       if(S_ISREG(buf.st_mode)

              putchar(‘-‘);

       if(S_ISDIR(buf.st_mode)

              putchar(‘d‘);

 

通過上面對st_mode成員的分析我們可以得出這樣的結論,st_mode用了16個bit來表示一個檔案的類型和許可權,這樣又節省了記憶體資源,運用位元運算還能加快其運算速度。總結一下如:

 

現在我們來看怎樣取得使用者名稱。

我們通過st_uid和st_gid可以取得主人使用者ID和組ID,我們應該還記得在剛開始學習linux基本操作和shell編程的時候,有說到,/etc/passwd裡面存放的是使用者的帳號資訊,其內容如下所示:

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

它們都用 : 分開來的,其中,第一個是使用者名稱,第三個是其對應的使用者ID,我們可以通過讀取passwd檔案內容來取出對應的使用者名稱。通過讀取/etc/group檔案來取得組名。

如果你不想去這樣寫這個函數,我們的系統調用介面也提供了這樣一個通過ID取其使用者名稱和組名的函數:

getpwuid();

getgrgid();

這兩個函數的具體的用法自己去man 吧,要不就自己通過讀passwd的方法來取。嘿嘿!

 

最後一個,顯示時間。

這個要瞭解一個Linux裡面的時間機制,系統裡面的時間是用一個很大的數來表示的,它是指的從1970年1月1日(UTC)開始到目前時間所經過的秒數,因此它是個很大的數,既然它是個秒數,那我們就能把它轉化成當前的時間,這個我們直接使用庫函數就行了。因為時間的顯示格式有很多種,因此要對轉化後的日期時間也要轉化下。

localtime()將秒數時間轉化成一個本地時區的時間結構體,再通過strftime()將時間以格式列印出日期來。這兒也自己去man 一下。

 

進階篇

我們通過上面所講的可以寫出一個最簡單的ls –l 的命令了,但是還有很多細節沒有考慮到,看下面:

上面的test.txt檔案,當它的使用者權限擁有執行許可權時,設定它的s位,那麼顯示的是小寫s,當使用者權限沒有執行許可權時,它的s位是大寫的S,因此這兒也要將我們的ls –l再進一步的修改。同樣t位也用同樣的方式顯示。

 

當我們將修改使用者主人時,可以指定一個uid,比如下面,設定檔案的主人是uid為9999的主人,但是以9999為使用者id的使用者並不存在,系統ls 會像下面這樣顯示,直接顯示出它的uid並不會顯示其使用者名稱。

 

當顯示一個檔案的詳細資料時,如果這是一個普通檔案,沒有什麼問題,但是如果當前檔案是一個連結檔案的話,系統的ls會像下面那樣顯示:

 

它列印的是(連結檔案)的詳細資料,後面跟出了連結檔案指向的檔案(Linux裡面的連結檔案和我們windows裡的捷徑很相似)這兒就要多考慮一點了,如果當前檔案是一個連結檔案,還要列印出,這個連結檔案所指向的檔案。這兒用到readlink系統調用,這個自己去man 一下,very easy。

 

       當顯示多個檔案的時候,我們注意一下系統ls –l 它總是排列的很整齊,可見,它在列印資訊的時候,取的當前列裡最長的字元的長度列印的,同時還有它的檔案名稱是按照降序排列的。

 

++++++++++++++++++++++++++++++++++++++++++

本文系本站原創,歡迎轉載! 轉載請註明出處:

http://blog.csdn.net/mr_raptor/article/details/6844692

++++++++++++++++++++++++++++++++++++++++++

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.