linux獲取文件屬性(API)
阿新 • • 發佈:2018-08-14
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)