第四章 文件目錄

stat,fstat,fstatat,lstat

#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);//link有關信息,比stat多檢測link文件
int fstatat(int fd,const char *restrict pathname,struct stat *restrict buf,int flag);//

struct stat{
    mode_t          st_mode;i節(jié)點 中文件訪問權限
    ino_t           st_ino;目錄項中 i節(jié)點編號
    dev_t           st_dev;
    dev_t           st_rdev;
    nlink_t         st_nlink;有鏈接計數
    uid_t           st_uid;
    gid_t           st_gid;
    off_t           st_size;
    struct timespec st_atime;
    struct timespec st_mtime;
    struct timespec st_ctime;
    blksize_t       st_blksize;
    blkcnt_t        st_blocks;
}
struct timespec{
    time_t tv_sec;
    long   tv_nsec;
    ...
}

//附一份macos 10.13.4
truct stat {
    dev_t       st_dev;     /* [XSI] ID of device containing file */
    ino_t       st_ino;     /* [XSI] File serial number */
    mode_t      st_mode;    /* [XSI] Mode of file (see below) */
    nlink_t     st_nlink;   /* [XSI] Number of hard links */
    uid_t       st_uid;     /* [XSI] User ID of the file */
    gid_t       st_gid;     /* [XSI] Group ID of the file */
    dev_t       st_rdev;    /* [XSI] Device ID */
#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE)
    struct  timespec st_atimespec;  /* time of last access */
    struct  timespec st_mtimespec;  /* time of last data modification */
    struct  timespec st_ctimespec;  /* time of last status change */
#else
    time_t      st_atime;   /* [XSI] Time of last access */
    long        st_atimensec;   /* nsec of last access */
    time_t      st_mtime;   /* [XSI] Last data modification time */
    long        st_mtimensec;   /* last data modification nsec */
    time_t      st_ctime;   /* [XSI] Time of last status change */
    long        st_ctimensec;   /* nsec of last status change */
#endif
    off_t       st_size;    /* [XSI] file size, in bytes */
    blkcnt_t    st_blocks;  /* [XSI] blocks allocated for file */
    blksize_t   st_blksize; /* [XSI] optimal blocksize for I/O */
    __uint32_t  st_flags;   /* user defined flags for file */
    __uint32_t  st_gen;     /* file generation number */
    __int32_t   st_lspare;  /* RESERVED: DO NOT USE! */
    __int64_t   st_qspare[2];   /* RESERVED: DO NOT USE! */
};

文件類型

  1. 普通文件
  2. 目錄文件
  3. 塊特殊文件 FreeBSD不再支持
  4. 字符特殊文件
  5. FIFO 命令管道,用于進程間通信,第十五章會說明
  6. 套接字 socket,用于進程間的網絡通信
  7. 符號鏈接

文件類型信息包含在stat結構的st_mode成員中,上面有定義

//文件類型宏  st_mode 對應上面七種文件
S_ISREG()
S_ISDIR()
S_ISBLK()
S_ISCHR()
S_ISFIFO()
S_ISSOCK()
S_ISLNK()
//POSIX.1 允許實現將IPC對象說明為文件,但是有四種unix系統(tǒng)不將這些對象表示為文件,蛋疼,標準不遵守
S_TYPEISMQ()  消息隊列
S_TYPEISSEM() 信號量
S_TYPEISSHM() 共享存儲對象

設置用戶ID和設置組ID

一個進程關聯(lián)的ID有6種

實際用戶id,組id就是有效用戶id,組id

執(zhí)行一個程序文件的時候,如果該文件設置了下面的S_ISUID權限,那么進程執(zhí)行這個文件的時候就會將進程有效用戶id設置成文件所有者用戶id,類似S_ISGID,下面有chmod的條件二的特例

s權限位

典型場景,普通用戶可以修改密碼,而密碼記錄文件/etc/passwd和/etc/shadow普通用戶都是無法修改的,沒有權限,但是passwd命令的權限是-rwsr-xr-x,這就以為著,普通用戶使用這個命令時,在執(zhí)行的進程中,實際就以屬主root身份執(zhí)行,當然前提是要有相應的執(zhí)行權限x

安全問題,第八章討論

文件訪問權限

