一、stat 函數,獲取文件元數據
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
二、stat結構體字段詳情如下:
struct stat{
dev_t st_dev; //設備號,文件所在磁盤位置。高8位主,低8位次
ino_t st_ino; //inode num ls -i 可查看i節點號
mode_t st_mode;//文件的類型和存取的權限. (st_mode & S_IFMT)得到文件類型,(st_mode & 07777) 獲取權限,並以8進制輸出。
nlink_t st_nlink;//鏈向此文件的連接數(硬連接)
uid_t st_uid; //文件所屬用戶
gid_t st_gid; //文件所屬組
dev_t st_rdev;//設備號,針對設備文件
off_t st_size;//文件大小,字節為單位
blksize_t st_blksize;//系統塊的大小
blkcnt_t st_blocks;//文件所占塊數
time_t st_atime;//最近存取時間(訪問時間)
time_t st_mtime;//最近修改時間 ---實現ls中的時間
time_t st_ctime;//最近狀態改變時間
}
/**********************
實現ls -l 功能
1、第一欄:文件的屬性 2、第二欄:表示文件個數。如果是文件的話,那個數是1;如果是目錄,那數目就是該目錄中的文件個數。
3、第三欄:該文件或目錄的擁有者。 4、第四欄:表示所屬的組(group)。
5、 第五欄:表示文件大小。文件大小用byte來表示。 6、 第六欄:表示創建日期。以“月,日,時間”的格式表示。
7、第七欄:表示文件名
鏈接數 st_nlink
用戶名 st_uid---再利用getpwuid得到用戶struct passwd結構體。結構體pw_name為用戶名
組名 st_gid ---利用getprgid(gid_t gid) 得到group字段的gr_name
文件大小 off_t st_size
時間 st_mtime
名稱
如果是符號鏈接文件: 獲取其指向的文件。 readlink. 符號鏈接文件用 lstat()來獲取符號鏈接文件自身的狀態。stat()查看符號鏈接所指向文件的狀態
***********************/
1 #include<unistd.h> 2 #include<sys/types.h> 3 #include<sys/stat.h> 4 #include<fcntl.h> 5 #include<stdlib.h> 6 #include<stdio.h> 7 #include<errno.h> 8 #include<string.h> 9 #define ERR_EXIT(m)\ 10 do\ 11 {\ 12 perror(m);\ 13 exit(EXIT_FAILURE);\ 14 }while(0) //宏要求一條語句 15 #define MAJOR(x) (int)((unsigned short)x >> 8)//主設備號,高8位 16 #define MINOR(x) (int)((unsigned short)x & 0x00ff) //次設備號,低8位 17 int filetype(struct stat *buf);//打印文件類型 18 void filepermission(struct stat *buf,char *perm);//將權限bits位轉換成字符形式 19 int main(int argc,char* argv[]) 20 { 21 if(argc!=2) 22 { 23 fprintf(stderr,"Usage %s file\n",argv[0]); 24 exit(EXIT_FAILURE); 25 } 26 struct stat sbuf; 27 //打印文件名 28 printf("Filename:%s\n",argv[1]); 29 if(stat(argv[1],&sbuf)==-1)//ls -li argv[1] df argv[1] 30 { 31 ERR_EXIT("stat error"); 32 } 33 //打印設備號和i結點號碼。主設備號決定了系統用什么驅動程序訪問設備 34 printf("FILE number:major %d,minor %d,inode %d \n",MAJOR(sbuf.st_dev),MINOR(sbuf.st_dev),(int)sbuf.st_ino); 35 36 if(filetype(&sbuf))//獲取文件類型。 37 { 38 printf("Device number:major %d,minor %d\n",MAJOR(sbuf.st_rdev),MINOR(sbuf.st_rdev));//如果是設備文件,打印出主次設備號 39 } 40 //獲取文件權限 41 char perm[]="----------";//第一位是類型 42 filepermission(&sbuf,perm); 43 //打印文件權限 44 printf("File Permission bits=%o %s\n",(sbuf.st_mode&07777),perm); 45 return 0; 46 }
//打印輸出文件類型。 47 int filetype(struct stat *buf) 48 { 49 int flag=0; 50 printf("Filetype: "); 51 mode_t mode; 52 mode=buf->st_mode;//需要與掩碼與得到的結果可判定文件類型 53 switch(mode & S_IFMT){ 54 case S_IFSOCK: 55 printf("socket \n"); 56 break; 57 case S_IFLNK: 58 printf("symbolic link\n"); 59 break; 60 case S_IFREG: 61 printf("regular file\n"); 62 break; 63 case S_IFBLK: 64 printf("block file\n"); 65 break; 66 case S_IFDIR: 67 printf("directory\n"); 68 break; 69 case S_IFCHR: 70 flag=1;//設備文件 71 printf("character device\n"); 72 break; 73 case S_IFIFO: 74 printf("FIFO\n"); 75 break; 76 default : 77 printf("unknown file type\n"); 78 break; 79 } 80 return flag; 81 }
//打印文件權限 82 void filepermission(struct stat *buf,char * perm) 83 { 84 85 perm[0]='?';//先獲取類型 86 mode_t mode; 87 mode=buf->st_mode;//需要與掩碼與得到的結果可判定文件類型 88 switch(mode & S_IFMT){ 89 case S_IFSOCK: 90 perm[0]='s'; 91 break; 92 case S_IFLNK: 93 perm[0]='l'; 94 break; 95 case S_IFREG: 96 perm[0]='-'; 97 break; 98 case S_IFBLK: 99 perm[0]='b'; 100 break; 101 case S_IFDIR: 102 perm[0]='d'; 103 break; 104 case S_IFCHR: 105 perm[0]='c'; 106 break; 107 case S_IFIFO: 108 perm[0]='p'; 109 break; 110 } 111 //再獲取權限.也可利用算法實現664 ----rw rw w 112 if(mode & S_IRUSR) 113 perm[1]='r'; 114 if(mode & S_IWUSR) 115 perm[2]='w'; 116 if(mode & S_IXUSR) 117 perm[3]='x'; 118 if(mode & S_IRGRP) 119 perm[4]='r'; 120 if(mode & S_IWGRP) 121 perm[5]='w'; 122 if(mode & S_IXGRP) 123 perm[6]='x'; 124 if(mode & S_IROTH) 125 perm[7]='r'; 126 if(mode & S_IWOTH) 127 perm[8]='w'; 128 if(mode & S_IXOTH) 129 perm[9]='x'; 130 perm[10]='\0'; 131 }