天天看點

檔案和目錄(一)--unix環境進階程式設計

     普通檔案和目錄linux中最多的兩類檔案,linux中一共有七種類型的檔案,如下:

1.普通檔案
2.目錄
3.字元特殊裝置
4.塊特殊裝置
5.FIFO,又叫命名管道
6.Socket,即套接字
7.符号連結
           

擷取一個檔案的詳細資訊可以使用stat函數組,stat函數組包括三個函數,它們的函數原型如下:

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

這三個函數的功能大同小異,都是将一個檔案的相關資訊存入到一個stat結構體變量中,也就是提供的第二個參數。stat函數的第一個參數為檔案的路徑名字,fstat的第一個參數為打開檔案的檔案描述符,lstat函數與前面的兩個函數一個最大的不同是它并不跟随符号連結,即獲得的不是符号連結指向的檔案的資訊,而是符号連結本身的資訊。stat這個結構體中的成員如下:

struct stat
{
  mode_t st_mode; //檔案的類型和權限
  ino_t st_ino; //inode的節點号
  dev_t st_dev; //裝置号
  dev_t st_rdev; //特殊裝置号
  nlink_t st_nlink; //連接配接數
  uid_t st_uid; //檔案所有者
  gid_t st_gid; //檔案所屬組
  off_t st_st_size; //檔案的位元組數
  time_t st_atime; //檔案的最後存取時間
  time_t mtime; //檔案的最後修改時間
  time_t ctime; //檔案權限的最後修改時間
  long st_blksize; //最佳的IO塊長度
  long st_blocks; //512位元組的塊數
};
           

可以使用stat結構體中的成員的st_mode來判斷檔案的類型,者需要使用到<sys/stat.h>頭檔案中提供的一系列宏:

S_ISREG();判斷普通檔案
S_ISDIR(); 判斷目錄
S_ISCHR(); 判斷特殊字元裝置
S_ISBLK(); 判斷塊特殊裝置
S_ISFIFO(); 判斷FIFO
S_ISSOCK(); 判斷是否為Socket
S_ISLNK(); 判斷是否為符号連結
           

     對每個檔案都有九個基本相關的存取許可權,如下:

S_IRUSR 使用者讀
S_IWUSR 使用者寫
S_IXUSR 使用者執行

S_IRGRP 組讀
S_IWGRP 組寫
S_IXGRP 組執行

S_IROTH 其他使用者讀
S_IWOTH 其他使用者寫
S_IXOTH 其他使用者執行
           

在一個程序打開檔案時,會按下面四步來進行:

1.先檢查改程序的有效使用者ID,如果為0,說明是超級使用者,則系統給改程序充分的自由去操作檔案,否則進入下一步檢查。
2.檢查程序的有效使用者ID和檔案所有者ID是否相同,如果相同則按照該檔案的所有者的權限進行相關的檢查,符合權限則允許操作,不符合則拒絕,直接結束。ID不同則進入下一步
3.檢查程序的有效組ID和檔案所屬組的ID是否相同,如果相同則按照該檔案組的權限進行相關檢查,符合權限則允許操作,不符合則拒絕,直接結束。ID不同則進入下一步
4.按照該檔案其他使用者的權限進行相關檢查,符合權限則允許操作,不符合則拒絕,直接結束。
           

這裡需要說明的是有效ID和實際ID在大多數情況下是相同的,但是當設定SUID和SGID權限時,有效ID和實際ID就不同了。另外有效ID是程序的一個性質,但是實際ID是檔案的一個性質。每當建立一個檔案的時候,該檔案的所有者和建立檔案程序的有效ID相同,該檔案所屬的組和該程序的有效組ID相同,也可能是該檔案的組和該檔案所在目錄所屬的組相同。

     access函數用程序的實際ID來測試程序對檔案的權限,它的函數原型如下:

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

如果執行成功則傳回0,否則傳回-1。第一個參數為所要進行測試的檔案的名字,第二個參數為測試的權限,它的選擇有:

R_OK 測試讀許可權
W_OK 測試寫許可權
X_OK 測試執行許可權
F_OK 測試檔案是否存在
           

mode可以是上面的幾個參數按位或的結果。需要注意的是access函數隻測試程序的實際ID,而不測試程序的有效ID。一定要注意這一點,否則這可能會在某些情況下給我們造成困惑。

     相信在linux下面使用過umask指令的朋友們,都對umask函數的作用一定也了解。umask函數的作用就是在程序執行時,調整umask的值,給程序建立的檔案設定合适的權限,當該程序結束時,umask仍保持原來系統中的值不變。它的函數原型如下:

mode_t umask(mode_t cmask);
           

它的傳回值是原來的umask的值,這也是linux系統中少數幾個沒有出錯傳回值的幾個函數之一。它的作用是從建立檔案時指定的權限中減掉umask中指定的權限。比如,程序建立檔案時指定的使用者權限是:

rwxrwxrwx
           

而且umask指定的值是022,則改程序建立的檔案的權限就是755。

     chmod和fchmod函數用來改變檔案的權限,它們的函數原型如下:

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

chmod在檔案名上操作,而fchmod在檔案描述符上進行操作。第二個參數用來指定檔案要修改的權限,它是下面幾個參數的按位或:

S_ISUID 是否為SUID
S_ISGID 是否為SGID
S_ISVTX 是否為SBIT

S_IRWXU 使用者讀寫執行
S_IRUSR 使用者讀
S_IWUSR 使用者寫
S_IXUSR 使用者執行

S_IRWXG 組讀寫執行
S_IRGRP 組讀
S_IWGRP 組寫
S_IXGRP 組執行

S_IRWXO 其他讀寫執行
S_IROTH 其他讀
S_IWOTH 其他寫
S_IXOTH 其他執行
           

該函數如果執行成功則傳回0,若出錯傳回-1。關于SUID,SGID和SBIT的相關說明請參考另一篇部落格:

http://blog.csdn.net/xiaocainiaoshangxiao/article/details/17378611
           

使用者在使用程序修改目前檔案的權限時,程序的有效使用者ID必須等于檔案的所有者,或者是0即超級使用者。

     chown,fchown以及lchown用來改變檔案的所有者和所屬的組,它們的函數原型如下:

int chown(const char* pathname, uid_t owner, gid_t group);
int fchown(int filedes , uid_t owner, gid_t group);
int lchown(const char* filename ,uid_t owner ,gid_t group);
           

當該函數執行成功時,傳回0,出錯則傳回-1。修改檔案的使用者ID需要據程序的有效使用者ID為超級使用者。當程序的有效使用者ID等于檔案的使用者ID時,可以修改該檔案組ID。

繼續閱讀