st_mode 值包含了這些權限。

用戶(擁有者)讀寫執(zhí)行,同組讀寫執(zhí)行,其他組讀寫執(zhí)行

0400 0200 0100 0040 0020 0010 0004 0002 0001

S_IRUSR S_IWUSR S_IXUSR S_IRGRP S_IWGRP S_IXGRP S_IROTH S_IWOTH S_IXOTH

進程中操作文件,其實開這個進程的實際用戶id,組id就是進程的有效用戶id,組id

  1. 打開一個文件就擁有了上目錄的執(zhí)行權限,對目錄執(zhí)行權限位被稱為搜索位。這就是為什么對于目錄其執(zhí)行權限位常被稱為搜索位的原因。
  2. 讀權限
  3. 寫權限
  4. open中指定O_TRUNC,必須要有寫權限
  5. 創(chuàng)建新文件,必須要有當前目錄的寫和執(zhí)行權限
  6. 刪除文件,必須要有當前目錄的寫和執(zhí)行權限,對該文件本身不需要讀、寫權限,如果設置t權限那么要檢測是否是文件或者目錄擁有者或者root
  7. 7個exec函數任何執(zhí)行某個文件,都需要具有該文件的執(zhí)行權限,而且必須是普通文件

新文件和目錄的所有權

新文件和新目錄所有權規(guī)則相同

用戶ID為進程有效用戶ID;組ID實現兩種:進程有效組ID,所在目錄的組ID

#include <unistd.h>
int access(const char *pathname,int mode);
int faccessat(int fd,const char *pathname,int mode,int flag);//成功0

mode 值

R_OK W_OK X_OK

umask

#include <sys/stat.h>
mode_t umask(mode_t cmask);//返回值是之前文件模式創(chuàng)建屏蔽字,少數幾個沒有出錯返回

作用就是無法設置權限
常用002(其他用戶寫),022(),027()
2018-4-10 23:31

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

改文件權限必須是擁有者或者超管

mode:上面9中再加下面六種

組合權限:S_IRWXU S_IRWXG S_IRWXO

特殊權限三種:

s權限:S_ISUID(執(zhí)行時設置用戶ID) S_ISGID(執(zhí)行時設置組ID)

t權限:粘著位,S_ISVTX(保存正文saved-text) ,現在只針對目錄,刪除文件的權限

chmod("file",(buf.st_mode & ~S_IXGRP) | S_ISGID)

s權限配合執(zhí)行權限(用戶和組必須設置x權限)可以以root身份權限執(zhí)行

vtx權限也就是t權限:給目錄和文件設置t權限是完全不同目的,目錄擁有t權限,那么目錄下的文件只有該目錄擁有者或者文件擁有者和root才能刪除和更名

chmod 會自動清除兩個權限位的條件

  1. 一些unix系統(tǒng),不允許除root用戶以外的用戶設置文件S_ISVTX,防止用戶惡意設置,影響系統(tǒng)性能(linux系統(tǒng)沒有這種限制)
  2. 新文件的組ID不等于進程有效組ID,而且沒有root權限,那么設置組ID會被關閉

chown,fchown,fchownat,lchown

#include <unistd.h>
int chown(const char *pathname,uid_t owner,gid_t group);
int fchown(int fd,uid_t owner,gid_t group);
int fchownat(int fd,const char *pathname,uid_t owner,gid_t group,int flag);
int lchown(const char *pathname,uid_t owner,gid_t group);
AT_FDCWD 相對path = 絕對path 很多函數用到

基于BSD系統(tǒng)規(guī)定只有root用戶可以更改一個文件的所有者

System V 則允許任一用戶更改他們所擁有文件的所有者

文件長度

st_size

st_blksize

st_blocks

文件空洞

原因是偏移量超過文件尾端,并寫入數據造成的

文件截斷

第三章open函數第二個參數中有個O_TRUNC

#include <unistd.h>
int truncate(const char *pathname,off_t length);
int ftruncate(int fd,off_t length);

文件系統(tǒng)

solaris支持多種不同類型的磁盤文件系統(tǒng)

基于傳統(tǒng)bsd的ufs,讀寫dos的pcfs,cd的hsfs

macos大小寫不敏感

