1. 程式人生 > >Unix/Linux程式設計-檔案和目錄(一)

Unix/Linux程式設計-檔案和目錄(一)

檔案和目錄(一)

4.1 4個stat函式

#include <sys/stat.h>

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

int  fstat(int fd, struct stat *buf);

int  lstat(const char *pathname, struct stat *buf);

int fstatat(int fd, const char *pathname,struct stat *buf, int flag);

返回值:成功返回0,錯處返回-1


(1) stat函式將於此路徑名的檔案有關資訊儲存在buf指向的緩衝區中。
(2) fstat函式獲取已開啟描述符fd上相關資訊。
(3) lstat函式返回該符號連結的有關資訊,而不是由該符號連結引用的檔案的資訊。
(4) fstatat函式為一個相對於當前開啟目錄的路徑名返回的檔案資訊。flag引數控制著是否跟隨這一個符號連結。當標誌設定為AT_SYMLINK_NOFOLLOW時,則不會跟隨符號連結。

4.2 stat結構體

struct stat {

              dev_t     st_dev;     /* ID of device containing file */

              ino_t     st_ino;     /* inode number */

              mode_t    st_mode;    /* protection */

              nlink_t   st_nlink;   /* number of hard links */

              uid_t     st_uid;     /* user ID of owner */

              gid_t     st_gid;     /* group ID of owner */

              dev_t     st_rdev;    /* device ID (if special file) */

              off_t     st_size;    /* total size, in bytes */

              blksize_t st_blksize; /* blocksize for file system I/O */

              blkcnt_t  st_blocks;  /* number of 512B blocks allocated */

              time_t    st_atime;   /* time of last access */

              time_t    st_mtime;   /* time of last modification */

              time_t    st_ctime;   /* time of last status change */

           };


4.3 檔案型別

Unix/Linux系統中,檔案有7種類型:
(1) 普通檔案(regular file)。至於普通檔案是文字檔案還是二進位制資料,對於核心而言沒有區別,關鍵在於解釋這個檔案的應用程式。
(2) 目錄檔案(directory file)。這種檔案包含了其他檔案的名字以及指向與這些檔案有關資訊的指標。
(3) 塊特殊檔案(block special file)。這種型別的檔案提供對裝置帶緩衝的訪問,每次訪問以固定長度為單位進行。
(4) 字元特殊檔案(character special file)。這種型別的檔案提供對裝置不帶緩衝的訪問,每次訪問長度可變。
(5) FIFO。用於程序間通訊,也叫管道(pipe)。
(6) 套接字(socket)。這種型別的檔案用於程序間的網路通訊。
(7) 符號連結(symbolic link)。這種型別的檔案指向另一個檔案。


檔案型別資訊儲存在stat結構的st_mode成員中,可以使用下面的巨集來確定檔案型別。

巨集

檔案型別

S_ISREG()

普通檔案

S_ISDIR()

目錄檔案

S_ISCHR()

字元特殊檔案

S_ISBLK()

塊特殊檔案

S_ISFIFO()

FIFO或管道

S_ISLNK()

符號連結

S_ISSOCK()

套接字

早期的Unix版本並不提供S_ISxxx巨集,需要將sd_mode與遮蔽字S_IFMT位與運算,然後與名為S_IFxx的常量進行比較。
#define S_ISDIR (mode)  ( ( (mode)  &  S_IFMT) ) == S_IFDIR)

4.4 檔案訪問許可權

4.4.1 檔案的9個訪問許可權位

stat結構中的成員st_mode值也包含對了檔案的訪問許可權為。每個檔案有9個訪問許可權位:

st_mode遮蔽

含義

S_IRUSR

S_IWUSR

S_IXUSR

使用者讀

使用者寫

使用者執行

S_IRGRP

S_IWGRP

S_IXGRP

組讀

組寫

組執行

S_IROTH

S_IWOTH

S_IXOTH

其他讀

其他寫

其他執行

(1) 目錄的讀許可權和執行許可權與普通檔案的意義是不同的。對於目錄,讀許可權允許我們獲取該目錄中所有檔名的列表。當一個目錄是我們要訪問檔案的路徑名的一個組成部分時,對該目錄的執行許可權使我們可通過該目錄(也就是搜尋該目錄,尋找一個特定的檔名)。
(2) 對目錄具有寫許可權和執行許可權,才能在目錄中建立一個檔案。
(3) 如果要刪除一個現有檔案,必須對包含該檔案的目錄具有寫許可權和執行許可權,但對該檔案本身則不需要讀、寫許可權。

4.4.2 核心檔案訪問許可權測試

程序每次開啟、建立或刪除一個檔案時,核心就進行檔案訪問許可權測試:
(1) 若程序的有效使用者ID是0(超級使用者),則允許訪問。
(2) 若程序的有效使用者ID等於檔案的所有者ID(也就是程序擁有此檔案),那麼如果所有者適當的訪問許可權為被設定,則允許訪問,否則拒絕訪問。
(3) 若程序的有效組ID或程序的附屬組ID之一等於檔案的組ID,那麼如果適當的訪問許可權位被設定,則允許訪問,否則拒絕訪問。
(4) 若其他使用者適當的訪問許可權為被設定,則允許訪問,否則拒絕訪問。

4.5 access和faccessat函式

當一個程序使用設定使用者ID或設定組ID功能作為另一個使用者(或組)執行時,希望按其實際使用者ID和實際組ID來測試其訪問許可權,就需要使用access或faccessat函式。

#include <unistd.h>

int  access(const char *pathname, int mode);

int faccessat(int fd, const char *pathname, int mode, int flag);

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

mode引數:

mode

說明

F_OK

測試檔案是否存在(access函式)

R_OK

測試讀許可權

W_OK

測試寫許可權

X_OK

測試執行許可權

flag引數可以用於改變faccessat函式的行為,如果flag設定為AT_EACCESS,訪問檢查用的是呼叫程序的有效使用者ID和有效組ID,而不是實際使用者ID和實際組ID。

4.6 umask函式

#include <sys/stat/h>

mode_t umask(mode_t cmask);

返回值:之前的檔案模式建立遮蔽字

umask函式為程序設定檔案模式建立遮蔽字,並返回之前的值。
cmask是4.4.1中列出的9個常量中的若干個按位或組成的。

4.7 更改檔案訪問許可權:chmod、fchmod和fchmodat

#include <sys/stat.h>

int  chmod(const char *pathname, mode_t mode);

int  fchmod(int fd, mode_t mode);

int fchmodat(int fd,const char *pathname, mode_t mode,int flag);

返回值:成功返回0,出錯返回-1

flag引數可以用於改變fchmodat的行為,當設定了AT_SYMLINK_NOFOLLOW標誌時,不會跟隨符號連結。為了改變一個檔案的許可權位,程序的有效使用者ID必須等於檔案的所有者ID,或者該程序必須具有超級使用者許可權。
引數mode所示常量的按位或:

mode

說明

S_ISUID

S_ISGID

S_ISVTX

執行時設定使用者ID

執行時設定組ID

儲存正文(粘著位)

S_IRWXU

S_IRUSR

S_IWUSR

S_IXUSR

使用者讀寫執行

使用者讀

使用者寫

使用者執行

S_IRWXG

S_IRGRP

S_IWGRP

S_IXGRP

組讀寫執行

組讀

組寫

組執行

S_IRWXO

S_IROTH

S_IWOTH

S_IXOTH

其他讀寫執行

其他讀

其他寫

其他執行

如果我們只想修改其中的某些許可權位,先呼叫stat獲得當前許可權,然後修改他。