【Linux學習筆記】獲取檔案屬性 — stat()、fstat()、lstat()小結
相關文章
Linux是基於檔案的作業系統,一切皆檔案。下面就詳細的整理一下關於Linux檔案屬性的內容。
一、檔案屬性函式
系統提供了3個獲取檔案屬性的函式,分別是:stat()、fstat()、lstat()。
1、函式原型
標頭檔案包含:
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- int stat(constchar *path, struct stat *buf);
-
int fstat(int fd, struct stat *buf);
- int lstat(constchar *path, struct stat *buf);
注意:
(1) stat() 和 lstat() 都是通過檔案路徑和檔名訪問到檔案,然後把檔案屬性放到 struct stat *buf中;而 fstat() 是通過檔案描述符得到檔案的屬性。
(2) 檔案本身沒有什麼許可權限制,但是檔案的上層目錄必須有訪問許可權才能獲取到檔案的屬性。
(3) 當檔案是符號連結時,lstat() 返回的是該符號連結本身的資訊;而 stat() 返回的是該該符號連結指向的檔案的資訊。
2、檔案屬性結構體
在獲取檔案屬性的時候,使用到了系統定義的檔案屬性結構體,結構體定義在<sys/stat.h>中,原型如下:
- 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 */
- 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 */
- };
其中,st_mode成員描述了檔案的 型別 和 許可權 兩個屬性。
st_mode是32位的整型變數,目前只使用了該變數的低16位。
// 八進位制,過濾出前四位表示的檔案型別
S_IFMT 0170000 bit mask for the file type bit fields
// bit12 ~ bit15
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
// 特殊屬性,分別為set-user-ID位、set-group-ID位和sticky位
S_ISUID 0004000 set UID bit
S_ISGID 0002000 set-group-ID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
// Permission屬性區域的bit0~bit8,即st_mode欄位的最低9位,代表檔案的許可許可權,// 標識了檔案所有者(owner)、組使用者(group)、其他使用者(other)的
// 讀(r)、寫(w)、執行(x)許可權。
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
在最後面的示例程式碼中,會通過 st_mode 成員來判斷檔案的型別。
3、返回值及錯誤
老規矩:
成功返回0,錯誤返回-1,並設定errno。
錯誤返回:
1、ENOENT 引數file_name 指定的檔案不存在
2、ENOTDIR 路徑中的目錄存在但卻非真正的目錄
3、ELOOP 欲開啟的檔案有過多符號連線問題, 上限為16 符號連線
4、EFAULT 引數buf 為無效指標, 指向無法存在的記憶體空間
5、EACCESS 存取檔案時被拒絕
6、ENOMEM 核心記憶體不足
7、ENAMETOOLONG 引數file_name 的路徑名稱太長
二、示例
- /* file stat example */
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <stdlib.h>
- #include <time.h>
- int main(int argc, char **argv){
- struct stat st;
- if(argc != 2){
- fprintf(stderr, "Usage: %s <file_pathname> \n", argv[0]);
- exit(EXIT_FAILURE);
- }
- if(stat(argv[1], &st) == -1){
- perror("stat");
- exit(EXIT_SUCCESS);
- }
- printf("File type: ");
- switch(st.st_mode & S_IFMT){
- case S_IFBLK: printf("block device\n"); break;
- case S_IFCHR: printf("character device\n"); break;
- case S_IFDIR: printf("directory\n"); break;
- case S_IFIFO: printf("FIFO/pipe\n"); break;
- case S_IFLNK: printf("symlink\n"); break;
- case S_IFREG: printf("regular file\n"); break;
- case S_IFSOCK: printf("socket\n"); break;
- default: printf("unknown?\n"); break;
- }
- printf("I-node number: %ld\n", (long) st.st_ino);
- printf("Mode: %lo (octal)\n", (unsigned long) st.st_mode);
- printf("Link count: %ld\n", (long) st.st_nlink);
- printf("Ownership: UID=%ld GID=%ld\n", (long) st.st_uid, (long) st.st_gid);
- printf("device containing file id:%ld \n", (long) st.st_dev);
- printf("device id: %ld \n", (long) st.st_rdev);
- printf("File size: %lld bytes\n", (longlong) st.st_size);
- printf("Preferred I/O block size: %ld bytes\n", (long) st.st_blksize);
- printf("Blocks allocated: %lld\n", (longlong) st.st_blocks);
- printf("Last status change: %s", ctime(&st.st_ctime));
- printf("Last file access: %s", ctime(&st.st_atime));
- printf("Last file modification: %s", ctime(&st.st_mtime));
- exit(EXIT_SUCCESS);
- }
三、執行結果