access函數
NAME
accesss - 檢查實際用戶的文件訪問權限
SYNOPSIS
#include <unistd.h>
int access(const char *pathname, int mode);
#include <fcntl.h> /* Definition of AT_* constants */
#include <unistd.h>
int faccessat(int dirfd, const char *pathname, int mode, int flags);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
faccessat():
Since glibc 2.10:
_XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
Before glibc 2.10:
_ATFILE_SOURCE
DESCRIPTION
access()函數檢查進程是否可以訪問文件路徑名.如果文件名是一個符號鏈接,那它是個引用.
訪問權限將以指定的模式mode去檢查,模式mode的值可以是F_OK,或者是和R_OK、W_OK及X_OK做按位或運算組合. F_OK是測試文件是否存在,R_OK,W_OK和X_OK分別用來測試文件是否具有可寫、可讀和可執行權限.當用戶對文件執行某個操作時(如打開),內核以進程的有效用戶ID和有效組ID爲基礎執行其訪問權限測試.有時,進程也希望按其實際用戶ID和實際組ID來測試其訪問能力.
如果一個進程已超級用戶權限運行,那它可以執行任何一個可運行文件.
faccessat()
除了在描述上有些差異外,faccessat()系統調用和access()完全相同.
如果參數pathname是一個相對路徑名,那它是相對於dirfd的路徑,而不是相對應於當前工作目錄.
如果參數pathname是一個相對路徑名,並且參數dirfd指定爲AT_FDCWD,那pathname被解析爲相對應的當前工作目錄.
如果參數pathname是一個絕對路徑名,參數dirfd被忽略.
flags是由下例幾個值做或運算的組合:
AT_EACCESS 使用有效用戶ID和有效用戶組ID執行訪問權限,默認情況下,faccessat()是以實際用戶ID和實際組ID來檢查其訪問能力.
AT_SYMLINK_NOFOLLOW 如果參數pathname是一個符號鏈接,不要放棄處理,而是返回一個關於符號鏈接本身的信息.
RETURN VALUE
成功返回0(所有檢測權限都通過檢查),失敗返回-1(模式mode至少有一訪問權限被禁止),出錯設置errno指明出錯信息.
ERROES
access()將會失敗,如果出現下一情況:
EACCES 參數pathname所指定的文件不符合測試權限要求.
ELOOP 參數pathname有太多連接符.
ENAMETOOLONG 參數panthname太長.
ENOTDIR 參數panthname是一個目錄.
EROFS 在一個只讀的文件上測試寫入權限.
access()可能會失敗,如果出現下一情況:
EFAULT 參數panthname指針超出可存取內存空間.
EINVAL 指定的參數mode不正確.
EIO IO存取出錯.
ENOMEM 主內存存儲空間不足.
ETXTBSY 在一個正在運行的文件上測試寫入權限.
CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001.
NOTES
警告:使用access()做用戶認證方面的判斷要特別小心,例如在access()後再做open()的空文件可能會造成系統安全上的問題.因爲用戶可能利用檢查和打開中間這個短暫的時間間隔來操作它.所以用戶應該避免這種情況.(例子已說明,一個更安全的選擇是暫時切換進程的有效用戶ID到實際用戶ID,然後再調用open().)
access()取消對符號鏈接的檢查,如果需要對一個符號鏈接進行檢查,請使用faccessat()函數,將標誌位置爲AT_SYMLINK_NOFOLLOW.
如果任意一位訪問權限被禁止,access()將出錯,儘管其他訪問權限位通過.
如果進程有適當的訪問權限,比如超級用戶,在POSIX.1-2001規定中,允許檢查一個沒有設置可執行位的文件,且成功返回,但在Linux下不行.文件所在的每一個目錄都可以訪問,纔可以使用access()檢查文件的訪問權限.如果文件所在目錄不能訪問,則調用access()函數將會失敗,儘管待檢查的文件有訪問的權限.
access()只作權限的檢查, 並不理會文件狀態或文件內容,因此,如果一目錄表示爲"可寫入",表示可以在該目錄中建立新文件等操作,而非意味此目錄可以被當做文件處理.例如:你會發現DOS
的文件都具有"可執行"權限,但用execve()執行時則會失敗.
這些調用在NFSv2文件系統用戶ID映射中可能無法正常工作,因爲檢查UID映射文件時,UID映射文件是在服務器端的,而在客戶端是不可見的,類似的問題也可能會出現在掛載的文件系統中.
C library/kernel ABI differences
原始的faccessat()系統調用只需要前三個參數,標誌AT_EACCESS 和AT_SYMLINK_NOFOLLOW是在glibc函數庫中使用,如果指定其中一個標誌,那函數庫調用fstastat(2)函數來檢查文件的訪問權限.
Glibc notes
在老版本的內核系統中,如果沒有指定AT_EACCESS和AT_SYMLINK_NOFOLLOW標誌的話,函數faccessat()是不可用的,glibc函數庫將會調用access().當參數pathname是相對路徑時,glibc函數庫會在/proc/self/fd中構造一個符號鏈接作爲對應的dirfd參數.
BUGS
在內核2.4(或更早)處理X_OK檢查不是很成熟,對一個沒有目錄的文件,如果所有用戶的可執行權限都被禁止,當access()指定mode爲X_OK來檢查文件權限時,將會返回-1,如果指定mode爲R_OK或者W_OK,則access()返回0.在早期的內核2.6中也有類似的問題.
在內核2.6.20版本前,如果是底層的掛載文件系統,這些函數調用都忽略了標誌MS_NOEXEC,但從內核2.6.20標誌MS_NOEXEC纔得到重視.
END
筆者:個人能力有限,只是學習...讀者若發現文中錯誤,敬請提出.