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相关推荐
- linux编程课后作业,Unix/Linux 编程实践教程第三章习题
tips: 答案仅供参考,不保证正确* 3.1 在我的 deepin 上,d_name 的长度是 256,有的系统定义成 1 是为了节省空间,使用时可以通过 malloc() 动态的分配空间,比如: ...
- stty详解-Unix/Linux编程实践教程第五章 学习stty
读书笔记-第五章 连接控制 学习stty 先放上思维导图 为设备编程&设备就像文件 前面所学的知识都是基于文件的,而在unix/linux系统中,所有的设备(打印机,终端,话筒,摄像头等等)也 ...
- 《Unix/linux编程实践教程》------重定向程序的I/O
<Unix/linux编程实践教程>书中举例命令more的用法: $more filename $command | more $more < filename 用法1直接显示fil ...
- Unix/Linux编程实践教程–书评
花了两个月的时间把这本书读完了,完成了一部分的课后习题. 总的来说,这是一本挺好的Unix\Linux编程的入门书(虽然书中的小错误一大堆),书的开始部分简要介绍了Unix系统编程,讲述了如何使用男人 ...
- linux pipe函数 重定向,I/O重定向和管道——《Unix/Linux编程实践教程》读书笔记(第10章)...
1.I/O重定向的概念与原因 及 标准输入.输出的标准错误的定义 所以的Unix I/O重定向都基于标准数据流的原理.三个数据了分别如下: 1)标准输入--需要处理的数据流 2)标准输出--结果数据流 ...
- 进程和程序:编写shell——《Unix/Linux编程实践教程》读书笔记(第8章)
2019独角兽企业重金招聘Python工程师标准>>> 1.Unix shell的功能 shell是一个管理进程和运行程序的程序.所有常用的shell都有3个主要功能: (1)运行程 ...
- unix/linux编程实践,Unix/Linux编程实践教程–cp在OS X的实现
环境:OS X10.12.4 书中的代码对于OS X是适用的.值得提一嘴的是,其实OS X的open是可以在文件不存在的时候自动创建的,man 2 open时,就可以看到这个说明. The oflag ...
- 学习Unix/Linux编程要学些什么
最近利用空余时间看了一下<Unix/Linux编程实践教程>,原书名为:Understanding Unix/Linux Programming: A Guide to Theory an ...
- Unix/Linux编程:进程间通信(IPC)总结
IPC工具分类 如上,Unix系统上IPC根据功能可以分为三类 通信:这些工具关注进程间的数据交换 同步:这些进程关注进程和线程操作之间的同步 信号:虽然信号的主要作用不为此,但是在特定场景下仍然可以 ...
最新文章
- SLAM-ch2-使用kdevelop创建helloWorld程序
- python实现vlookup功能_干货一:怎么在python里面实现vlookup
- canopy算法 java_mahout源码canopy算法分析之二CanopyMapper
- mysql优化说出九条_技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢?
- Java Radom类的使用方法实例
- 设计洪水位与校核洪水位
- fastjson的@JSONField注解
- bzoj1051: [HAOI2006]受欢迎的牛
- 拼图项目的动机和目标
- Android中的Handler机制
- 英语常见介词错误用法,你有犯过吗?
- 博士生找工作的真相!就问一声:你是否足够强大?
- 图片 button 去背景色_不会PS没关系,用Word更换证件照背景色只要10秒!
- 移动端小总结(1)---meta、input和单行多行文字溢出省略号
- winxp计算机语言改为英语,系统之家xp系统语言设置将英文版改为中文的方法
- 网络上的计算机无权限访问权限,权限,教您怎么解决无internet访问权限
- 用devc++表白_【吉利表白墙】19级倪yl,风吹起如花般破碎的流年,而你的笑容摇晃摇晃,成为我命途中最美的点缀...
- 使用echart的小指南
- iOS开发-集成一网通支付
- 八、血条的制作和boss敌人的产生(雷霆战机)
热门文章
- c 如何操作php,thinkphp的c方法使用示例
- android iOS 都精通,Android IOS开发要理解何为面向对象的思维
- java实验_Java实验报告(实验一)
- 剑指offer python实现_剑指Offer第2题详解(附Python、Java代码实现)
- 事业单位综合应用能力计算机,最新事业单位统考-综合应用能力C类梳理精华.pdf...
- micropython编译原理_C语言嵌入式Linux高级编程第9期:CPU和操作系统入门视频课程...
- 【JAVA基础篇】彻底搞懂拆箱装箱
- java string的作用_浅谈java String不可变的好处
- 判断按键值_Pygame(九)按键事件(2)
- 软件工程(Rational统一过程)