UNIX文件的信息
stat, fstst, lstat - get file status
1. stat, fstat和lstat
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
-
- int stat(const char *path, struct stat *buf);
- int fstat(int fd, struct stat *buf);
- int lstat(const char *path, struct stat *buf);
stat() stats the file pointed to by path and fills in buf.
lstat() is identical to stat(), except that if path is a sym‐
bolic link, then the link itself is stat-ed, not the file that
it refers to.
fstat() is identical to stat(), except that the file to be
stat-ed is specified by the file descriptor fd.
- struct stat {
- dev_t st_dev; /* ID of device containing file */
- ino_t st_ino; /* inode number */
- mode_t st_mode; /* protection */
- nlink_t st_nlink; /* number of hard links */
- uid_t st_uid; /* user ID of owner */
- gid_t st_gid; /* group ID of owner */
- dev_t st_rdev; /* device ID (if special file) */
- off_t st_size; /* total size, in bytes.used for regular file or symbolic link */
- blksize_t st_blksize; /* blocksize for file system I/O */
- blkcnt_t st_blocks; /* number of 512B blocks allocated */
- time_t st_atime; /* time of last access */
- time_t st_mtime; /* time of last modification */
- time_t st_ctime; /* time of last status change */
- };
2.文件類型:可以由sys/stat.h中相應宏判斷。這些宏基本都是mode和S_IFxx相&得到結果。
(1).普通文件:內核并不區分文本文件還是二進制文件。對普通文件的解釋由處理該文件的應用程序進行。由S_ISREG()宏來判斷。
(2).目錄文件:只有內核才能寫目錄文件。由S_ISDIR()宏來判斷。
(3).塊特殊文件:提供對帶緩沖的設備的訪問。每次訪問以固定長度的單位進行。由S_ISCHR()宏來判斷。
(4).字特殊文件:提供對不帶緩沖的設備的訪問。每次訪問長度可變。系統中只有這兩種設備類型。由S_ISBLK()宏來判斷。
(5).FIFO:這種類型文件用于進程間通信,有時候也稱為命名管道。由S_ISFIFO()宏來判斷。
(6).嵌套字socket:這種文件類型用于進程鍵的網絡通信。也可以用于一臺host上進程之間的非網絡通信。由S_ISSOCK()宏來判斷。
(7).符號鏈接:這種文件類型指向另一個文件。由S_ISLNK()宏來判斷。
POSIX.1允許實現IPC對象表示為文件,同樣可以由宏來判斷S_TYPEPEISMQ()消息隊列,S_TYPEISSEM信號量和S_TYPEISSHM()共享存儲。
3. 文件訪問權限
stat中的st_uid和st_gid:實際用戶ID和實際組ID標識文件究竟屬于誰。有效用戶ID以及附加組ID決定了我們的文件訪問呢權限。通常兩者相等,但在文件模式字中設置一個特殊標志:當執行此文件時,其進程的有效用戶ID設置為文件所有者的ID(st_uid)。與此類似,設置另一個特殊標志:當執行此文件時,其進程的有效用戶組ID設置為文件所有者組的ID(st_gid)。
例如/etc/passwd,/etc/shadow文件所有者是root,只有root才對/etc/passwd,/etc/shadow有寫權限。而passwd允許任何一個用戶改變自己的密碼。因此需要設置passwd的setuid位以保證執行該程序的進程有root權限區更改相關文件。
規則:
(1).open with O_TRUNC必須對文件有寫權限。
(2).創建一個文件必須對所在目錄有寫和執行權限,同樣刪除一個文件必須對文件的目錄有寫和執行權限(不需要對該文件有寫和執行權限)。
(3).如果對該文件使用任意exec函數,必須對該文件有執行權限外還要保證該文件是一個普通文件。
每次打開,創建和刪除一個文件,內核就進行文件訪問權限的測試,而這種測試可能涉及文件的所有者,有效ID(有效用戶和有效組ID)以及附加組ID(如果支持的話)。內核測試的順序是:
a).如果進程有效用戶ID是0,則允許所有權限。
b).若進程的有效用戶ID等于文件的所有者ID,那么根據文件所有者的訪問權限來判斷。
c).若進程的有效組ID或進程的附加組ID之一等于文件的組ID,那么根據文件所有者組的訪問權限來判斷。
d).最后根據其他用戶的適當訪問權限判斷。
對于其中任意一步滿足(無論權限允許還是拒絕),那么不進行下面的測試。
創建新文件:新文件的用戶ID設置為進程的有效用戶ID,而組ID可以為以下二者之一:新文件的組ID可以是進程的有效組ID或為所在目錄的組ID。(Linux ext2/3可以在mount的時候設置)
4.umask, access, chmod, fchmod, chown, fchown, lchown系統調用:略。注:在linux中只有root才能使用chown指令更改用戶ID,但是組ID可以更改為進程的有效組ID(前提是當前進程擁有此文件)。
5.sticky bit:如果一個可執行文件的這一位被設置了,那么該程序第一次執行并結束時,其程序的正文部分(機器指令部分)的一個副本仍被保存在交換區,使得下次執行該程序時能較快地將其裝入內存區。交換區占用連續磁盤空間,可將它視為連續文件。而且一個程序的正文部分在交換區也是連續存放的,相比一般的UNIX文件系統,文件的各數據塊是隨機存放的。所以對于常用的應用程序常常設置它們所在文件的sticky bit。但是對于UNIX系統大多數都配置有虛擬存儲系統和快速文件系統不再需要這種技術。
對目錄設置sticky bit,則只有對該目錄具有寫權限的用戶在滿足下列條件之一的情況下才能刪除和更名目錄下的文件:擁有此文件,擁有此目錄或是超級用戶。目錄/tmp和/var/spool/uucppublic是設置sticky bit的典型候選者,任何用戶都可在這兩個目錄中創建文件。任一用戶對這兩個目錄的權限通常都是讀寫執行兼具。但是用戶不能刪除或者更名屬于其他人的文件,為此這兩個目錄的文件模式都設置了sticky bit。
Reference documentation:
Linux Programmer's Manual STAT(2)
APUE