|
TOP
|
|
Linux 下几个文件操作命令的代码实现(四)
|
ntf(stderr,"open error %s \n",strerror(errno));
exit(1);
}
if(fstat(fd,fp)== -1){
fprintf(stderr,"fstat error %s \n",strerror(errno));
exit(2);
}
if(fp->st_size > (SIZE-1)){
fprintf(stderr,"buffer size is not big enough \n");
exit(3);
}
if(read(fd,buf,fp->st_size) == -1){
fprintf(stderr,"read error.\n");
exit(4);
}
p1=strchr(buf,NLINE);
p2=strrchr(buf,NLINE);
*p2='\0';
do{
p2=strrchr(buf,NLINE);
p4=p2;
p3=p2+sizeof(char);
printf("%s\n",p3);
*p4='\0';
}while(p2 != p1);
if(p2 == p1){
*p2 = '\0';
printf("%s\n",buf);
}
return 0;
}
|
让我们来运行一下该程序: 程序的运行情况如下,假设编译后的可执行文件名为 emulatetac,有一个文本文件 test.txt。 | # gcc emulatetac.c -o emulatetac
# cat test.txt
1
2
3
a
b
# ./emulatetac test.txt
b
a
3
2
1
|
可以看出文件内容以倒序方式显示输出了。 tac 命令实现的说明 下面逐行讲解: - #include 的头文件,都应该通过 man 2 系统调用命令来查找,这里就不多说了。
- 下面定义了一个宏常量 SIZE,该常量主要用来表示能够读入最大多少个字节的文件,当文件过大的时候程序就不执行,直接退出。然后定义了宏常量 NLINE 表示换行符'\n'。
- 接下来主程序体开始了:首先定义一个字符数组 buf,用来把读入文件的每个字节都存在该数组里面。
- 然后定义了 4 个字符串指针,一个指向结构体 struct stat 的指针 fp,一个文件描述符。
- 然后为指向结构体的指针 fp 分配存储空间。
- 接下来判断输入参数是否为 2 个,也就是命令本身和文件名。不是 2 个就直接退出。
- 然后以只读方式打开输入文件名的文件,也就是 test.txt。打开成功的话,把打开的文件赋值到文件描述符 fd 中,错误的话退出。
- 然后用 fstat 系统调用把文件描述符 fd 中对应文件的元信息,存放到结构体指针 fp 指向的结构中。
- 下面判断当文件的大小超过缓冲区数组 buf 的大小 SIZE-1 时,就退出。
- 下面将把文件 test.txt 中的每个字符存放到数组 buf 中。
- 下面是程序的核心部分:首先我们找到字符串 buf 中的第一个换行字符存放到 p1 指针里面,然后把最后一个换行字符置为字符串结束符。
- 接下来我们从后往前查找字符串 buf 中的换行符,直到遇到第一个换行符 p1。同时打印每个找到的换行符'\n'中的下一个字符开始的字符串,也就刚好是一行文本。
- 最后当从后向前找到第一个换行字符时,打印第一行,程序结束。
df 命令的实现 df 命令的模拟实现 通过 strace 命令查看 df 主要使用了如下的系统调用:open、fstat、read、statfs 我这里实际上是模拟实现的 df --block-size=4096 这个命令,也就是说以 4096 字节为块大小来显示磁盘使用情况。 这里最为关键的是 statfs 这个结构体,该结构体的某些字段被用作 df 命令的输出字段: | struct statfs {
long f_type; /* type of filesystem (see below) */
long f_bsize; /* optimal transfer block size */
long f_blocks; /* total data blocks in file system */
long f_bfree; /* free blocks in fs */
long f_bavail; /* free blocks avail to non-superuser */
long f_files; /* total file nodes in file system */
long f_ffree; /* free file nodes in fs */
fsid_t f_fsid; /* file system id */
long f_namelen; /* maximum length of filenames */
};
|
比如:df --block-size=4096 的输出如下(纵向列出): | Filesystem
/dev/sda1
4K-blocks
5077005 f_blocks 字段
Used
145105 f_blocks 字段 -f_bfree 字段
Available
4669841 f_bavail 字段
Use%
4% (f_blocks-f_bfree)/ f_blocks*100% 来计算磁盘使用率。
Mounted on
/
|
模拟实现的代码如下: 清单 5. 模拟实现代码
|
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/vfs.h>
#include <math.h>
#define SIZE1 100
#define FN "/etc/mtab"
#define SPACE ' '
int displayapartition(char * pt,char * pt1);
int main(void){
char tmpline[SIZE1];
FILE * fp;
char * pt1;
char * pt2;
char * pt3;
if( (fp = fopen(FN,"r")) == NULL ){
fprintf(stderr,"%s \n",strerror(errno));
exit(5);
}
while( fgets(tmpline, SIZE1, fp) != NULL ){
pt1=strchr(tmpline, SPACE);
pt2=pt1+sizeof(char);
*pt1='\0';
pt3=strchr(pt2,SPACE);
*pt3='\0';
if(strstr(tmpline,"/dev") != NULL ){
displayapartition(tmpline,pt2);
}
}
return 0;
}
int displayapartition(char * pt,char * pt1){
struct statfs buf;
statfs(pt1,&buf);
int usage;
usage=ceil((buf.f_blocks-buf.f_bfree)*100/buf.f_blocks);
printf("%s ",pt);
printf |
|