ls -l這個查詢所輸出的分別是文件的權限信息、硬鏈接數、用戶id、組id、文件大小、最後訪問時間、文件名;這些都在stat結構體裏面、stat結構體以下:數組
/*用不到的成員被註釋掉,只需瞭解須要的成員便可*/ struct stat{ //dev_t st_dev;/*設備id號*/ //ino_t st_ino;/*i節點號*/ mode_t st_mode;/*權限與文件類型*/ nlink_t st_nlink;/*硬連接數*/ uid_t st_uid;/*用戶id*/ ggid_t st_gid;/*所在組id*/ //dev_t st_rdev;/*設備id,對於特殊文件纔有*/ off_t st_size;/*大小,較爲經常使用*/ //blksize_t st_blocks;/*blocksize for file system I/O*/ //blkcnt_t st_blksize;/*number of 512B blocks allocated*/ //time_t st_atime;/*最後的訪問時間*/ time_t st_mtime;/*最後的修改時間,較爲經常使用*/ //time_t st_ctime;/*最後的狀態改變時間*/ }
這個題目我的以爲有些技巧性,首先是9個權限位信息,那麼就要想到mode的權限管理,那麼,上課所講的mode_t mode哦按段文件類型的宏函數、表示文件權限與類型的宏變量就是不可少的:socket
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.)/*判斷是不是SOCKET文件*/
另外就是時間,要充分利用<time.h>裏面的tm結構體,注意到最後利用localtime進行轉換。函數
#include<sys/types.h> #include<sys/stat.h> #include<time.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<dirent.h> #include<unistd.h> #include<pwd.h> #include<grp.h> /** m:mode權限,這個請看前面解釋 str: */ char* get_mode(mode_t mode,char* str)//顯示文件讀寫權限函數 { if(S_ISREG(mode)) strcpy(str,"-");//普通文件 else if(S_ISDIR(mode)) strcpy(str,"d");//目錄文件 else if(S_ISCHR(mode)) strcpy(str,"c");//字符設備文件 else if(S_ISBLK(mode)) strcpy(str,"b");//塊設備文件 else if(S_ISFIFO(mode)) strcpy(str,"p");//管道文件 else if(S_ISLNK(mode)) strcpy(str,"l");//連接文件 else if(S_ISSOCK(mode)) strcpy(str,"n");//socket文件 /**斷定文件訪問權限的屏蔽字 這裏使用strcat的巧妙之處就在於聯想到是到最後字符串,那麼這裏將所需的權限按照順序拼接,只需對比,那麼就能夠輸出這裏是否有訪問的權限 思路來源:leetcode中的題解*/ // 屬主權限 strcat(str,mode&S_IRUSR?"r":"-");//判斷是否用戶可讀 strcat(str,mode&S_IWUSR?"w":"-");//判斷用戶是否可寫 strcat(str,mode&S_IXUSR?"x":"-");//判斷用戶有無執行權限 // 同組權限 strcat(str,mode&S_IRGRP?"r":"-");//判斷組有無讀權限 strcat(str,mode&S_IWGRP?"w":"-");//判斷組有無寫特權 strcat(str,mode&S_IXGRP?"x":"-");//判斷組有無可執行權限 // 其它權限 strcat(str,mode&S_IROTH?"r":"-");//判斷其餘有無讀權限 strcat(str,mode&S_IWOTH?"w":"-");//判斷其餘我有無寫權限 strcat(str,mode&S_IXOTH?"x":"-");//判斷其餘有無寫權限 return str;//返回拼接完成的字符串,即爲要求的9位字符串 } /** 這裏須要明確 一是Unix時間是從1970年1月1日0時0分0秒開始,用秒差形式,那麼在結構體stat中有time_t st_time(最後修改時間)做爲標準來進行打印 二是在c語言中,<time.h>有來判斷時間tm結構體,計算機大多數狀況使用的都是time_t,由於他的效率高,可是顯示位tm結構形式,localtime()實現time_t到tm的轉換,time_t的指針做爲參數,返回值tm的指針 思路來源:學校acm題庫 */ void time_ch(struct stat *message)//經過秒數來計算日期 { struct tm * chtm = localtime(&(message->st_mtime));//這個在上面註釋中已經詳細說明,再也不贅述 if(chtm == NULL){ printf("localtime is error"); exit(0); } else{ printf("%d月 %d ",chtm->tm_mon+1,chtm->tm_mday);//tm_mom屬於[0,11] } if(chtm->tm_hour < 10)//0-9要轉換成0x形式 printf("0");//先打印0 printf("%d:",chtm->tm_hour);//在打印x printf("%d ",chtm->tm_min);//打印分鐘不存在0x問題 //對比ls -l,沒有秒 } void list_nlink(const struct stat *message){//打印出硬鏈接數 printf("%d ",message->st_nlink); } /** 對於main裏面參數的理解 * argc: 整數,爲傳給main()的命令行參數個數。 * argv: 字符串數組。 * env: 安符串數組。env[] 的每個元素都包含ENVVAR=value形式的字符串。其中ENVVAR爲環境變量如PATH或87。value 爲ENVVAR的對應值如C:\DOS,C:\TURBOC(對於PATH)或YES(對於87)。 */ int main(int argc,char** argv,char** environ)//主函數 { char* dir_name=NULL;//文件名字 if(argc == 1)//第一個參數,那麼按道理來說,他應該是根目錄(我的的猜想,沒有獲得驗證) { dir_name="."; } else if(argc == 2)//第二個參數,即爲文件 { dir_name = argv[1];//獲取文件名字 } else//當位3或者更大時,那麼已經不是一個文件,退出程序 { puts("it isn't a dir"); return -1; } DIR* fd = opendir(dir_name);//打開文件 if(NULL == fd)//判斷錯誤並處理 { perror("opendir"); return -1; } struct dirent* de=readdir(fd);//定義接收readdir函數返回的結構體變量,判斷是讀取文件 for(;de;de=readdir(fd))// { if('.'==de->d_name[0]) continue; //經過文件名得到文件信息 struct stat s; int ret = lstat(de->d_name,&s);//用lstat函數讀取filename文件的信息,並將結果返回到stat結構體中 if(0 > ret)//stat函數出錯進行信息輸出 { perror("stat is error"); return -1; }//stat函數不出錯則進行信息輸出 char str[11] = {};//用於9個標誌位所需 printf("%s ",get_mode(s.st_mode,str));//類型 list_nlink(&s); struct passwd *passwd; passwd = getpwuid(s.st_uid); printf ("%s ", passwd->pw_name);//主名 struct group *group; group = getgrgid(passwd->pw_gid); printf ("%s ", group->gr_name); //組名 printf("%5lu ",s.st_size);//大小 time_ch(&s);//時間 printf("%s\t",de->d_name);//文件名 printf("\n"); } closedir(fd);//關閉文件 }
進行測試,發現了本身其中的不足,沒有排序以及沒有總用量,而且沒有對與在使用的打亮。若是有解決的,歡迎指正。測試