在前面的兩篇,我們了解了IO操作的一些基本操作函數(shù),包括open、read和write。
在本篇我們來學(xué)習(xí)一下文件系統(tǒng)的其他特性和一個文件的屬性,涉及的函數(shù)功能包括:
我們還會了解一些文件系統(tǒng)相關(guān)的數(shù)據(jù)結(jié)構(gòu)和符號鏈接(symbolic link)。
1 函數(shù)stat、fstat、fstatat、lsat函數(shù)#include <sys/stat.h>int stat(const char *restrict pathname, struct stat *restrict buf );int fstat(int fd, struct stat *buf);int lstat(const char *restrict pathname, struct stat *restrict buf );int fstatat(int fd, const char *restrict pathname, struct stat *restrict buf, int flag);//All four return: 0 if OK, −1 on error
函數(shù)功能:
stat返回pathname指定文件的信息;
fstat獲取在文件描述符fd上打開的文件信息;
lstat的功能和stat函數(shù)類似,只是有一種情況有區(qū)別,當(dāng)pathname指定的文件是一個符號鏈接的時候,lstat函數(shù)獲取的文件信息是該符號鏈接的信息,而不是符號鏈接所指向文件的信息,在后面我們會了解更多關(guān)于符號鏈接的相關(guān)內(nèi)容;
fstatat:文件描述符fd表示一個父目錄,pathame指定父目錄下得一個子目錄,fstatat函數(shù)返回該子目錄下的文件統(tǒng)計數(shù)。flag用來設(shè)置是否查詢符號鏈接所指向的文件,如果flag設(shè)置為AT_SYMLINK_NOFOLLOW,則fstatat函數(shù)只返回該符號鏈接的相關(guān)信息,如果不設(shè)置該標(biāo)志位,則返回該符號鏈接指向的文件的相關(guān)信息。
是一個關(guān)鍵的輸出參數(shù),上面的參數(shù)將文件屬性填充值該結(jié)構(gòu)體內(nèi)。結(jié)構(gòu)體如下圖所示:
結(jié)構(gòu)體中得每個成員都代表文件的某一個屬性,我們會逐個了解屬性的具體含義。
2 文件類型(File Type)目前我們了解了兩種文件:常規(guī)文件(regular files)和文件夾(directory)。
常見的幾種文件類型包括:
stat結(jié)構(gòu)體中得st_mode制定了文件的類型。
Example:
#include "apue.h"intmain(int argc, char *argv[]){ int i; struct stat buf; char *ptr; for (i = 1; i < argc; i++) { PRintf("%s: ", argv[i]); if (lstat(argv[i], &buf) < 0) { err_ret("lstat error"); continue; } if (S_ISREG(buf.st_mode)) ptr = "regular"; else if (S_ISDIR(buf.st_mode)) ptr = "directory"; else if (S_ISCHR(buf.st_mode)) ptr = "character special"; else if (S_ISBLK(buf.st_mode)) ptr = "block special"; else if (S_ISFIFO(buf.st_mode)) ptr = "fifo"; else if (S_ISLNK(buf.st_mode)) ptr = "symbolic link"; else if (S_ISSOCK(buf.st_mode)) ptr = "socket"; else ptr = "** unknown mode **"; printf("%s/n", ptr); } exit(0);}
運(yùn)行截圖:
每個進(jìn)程6個甚至更多的ID和它關(guān)聯(lián)。如下表所示:
簡要介紹ID的區(qū)別:
一般情況下,effective user ID = real user ID,effective group ID = real group ID.
每個文件都由一個所有者,和一個組所有者,分別對應(yīng)stat數(shù)據(jù)結(jié)構(gòu)中得字段:st_uid和st_gid。
如果執(zhí)行程序時,希望effective user(group) ID != real user(group) ID,即希望改變進(jìn)程的訪問資源的權(quán)限為文件所有者的訪問權(quán)限,而不是真實(shí)用戶的訪問權(quán)限,可以通過設(shè)置mode中兩個bit來實(shí)現(xiàn)將effective user(group) ID設(shè)置為文件所有者(組),這兩個bit叫做:set-user-ID位和set-group-ID位。這兩個位包含在stat數(shù)據(jù)結(jié)構(gòu)中得st_mode字段中,可以通過函數(shù)S_ISUID和S_ISGID來測試。
4 文件訪問權(quán)限(File access Permissions)stat數(shù)據(jù)結(jié)構(gòu)中的st_mode字段中同樣包含文件訪問權(quán)限位。
每個文件有9中權(quán)限位:
這些標(biāo)志位的使用需要注意的事項(xiàng)總結(jié)如下:
文件訪問權(quán)限檢測流程:
簡單來說,如果進(jìn)程是該文件的擁有者,則訪問是否允許取決于用戶訪問權(quán)限標(biāo)志位,忽略組權(quán)限標(biāo)志位;如果進(jìn)程不是該文件的擁有者,但是該進(jìn)程屬于某個有訪問權(quán)限的組,訪問是否允許取決于組權(quán)限標(biāo)志位的設(shè)置,忽略other訪問權(quán)限標(biāo)志位。
5 新文件和目錄的所有權(quán)(ownership)新文件的real user ID為創(chuàng)建該文件的進(jìn)程的effective user ID。
新文件的real group ID的取值取決于:
access和faccessat函數(shù)用于測試當(dāng)前用戶(real user,當(dāng)前登錄用戶)對某一文件是否有某種操作權(quán)限。
函數(shù)聲明:
#include <unistd.h>int access(const char* pathname, int mode);int faccessat(int fd, const char* pathname, int mode, int flag);
mode的可取值,當(dāng)為F_OK,測試文件是否存在。
faccessat函數(shù)的相關(guān)細(xì)節(jié):
Example:
#include "apue.h"#include <fcntl.h>intmain(int argc, char *argv[]){ if (argc != 2) err_quit("usage: a.out <pathname>"); if (access(argv[1], R_OK) < 0) err_ret("access error for %s", argv[1]); else printf("read access OK/n"); if (open(argv[1], O_RDONLY) < 0) err_ret("open error for %s", argv[1]); else printf("open for reading OK/n"); exit(0);}
測試:
由于本地mac環(huán)境搞不定,所以直接截書上的例子吧。
該例中,當(dāng)切換到root用戶,修改了該文件的所有者為root用戶,并且設(shè)置了set-user-ID,這樣當(dāng)切換到別的用戶時,仍可以以RDONLY方式打開文件,但是由于access是測試當(dāng)前real user的讀權(quán)限,當(dāng)切換到其他用戶時,access測試不通過,顯示Permission denied。
好吧,直接忽略上面這個例子吧,我沒能在自己的機(jī)器上重現(xiàn),只是直接隨便翻譯書上某一段話。如果有某位高手看懂了,請指點(diǎn)。
小結(jié)由于這一章內(nèi)容比較多,所以打算用三篇來寫,這是第一篇,主要介紹了stat函數(shù),access函數(shù),文件類型和各種令人糊涂的ID。
參考資料:
《Advanced Programming in the UNIX Envinronment 3rd》
新聞熱點(diǎn)
疑難解答