需求内容:
编写一个类似于cp命令的程序,当使用该程序复制一个包含空洞(连续的空字节)的普通文件时,要求目标文件的空洞与源文件保持一致。
测试一:普通文件的复制
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/epoll.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d $$ " format "\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
#define printable(ch) (isprint((unsigned char)ch)?ch:'#')
#define MAX_BUF 1024
int my_cp(int argc, char *argv[]){
char buf[MAX_BUF + 1];
for(int i = 0; i < argc; i++){
printf("%s,",argv[i]);
}
printf("\n");
if(argc < 3){
printf("Usage: %s <src_file> <dst_file>\n");
return 0;
}
char *src_file = argv[1];
char *dst_file = argv[2];
int fd1 = open(src_file,O_RDONLY);
if(fd1 < 0){
perror("open1");
return -1;
}
DEBUG_INFO("open %s ok\n", src_file);
int fd2 = open(dst_file,O_WRONLY | O_TRUNC | O_CREAT,0666);
if(fd2 < 0){
perror("open2");
return -2;
}
DEBUG_INFO("open %s ok\n", dst_file);
while(1){
memset(buf,0,sizeof(buf));
int len = read(fd1,buf,MAX_BUF);
if(len <= 0){
break;
}
write(fd2,buf,len);
}
DEBUG_INFO("bye bye");
close(fd1);
close(fd2);
return 0;
}
int main(int argc, char *argv[])
{
my_cp(argc,argv);
return 0;
}
实验
创建源文件
$ echo "hello world" > hello.txt
执行测试程序生成world.txt
./_build_/cp1 hello.txt world.txt
读取world.txt文件内容
$ cat world.txt
hello world
测试二:制作空洞文件
文件命名cp2.txt,制作一个带空洞的文件black_hole.txt,文件开头是字符串begin,尾巴是字符串end。中间是空洞,总计大小是100。
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/epoll.h>
#define _DEBUG_INFO
#ifdef _DEBUG_INFO
#define DEBUG_INFO(format, ...) printf("%s:%s:%d $$ " format "\n" \
,__FILE__,__func__,__LINE__ \
, ##__VA_ARGS__)
#else
#define DEBUG_INFO(format, ...)
#endif
#define printable(ch) (isprint((unsigned char)ch)?ch:'#')
#define MAX_BUF 1024
int create_black_hole_file(char *name){
int fd = open(name,O_CREAT | O_RDWR | O_TRUNC,0666);
if(fd < 0){
perror("open");
return -1;
}
DEBUG_INFO("open %s ok",name);
DEBUG_INFO("cur pos:%d",lseek(fd,0,SEEK_CUR));
write(fd,"begin",sizeof("begin"));
DEBUG_INFO("cur pos:%d",lseek(fd,0,SEEK_CUR));
DEBUG_INFO("%d",lseek(fd,100-sizeof("begin") - sizeof("end"),SEEK_END));
write(fd,"end",sizeof("end"));
DEBUG_INFO("cur pos:%d",lseek(fd,0,SEEK_CUR));
close(fd);
return 0;
}
int main(int argc, char *argv[])
{
create_black_hole_file("black_hole.txt");
return 0;
}
执行测试文件,生成black_hole.txt文件,大小是100
$ ls -lshF black_hole.txt
4.0K -rw-rw-r-- 1 lkmao lkmao 100 6月 28 15:08 black_hole.txt
复制黑洞文件并验证
用测试1的测试程序复制这个空洞文件,看看会有什么现象。
./_build_/cp1 black_hole.txt other_black_hole.txt
如下所示:好美没啥问题,大小没错,使用diff比较一下。
$ ls -lsh other_black_hole.txt
4.0K -rw-rw-r-- 1 lkmao lkmao 100 6月 28 15:16 other_black_hole.txt
使用diff比较,如下所示 ,零输出,这应该是相同的意思吧
对比md5值
复制链接文件并验证
创建一个软链接
$ ln -s black_hole.txt ln.txt
$ ls -lsh ln.txt
0 lrwxrwxrwx 1 lkmao lkmao 14 6月 28 15:25 ln.txt -> black_hole.txt
$
通过软链接复制:
./_build_/cp1 ln.txt other_ln.txt
查看结果:
$ ls -lsh ln.txt other_ln.txt
0 lrwxrwxrwx 1 lkmao lkmao 14 6月 28 15:25 ln.txt -> black_hole.txt
4.0K -rw-rw-r-- 1 lkmao lkmao 100 6月 28 15:27 other_ln.txt
好像也没问题。
$ md5sum other_ln.txt
9253ef3823d27b6c854b26fe65a0aee6 other_ln.txt
$
小结
原来还以为有多难呢,真是,哎。