2018-4-12 23:55

文件系統(tǒng)的構成,下面

  • 磁盤:各個分區(qū)
  • 文件系統(tǒng):自舉塊,超級塊,柱面0...
  • 柱面:超級塊的副本,配置信息,i節(jié)點圖,塊位圖,i節(jié)點,數據塊
  • i節(jié)點:各個i節(jié)點...

目錄和文件塊:i節(jié)點數組,數據塊,目錄塊

目錄塊(項)中有文件名i節(jié)點編號(數據類型是ino_t),其中i節(jié)點指向數據塊

每個i節(jié)點有個鏈接計數,就是指向該節(jié)點的目錄項數,只有減少至0,才可以刪除文件,就是解除對一個文件的鏈接并不是釋放該文件占用的磁盤塊,就是刪除一個目錄項是unlink而不是delete

  1. 這個鏈接計數在stat結構中是st_nlink的成員,其基本系統(tǒng)數據類型是nlink_t,這是硬鏈接,這個計數初始文件1,葉目錄2(本身+./),創(chuàng)建一個硬鏈接就+1,無法給目錄創(chuàng)建或者條件很苛刻

  2. 軟鏈接S_IFLINK,符號鏈接symbolic link,它的實際類容:在數據塊中包含了該符號鏈接指向的文件名字,比如

    ls lib 
    lib -> usr/lib
    實際類容就是 usr/lib 這7個字節(jié)
    

i節(jié)點,stat大多信息來自i節(jié)點:文件類型、文件訪問權限、文件長度、指向文件數據塊的指針

目錄項,一個目錄項不能指向另一個文件系統(tǒng)

link,linkat,unlink,unlinkat,remove

#include <unistd.h>
int link(const char *existingpath,const char *newpath);
int linkat(int efd,const char *existingpath,int nfd,const char *newpath,int flag);

創(chuàng)建新目錄項和添加鏈接計數是一個原子操作

#include <unistd.h>
int unlink(const char *existingpath,const char *newpath);
int unlinkat(int fd,const char *pathname,int flag);
#include <stdio.h>
int remove(const char *pathname)

rename,renameat

#include <stdio.h>
int rename(const char *oldname,const char *newname);
int renameat(int oldfd,const char *oldname,int newfd,const char *newname);

符號鏈接

符號鏈接是一個文件的間接指針,硬鏈接直接指向文件的i節(jié)點

引入符號鏈接是因為劈開硬鏈接的一些限制

  1. 不要求鏈接和文件位于同一個文件系統(tǒng)中
  2. root才能創(chuàng)建(底層文件系統(tǒng)支持的情況下,因為很多還是不支持,mac和linux)

必須考慮函數是否可以處理符號鏈接

Mkdir,mkinfo,mknod,rmdir

避免子目錄指向父目錄造成死循環(huán),而且軟鏈接可以unlink,但是硬鏈接很難消除,這就是為什么硬鏈接有限制

創(chuàng)建和讀取符號鏈接

#include <unistd.h>
int symlink(const char *actualpath,const char *sympath);
int symlinkat(const char *actualpath,int fd,const char *sympath);
//open函數跟隨符號鏈接,所有下面方法可以打開鏈接本身
ssize_t readlink(const char* restrict pathname,char* restrict buf,size_t bufsize);
ssize_t readlinkat(int fd,cosnt char* restrict pathname,char* restrict buf,size_t bufsize);

兩個函數組合了open、read、close的所有操作

文件的時間

每個文件會維護三個時間

ls命令選項
st_atime 最后訪問時間-文件內容 read -u
st_mtime 最后修改時間-文件內容 write 默認
st_ctime i節(jié)點最后更改時間 chown,chmod -c

i節(jié)點所有信息都是與文件的實際內容分開存放的

st_ctime 系統(tǒng)不會維護,沒有函數可以去自定義修改這個

access、stat函數并不更改這3個時間中的任何一個

ps 創(chuàng)建一個新文件影響到包含次新文件的目錄,頁影響該文件的i節(jié)點,但是讀或寫只影響該文件的i節(jié)點

futimens,utimensat,utimes

POSIX.1中

