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! */
};
文件類型
- 普通文件
- 目錄文件
- 塊特殊文件 FreeBSD不再支持
- 字符特殊文件
- FIFO 命令管道,用于進程間通信,第十五章會說明
- 套接字 socket,用于進程間的網絡通信
- 符號鏈接
文件類型信息包含在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
- 打開一個文件就擁有了上目錄的執(zhí)行權限,對目錄執(zhí)行權限位被稱為搜索位。這就是為什么對于目錄其執(zhí)行權限位常被稱為搜索位的原因。
- 讀權限
- 寫權限
- open中指定O_TRUNC,必須要有寫權限
- 創(chuàng)建新文件,必須要有當前目錄的寫和執(zhí)行權限
- 刪除文件,必須要有當前目錄的寫和執(zhí)行權限,對該文件本身不需要讀、寫權限,如果設置t權限那么要檢測是否是文件或者目錄擁有者或者root
- 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 會自動清除兩個權限位的條件
- 一些unix系統(tǒng),不允許除root用戶以外的用戶設置文件S_ISVTX,防止用戶惡意設置,影響系統(tǒng)性能(linux系統(tǒng)沒有這種限制)
- 新文件的組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
這個鏈接計數在stat結構中是st_nlink的成員,其基本系統(tǒng)數據類型是nlink_t,這是硬鏈接,這個計數初始文件1,葉目錄2(本身+./),創(chuàng)建一個硬鏈接就+1,無法給目錄創(chuàng)建或者條件很苛刻
-
軟鏈接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é)點
引入符號鏈接是因為劈開硬鏈接的一些限制
- 不要求鏈接和文件位于同一個文件系統(tǒng)中
- 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)建文件 許可其他在目錄中搜索給定路徑名