一:背景
看了unix/linux编程实践,跟着书上代码实现了普通文件的拷贝,看到课后习题后需要实现目录之间的拷贝,因此有了本文,我最初实现cp用了180多行代码,后来觉得很多地方可以封装,但是最后居然越封装越多达到了200多行,今晚果断再次封装,修剪了代码大概170多行,要比课后答案的要简便点。该cp可以实现普通文件的拷贝,拷贝到指定目录下,和目录直接拷贝等功能。
二:思路
目录之间的拷贝我觉得最主要的功能就是path路径的拼装,处理好path路径问题,就很简单了。例如 /root/a.txt 拷贝到 /tmp下,那么只要传入/root/a.txt 和 /tmp/a.txt即可,那么关键就是/tmp和a.txt的拼装,在拷贝到/tmp/下你也可以先判断下目标是否有相同文件存在。若存在可以提示用户是否覆盖(这个功能我还没做)。这里主要还是字符串处理函数用的比较多,还有一个就是函数返回值得一个难点(下篇博文介绍下函数返回值)。
将C语言梳理一下,分布在以下10个章节中:
三:实现
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFERSIZE 4096
#define COPYMODE 0644
char *deal_path(char *,char *);
char *deal_path1(char *,struct dirent *);
int is_file(char *);
char *deal_with(char *,char *);
void oops(char *,char *);
int exists(char *);
void do_cp(char *,char *);
int main(int argc,char *argv[])
{
char answer[10];
char c;
//设置buf
struct stat filebuf1;
struct stat filebuf2;
struct stat tmpbuf;
char *filename=NULL;
char *filename2=NULL;
struct dirent *dirname;
DIR *dir_ptr;
//判断参数
if(argc != 3){
fprintf(stderr,"Usage: %s source destination\n",*argv);
exit(1);
}
//判断源文件和目标文件是否相等
if(strcmp(argv[1],argv[2]) == 0)
{
fprintf(stderr,"No Copy Source File equal Dest File\n");
exit(1);
}
//测试文件是否可以访问
if(access(argv[2],F_OK) == 0){
//询问文件是否可以覆盖
printf("Can you ovver the file (y/n):");
scanf("%9s",&answer);
while((c = getchar()) != EOF && c != '\n');
}
//判断用户的输入
if(*answer != 'y' && *answer != 'Y'){
fprintf(stderr,"the dst file exists,don't over\n");
exit(1);
}
//判断目标是否是目录
stat(argv[2],&filebuf2);
stat(argv[1],&filebuf1);
if(!S_ISDIR(filebuf1.st_mode)){
if(S_ISDIR(filebuf2.st_mode))
filename = deal_path(argv[2],argv[1]);
else
filename = argv[2];
// printf("%s\n",filename);
do_cp(argv[1],filename);
free(filename);
}
else{
if(S_ISDIR(filebuf2.st_mode))
if((dir_ptr = opendir(argv[1])) == NULL)
sprintf("stderr","Can't open dir %s\n",argv[1]);
else
while((dirname=readdir(dir_ptr)) != NULL){
filename = deal_path(argv[1],dirname->d_name);
if(is_file(filename)){
filename2 = deal_with(filename,argv[2]);
do_cp(filename,filename2);
free(filename);
free(filename2);
}else{
free(filename);
continue;
}
}
}
closedir(dir_ptr);
}
void do_cp(char *path1,char *path2)
{
int in_fd,out_fd,n_chars;
char buf[BUFFERSIZE];
if((in_fd = open(path1,O_RDONLY)) == -1)
oops("Cannot open",path1);
if((out_fd = open(path2,O_WRONLY|O_CREAT,COPYMODE)) == -1)
oops("Cannot create",path2);
//开始读取
while((n_chars = read(in_fd,buf,BUFFERSIZE)) > 0)
if(write(out_fd,buf,n_chars) != n_chars)
oops("Write error to",path2);
//判断最后是否写入
if(n_chars == -1)
oops("Read error from,path