1. 程式人生 > >linux獲取文件屬性(API)

linux獲取文件屬性(API)

line 簡單的 byte 鏈接文件 linux 地址 nano 行操作 while

有三個文件屬性查看的API:stat、fstat、lstat。 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> int stat(const char *pathname, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *pathname, struct stat *buf); #include <fcntl.h> /* Definition of AT_* constants */ #include <sys/stat.h> int fstatat(int dirfd, const char *pathname, struct stat *buf,int flags); stat不用打開文件,fstat需要打開文件,lstat主要是符號鏈接文件,查詢鏈接文件本身。 struct stat是一個內核定義結構體,在#include <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 filesystem I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ /* Since Linux 2.6, the kernel supports nanosecond precision for the following timestamp fields. For the details before Linux 2.6, see NOTES. */ struct timespec st_atim; /* time of last access */ struct timespec st_mtim; /* time of last modification */ struct timespec st_ctim; /* time of last status change */ #define st_atime st_atim.tv_sec /* Backward compatibility */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec }; 在ubantu16.04命令行中輸入 stat XXX: 文件:‘a.out‘ 大小:8968 塊:18 IO 塊:1024 普通文件 設備:2ah/42d Inode:5331 硬鏈接:1 權限:(0777/-rwxrwxrwx) Uid:( 0/ root) Gid:( 0/ root) 最近訪問:2018-08-12 12:29:37.000000000 +0800 最近更改:2018-08-12 12:29:37.000000000 +0800 最近改動:2018-08-12 12:29:37.000000000 +0800 創建時間:- 上訴信息就為結構體裏面數據。 下面非常簡單的測試函數 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #define FILENAME "1.txt" int main (void) { int ret = -1; struct stat buf; memset(&buf, 0, sizeof(buf)); ret = stat(FILENAME,&buf); if(ret<0) { perror("ret:"); _exit(-1); } printf("st_ino = %d\n",buf.st_ino); printf("st_size = %d\n",buf.st_size); printf("st_blksize = %d\n",buf.st_blksize); printf("st_blocks = %d\n",buf.st_blocks); return 0; } 如下為應用案例: 1、判斷文件類型 文件類型在st_mode裏面,這裏面是為操作的,類似於CPSR寄存器。linux中有很多宏來進行操作位的測試。如下 S_ISREG(m) is it a regular file? S_ISDIR(m) directory? S_ISCHR(m) character device? S_ISBLK(m) block device? S_ISFIFO(m) FIFO (named pipe)? S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) S_ISSOCK(m) socket? (Not in POSIX.1-1996.) S_ISREG這個宏返回1,則是普通文件,若不是就返回0.結果就是若是這個文件則是返回1,不是返回0.此外,st_mode還記錄了文件權限。測試方法和文件類型相似,使用位掩碼,但是沒有宏操作。由於很多,不再一一列舉,可通過man 2 stat查看。 簡單測試代碼: unsigned int result = buf.st_mode & (S_IRUSR >> 8); printf("file owner :%X\n",result); 對於文件來說,很重要的一部分就是文件的權限管理。 st_mode本質上一個三十二位的二進制,類型差不多就是unsigned int,反正差不多。 在操作之前需要對文件進行權限規則檢查: 1、文件有9個權限位(owner,group,others) 2、若是a.out為例,是看什麽執行了a.out,也就是當前進程,是哪個用戶進程。 在linux下面可以通過access函數來判斷是否有執行權限,可以測試得到當前用戶當前環境對目標文件是否有某種操作權限。 #include <unistd.h> int access(const char *pathname, int mode); 具體可通過man 2 access查看。 chowd和fchowd和lchowd 通過man 2 chmod查看,是用修改文件屬主。 文件掩碼umask是linux中的一個全局設置,作用就是設定我們系統新創建權限。 對於目錄文件,包含子文件的文件。 opendir與readdir #include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); DIR *fdopendir(int fd); #include <dirent.h> struct dirent *readdir(DIR *dirp); int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result); struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* not an offset; see NOTES */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file; not supportedby all filesystem types */ char d_name[256]; /* filename */ }; 每調用readdir一次只能讀出一個,要想讀出目錄中的所有目錄項,那麽必須多次讀取,readdir函數內部記住那個目錄已經被調用的,不會回返已經讀取的目錄項,要是readdir要是返回NULL就表示已經讀取完了。簡單的測試函數如下: #include <stdio.h> #include <dirent.h> #include <sys/types.h> #include <dirent.h> int main(int argc,char **argv) { DIR *pDir = NULL; struct dirent *pEnt = NULL; if(argc !=2) { printf("error"); return 0; } pDir = opendir(argv[1]); if(NULL == pDir) { perror("opendir:\n"); return -1; } while(1) { pEnt = readdir(pDir); if(pEnt != NULL) { printf("name:%s\n",pEnt->d_name); } else { break; } } return 0; } 可重入函數:readdir函數和以前接觸的函數是不同的,這個函數直接返回了一個結構體指針。因readdir內部申請了內存並且給了我們地址,多次調用readdir其實不會重復申請內存而是使用第一次調用readdir是分配的那個內存,所以設計方法是readdir不可重入的關鍵。 庫函數有一些函數是不可重入的,後來意識到這個中不安全,後來重新封裝了C庫函數,一般是不可重入函數後面加入_r變成可重入的函數。

朱友鵬老師視頻學習筆記

linux獲取文件屬性(API)