UNIX-LINUX编程实践教程-第三章-实例代码注解-ls2
一 問題
對ls1的功能進行擴展,以達到類似ll命令的功能。
二 分析
在ls1中,我們利用readdir()函數和dirent結構體來獲得目標文件夾內的文件名(dirent->d_name)。
現在我們借助函數stat()和結構體stat以及上面得到的文件名來獲得該目錄內文件的詳細信息(參看后面的“相關函數與結構體”部分)。
三 實現
1 頭文件
#include<stdio.h> #include<sys/types.h> #include<dirent.h> #include<sys/stat.h> #include<string.h>2 相關函數聲明
void do_ls(char dirname[]); void dostat(char *filename); void show_file_info(char *filename,struct stat *info_p); void mode_to_letters(int mode,char str[]); char *uid_to_name(uid_t uid); char *gid_to_name(gid_t gid);3 主函數
獲得目錄的路徑,并將該路徑傳遞給do_ls()函數
main(int ac,char *av[]) {if(ac == 1){do_ls(".");}else{while(--ac){printf("%s:\n",*++av);/* 傳遞目錄路徑到do_ls函數 */do_ls(*av);}} }4 do_ls()函數
結合opendir()函數和readdir()函數,通過目錄的路徑獲得該目錄內各文件或文件夾的名稱,并將該名稱傳遞給dostat()函數
void do_ls(char dirname[]) {DIR *dir_ptr;struct dirent *direntp;/* 使用opendir()函數“打開”目錄,返回指向該目錄的指針 */if((dir_ptr = opendir(dirname))==NULL){fprintf(stderr,"ls2:cannot open %s\n",dirname);}else{/* 使用readdir()函數讀取指針指向的目錄,獲得dirent結構體 */while((direntp = readdir(dir_ptr))!=NULL){/* 通過dirent結構體獲得文件名,并將文件名傳遞給dostat()函數 */dostat(direntp->d_name);}closedir(dir_ptr);} }5 dostat()函數
使用stat()函數,通過文件或文件夾的名稱獲得保存了該文件信息的stat結構體,將該結構體傳遞給show_file_info()函數
void dostat(char *filename) {struct stat info;/* 使用stat()函數,通過文件名獲得stat結構體info */if(stat(filename,&info) == -1){perror(filename);}else{/* 將stat結構體傳遞給show_file_info()函數 */show_file_info(filename,&info);} }6 show_file_info()函數
將stat結構體中的各項參數分別解析并輸出到標準輸出
void show_file_info(char *filename,struct stat *info_p) {/* 各解析函數聲明 */char *uid_to_name(),*ctime(),*gid_to_name(),*filemode();void mode_to_letters();char modestr[11];/* 解析并輸出文件的mode信息 */mode_to_letters(info_p->st_mode,modestr);printf("%s",modestr);/* 文件連接數 */printf("%4d",(int)info_p->st_nlink);/* 通過uid獲得對應的用戶名 */printf("%-8s",uid_to_name(info_p->st_uid));/* 通過gid獲得對應的組名 */printf("%-8s",gid_to_name(info_p->st_gid));/* 文件大小 */printf("%8ld",(long)info_p->st_size);/* 最近一次修改時間 */printf("%.12s",4+ctime(&info_p->st_mtime));/* 文件名 */printf("%s\n",filename); }?7?mode_to_letters()函數
將傳遞進來的mode參數解析成string格式
void mode_to_letters(int mode,char str[]) {strcpy(str,"----------");if(S_ISDIR(mode)) str[0] = 'd';if(S_ISCHR(mode)) str[0] = 'c';if(S_ISBLK(mode)) str[0] = 'b';if(mode&S_IRUSR) str[1] = 'r';if(mode&S_IWUSR) str[2] = 'w';if(mode&S_IXUSR) str[3] = 'x';if(mode&S_IRGRP) str[4] = 'r';if(mode&S_IWGRP) str[5] = 'w';if(mode&S_IXGRP) str[6] = 'x';if(mode&S_IROTH) str[7] = 'r';if(mode&S_IWOTH) str[8] = 'w';if(mode&S_IXOTH) str[9] = 'x'; }其中S_ISDIR、S_ISCHR、S_ISBLK等是宏,定義如下所示:
#define S_ISFIFO(m) (((m)(0170000)) == (0010000)) #define S_ISDIR(m) (((m)(0170000)) == (0040000)) #define S_ISCHR(m) (((m)(0170000)) == (0020000)) #define S_ISBLK(m) (((m)(0170000)) == (0060000)) #define S_ISREG(m) (((m)(0170000)) == (0100000))8?uid_to_name()函數
通過用戶的uid,利用getpwuid()函數,將uid轉換為用戶名
#include<pwd.h> char *uid_to_name(uid_t uid) {struct passwd *getpwuid(),*pw_ptr;static char numstr[10];if((pw_ptr = getpwuid(uid))==NULL){sprintf(numstr,"%d",uid);return number;}else{return pw_ptr->pw_name;} }9?gid_to_name()函數
通過用戶的gid,利用getgrgid()函數,將gid轉換為組名
#include<grp.h> char *gid_to_name(gid_t gid) {struct group *getgrgid(),*grp_ptr;static char numstr[10];if((grp_ptr = getgrgid(gid))==NULL){sprintf(numstr,"%d",gid);return numstr;}else{return grp_ptr->gr_name;} }?
相關函數與結構體
1 stat()函數
通過文件名獲取文件信息,并保存在stat結構體中
頭文件:#include <sys/stat.h> #include <unistd.h>
函數原型 int stat(const char *file_name, struct stat *buf)
參數 file_name 指向文件名的指針
buf 指向stat結構體的指針
返回值 0 執行成功
-1 執行失敗,錯誤代碼存于ermo中
2 stat結構體
頭文件:#include<sys/stat.h>
struct stat
{
mode_t st_mode; //文件對應的模式,文件,目錄等
ino_t st_ino; //i-node節點號
dev_t st_dev; //設備號碼
dev_t st_rdev; //特殊設備號碼
nlink_t st_nlink; //文件的連接數
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者對應的組
off_t st_size; //普通文件,對應的文件字節數
time_t st_atime; //文件最后被訪問的時間
time_t st_mtime; //文件內容最后被修改的時間
time_t st_ctime; //文件狀態(屬性)改變時間
blksize_t st_blksize; //文件內容對應的塊大小
blkcnt_t st_blocks; //文件內容對應的塊數量
}
3 ctime()函數
把日期和時間轉換為字符串
頭文件:#include <cstdio> #include <ctime>
函數原型?char *ctime(const time_t *time)
參數 time time_t格式的時間
返回值 char * 字符串格式的時間
4?getpwuid()函數
通過用戶的uid查找用戶的相關信息,并以passwd結構體返回其數據
頭文件:#include <sys/types.h> #include <pwd.h>
函數原型?struct passwd *getpwuid(uid_t uid)
參數 uid 用戶的uid
返回值 passwd結構體 uid對應的用戶信息
空指針 出錯
5?passwd結構體
struct passwd
{
char * pw_name; /* Username, POSIX.1 */
char * pw_passwd; /* Password */
__uid_t pw_uid; /* User ID, POSIX.1 */
__gid_t pw_gid; /* Group ID, POSIX.1 */
char * pw_gecos; /* Real Name or Comment field */
char * pw_dir; /* Home directory, POSIX.1 */
char * pw_shell; /* Shell Program, POSIX.1 */
char *pw_class;
time_t pw_change;
time_t pw_expire;
}
6?getgrgid()函數
通過gid,找到該組的相關信息,并以group結構體返回其信息
頭文件:#include<grp.h> #include<sys/types.h>
函數原型?strcut group * getgrgid(gid_t gid)
參數 gid
返回值 group結構體 正常
NULL 無數據或發生錯誤
7 group結構體
struct group
{
char *gr_name; /*組名稱*/
char *gr_passwd; /* 組密碼*/
gid_t gr_gid; /*組識別碼*/
char **gr_mem; /*組成員賬號*/
}
?
轉載于:https://www.cnblogs.com/cation/archive/2013/01/29/2875311.html
總結
以上是生活随笔為你收集整理的UNIX-LINUX编程实践教程-第三章-实例代码注解-ls2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: netbeans字体与颜色配置模板相关网
- 下一篇: linux 其他常用命令