#include <sys/stat.h>
int futimens(int fd,const struct timespec times[2]);
int utimensat(int fd,const char *path,const struct timespec times[2],int flag);

tv_nsec 字段:UTIME_NOW,UTIME_OMIT

times[2]:第一個包含訪問時間st_atime,第二個包含修改時間st_mtime

Single UNIX Specification的XSI擴展中

#include <sys/time.h>
int utimes(const char *pathname,const struct timeval times[2]);
struct timeval{
    time_t tv_sec;//s
    long tv_usec;//ms
}

場景:touch命令使用這些函數的某一個,tar和cpio也會可選地調用這些函數

Ps: macos中有些問題

mkdir,mkdirat,rmdir

#include <sys/stat.h>
int mkdir(const char *pathname,mode_t mode);
int mkdirat(int fd,const char *pathname,mode_t mode);

對應目錄來說,通常至少要設置一個x權限位,允許訪問該目錄中的文件名

#include <unistd.h>
int rmdir(const char *pathname);

讀目錄

一個目錄的w和x權限決定能否在目錄下new和del文件(當然前提是該目錄的t權限位沒有設置),但是這并不代表能否寫目錄本身

#include <dirent.h>
DIR *opendir(const char *pathname);//success:返回指針 fail:返回NULL
DIR *fdopendir(int fd);//success:返回指針 fail:返回NULL
以上兩個函數返回的指針由下面5個函數使用
struct dirent *readdir(DIR *dp);//success:返回指針 fail:返回NULL。返回下一個目錄的指針

void rewinddir(DIR *dp);//將偏移量放在最開始
int closedir(DIR *dp);//關閉目錄

long telldir(DIR *dp);//返回值與dp關聯(lián)的目錄中的當前位置。查詢偏移量

void seekdir(DIR *dp,long loc);//設置偏移量
DIR是一個內部結構

fig4.22實現了遍歷目錄

chdir,fchdir,getcwd

chdir,fchdir可以更改當前工作目錄

#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int fd);
#include <unistd.h>
char *getcwd(char *buf,size_t size);//success:返回buf,fail:返回NULL

設備特殊文件

st_dev,st_rdev

小結

S_ISUID S_ISGID

設置用戶ID 設置組 ID

執(zhí)行時設置有效用戶 ID

若組執(zhí)行位設置,則執(zhí)行時設置有效 組 ID;否則使強制性鎖起作用(若支持)

(未使用)

將在目錄中創(chuàng)建的新文件的組 ID 設置為目錄的組 ID

S_ISVTX

粘著位

在交換區(qū)緩存程序正文(若支持)

限止在目錄中刪除和重命名文件

S_IRUSR S_IWUSR S_IXUSR

用戶讀 用戶寫 用戶執(zhí)行

許可用戶讀文件

許可用戶寫文件

許可用戶執(zhí)行文件

許可用戶讀目錄項 許可用戶在目錄中刪除和創(chuàng)建文件 許可用戶在目錄中搜索給定路徑名

S_IRGRP S_IWGRP S_IXGRP

組讀 組寫 組執(zhí)行

許可組讀文件

許可組寫文件

許可組執(zhí)行文件

許可組讀目錄項

許可組在目錄中刪除和創(chuàng)建文件

許可組在目錄中搜索給定路徑名

S_IROTH S_IWOTH S_IXOTH

其他讀 其他寫 其他執(zhí)行

許可其他讀文件

許可其他寫文件

許可其他執(zhí)行文件

許可其他讀目錄項 許可其他在目錄中刪除和創(chuàng)建文件 許可其他在目錄中搜索給定路徑名

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數據革命閱讀 13,251評論 2 33
  • Ubuntu的發(fā)音 Ubuntu,源于非洲祖魯人和科薩人的語言,發(fā)作 oo-boon-too 的音。了解發(fā)音是有意...
    螢火蟲de夢閱讀 100,704評論 9 468
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現,斷路器,智...
    卡卡羅2017閱讀 136,569評論 19 139
  • 故事的開始,是一場意外; 故事的發(fā)展,是我一直的空歡喜; 這個故事,還在發(fā)生著,不知最后,是死是活。 “你喜歡男的...
    勒布朗的心肝兒閱讀 552評論 1 1

友情鏈接更多精彩內容