国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Unix > 正文

UNIX高級環(huán)境編程(3)Files And Directories

2024-06-28 13:21:57
字體:
供稿:網(wǎng)友
UNIX高級環(huán)境編程(3)Files And Directories - stat函數(shù),文件類型,和各種ID

在前面的兩篇,我們了解了IO操作的一些基本操作函數(shù),包括open、read和write。

在本篇我們來學(xué)習(xí)一下文件系統(tǒng)的其他特性和一個文件的屬性,涉及的函數(shù)功能包括:

  • 查看文件的所有屬性;
  • 改變文件所有者;
  • 改變文件權(quán)限;
  • 操作文件夾。

我們還會了解一些文件系統(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)體如下圖所示:

NewImage

結(jié)構(gòu)體中得每個成員都代表文件的某一個屬性,我們會逐個了解屬性的具體含義。

2 文件類型(File Type)

目前我們了解了兩種文件:常規(guī)文件(regular files)和文件夾(directory)。

常見的幾種文件類型包括:

  1. 常規(guī)文件(Regular File):包含某種組織形式的數(shù)據(jù)的文件,linux并不關(guān)心數(shù)據(jù)是文本或是二進(jìn)制(有一個例外,就是二進(jìn)制可執(zhí)行文件,內(nèi)核必須知道該類型的格式才能執(zhí)行),對數(shù)據(jù)的解析由應(yīng)用程序負(fù)責(zé)。
  2. 目錄文件(Directory):包含其他文件的名字,和指向這些文件信息的指針。進(jìn)程可以讀取目錄文件的內(nèi)容,但是只有內(nèi)核才又寫該類型文件的權(quán)限,進(jìn)程通過調(diào)用本篇介紹的一些函數(shù)才操作修改目錄文件,本質(zhì)上仍然是內(nèi)核修改。
  3. 塊文件(Block Special File):如硬盤驅(qū)動,提供了固定大小緩存用于IO的文件類型。
  4. 字符文件(Charactor Special File):無緩存的對可變大小單元進(jìn)行操作的文件類型。操作系統(tǒng)所有的設(shè)備都是塊設(shè)備文件或字符設(shè)備文件。
  5. 先入先出隊列(FIFO):進(jìn)程間通信使用的文件類型。
  6. 套接字(Socket):網(wǎng)絡(luò)或單機(jī)中的兩個進(jìn)程之間的通信使用的文件類型。
  7. 符號鏈接(Symbolic File):指向另一個文件的文件類型。

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)行截圖:

NewImage

3 設(shè)置用戶Id(User ID)和組Id(Group ID)

每個進(jìn)程6個甚至更多的ID和它關(guān)聯(lián)。如下表所示:

NewImage

簡要介紹ID的區(qū)別:

  • real user ID和real group ID:當(dāng)前登陸用戶的ID和該用戶所屬的組ID;
  • effective user ID、effective group ID和supplementary group IDs:文件的訪問權(quán)限。
  • saved set-user-ID和saved set-group-ID:當(dāng)一個程序運(yùn)行時,會拷貝effective user ID和effective group ID到這兩個變量中,這兩個ID和函數(shù)setuid相關(guān)。

一般情況下,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)限位:

NewImage

這些標(biāo)志位的使用需要注意的事項(xiàng)總結(jié)如下:

  • 如果要打開某個文件,則該文件全路徑上的所有文件夾都需要有執(zhí)行權(quán)限(execute permission),該文件則需要對應(yīng)的操作權(quán)限。需要可執(zhí)行權(quán)限的原因是可以通過(pass through)它找到下一級目錄或者文件;
  • 讀權(quán)限,允許打開某個已存在文件,標(biāo)志位:O_RDONLY和O_RDWR;
  • 寫權(quán)限,允許向某個已存在文件寫入數(shù)據(jù),標(biāo)志位:O_WRONLY和O_RDWR;
  • 調(diào)用open函數(shù)時,如果要指定標(biāo)志位O_TRUNC,需要寫權(quán)限;
  • 我們無法在某個文件夾下創(chuàng)建文件,除非我們對該文件夾有寫權(quán)限(write permission)和執(zhí)行權(quán)限(execute permission);
  • 刪除某個文件,需要該文件所在文件夾的寫權(quán)限和執(zhí)行權(quán)限,而不需要對該文件本身有寫權(quán)限或讀權(quán)限;
  • 如果我們希望使用exec類函數(shù)執(zhí)行某個文件,則必須有可執(zhí)行權(quán)限,并且該文件必須為regular file。

文件訪問權(quán)限檢測流程:

  1. 如果進(jìn)程的effective user ID是0,即超級用戶,則允許訪問;
  2. 如果進(jìn)程的effective user ID是文件所有者的ID,即該進(jìn)程是該文件的所有者(owner),并且相應(yīng)的訪問權(quán)限標(biāo)志位被設(shè)置,則允許訪問;
  3. 如果進(jìn)程的effective group ID或者supplementary group IDs之一是文件所有組的ID,并且相應(yīng)的訪問權(quán)限標(biāo)志位被設(shè)置,則允許訪問;
  4. 如果相應(yīng)的other訪問權(quán)限標(biāo)志位被設(shè)置,則允許訪問。

簡單來說,如果進(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的取值取決于:

  • 新文件的real group ID可以是常見該文件的進(jìn)程的effective group ID;
  • 新文件的real group ID可以是該文件所在目錄的real group ID。(必須保證該目錄下面的所有文件的real group ID都是該目錄的real group ID)。

6 函數(shù)access和faccessat

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,測試文件是否存在。

NewImage

faccessat函數(shù)的相關(guān)細(xì)節(jié):

  • 當(dāng)pathname為絕對路徑,或者fd取值為AT_FDCWD并且pathname為相對路徑時,功能和access相同。
  • 否則,faccessat函數(shù)指定的工作目錄為pathname指定的相對目錄加上fd描述符指定的父目錄。
  • 當(dāng)flag的值為AT_EACCESS時,測試時使用進(jìn)程的effective user和group而不是當(dāng)前real user ID和group。

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);}

測試:

NewImage

由于本地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》


發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 阿拉善右旗| 长武县| 延长县| 宁都县| 温泉县| 陕西省| 南部县| 广水市| 奉新县| 建水县| 清镇市| 安达市| 渝北区| 容城县| 鸡西市| 安龙县| 贡觉县| 卓尼县| 台南县| 肥乡县| 湾仔区| 容城县| 成都市| 江阴市| 敖汉旗| 三原县| 都匀市| 马山县| 芜湖县| 拉萨市| 睢宁县| 诸城市| 尼木县| 扎囊县| 噶尔县| 台山市| 吉水县| 和平区| 南安市| 双江| 南部县|