#include <dirent.h> #include <stdio.h> #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #define BUFFER_SIZE 1024 /* 每次读写缓存大小,影响运行效率 */ #define _LARRGEFILE_SOURCE #define _LARRGEFILE64_SOURCE #define _FILE_OFFSET_BITS 64 #define OFFSET 10240 /* 复制的数据大小 */ int cp_dir(const char *src,const char*dst); int cp_file(char * src1,char *dst2,mode_t mode); int main(int argc,char *argv[]) { struct stat stat_src; if(argc<3) { fprintf(stderr,"usage %s src_dir dsr_src\n",argv[0]); exit(EXIT_FAILURE); } if(stat(argv[1],&stat_src)!=0)//获得源文件属性 { fprintf(stderr,"%s(%d):stat error(%s)!\n", (char *)__FILE__,__LINE__,(char *)strerror(errno)); exit(EXIT_FAILURE); } umask(0000); if(S_ISREG(stat_src.st_mode))//如果为普通文件 { struct stat stat_dst; if(stat(argv[2],&stat_dst)==-1)//读取目标文件属性 { if(errno!=ENOENT) { fprintf(stderr,"%s(%d):stat error(%s)!\n", (char *)__FILE__,__LINE__,(char *)strerror(errno)); exit(EXIT_FAILURE); } else { cp_file(argv[1],argv[2],stat_src.st_mode);//复制文件 } } else { if(S_ISDIR(stat_dst.st_mode))//如果目标是目录 { char *ptr=(char*)malloc(strlen(argv[2])+1+strlen(argv[1])+1);//分配内存 sprintf(ptr,"%s/%s\0",argv[2],argv[1]); cp_file(argv[1],ptr,stat_src.st_mode); } else { printf("file %s exit,do you want over want overwrite it[y/n]",argv[2]); char ch; while(!scanf("%c",&ch)) { getchar(); } if(ch=='Y'||ch=='y')//y就拷贝文件 { unlink(argv[2]); cp_file(argv[1],argv[2],stat_src.st_mode); } else return 1; } } } else if(S_ISDIR(stat_src.st_mode))//如果源文件是目录 { struct stat stat_dst; if(stat(argv[2],&stat_dst)==-1)//读取目标文件属性 { if(errno!=ENOENT) { fprintf(stderr,"%s(%d):stat error(%s)!\n", (char *)__FILE__,__LINE__,(char *)strerror(errno)); exit(EXIT_FAILURE); } else { errno=0; if(-1==mkdir(argv[2],stat_src.st_mode))//创建目标目录 { perror("mkdir1"); exit(EXIT_FAILURE); } cp_dir(argv[1],argv[2]);//复制目录 } } else if(S_ISREG(stat_dst.st_mode)) { fprintf(stderr,"cant copy a dir to a file \n"); exit(EXIT_FAILURE); } else { char *ptr=(char *)malloc(strlen(argv[1])+1+strlen(argv[2])+1); sprintf(ptr,"%s /%s\0",argv[2],argv[1]); if(-1==mkdir(ptr,stat_src.st_mode)) { perror("mkdir2"); exit(EXIT_FAILURE); } cp_dir(argv[1],ptr); free(ptr); } } } int cp_dir(const char *src,const char*dst) { DIR *dirp=NULL; if(NULL==(dirp=opendir(src))) { perror("opendir"); exit(EXIT_FAILURE); } struct dirent *entp=NULL; while(NULL !=(entp=readdir(dirp)))//读取目录 内容 { if(strcmp(entp->d_name,"..")==0||strcmp(entp->d_name,".")==0) //如果当前 目录和上级目录,忽略 { continue; } char * name_src=(char *)malloc(strlen(src)+1+strlen(entp->d_name)+1); sprintf(name_src,"%s/%s\0",src,entp->d_name); char *name_dst= (char *)malloc(strlen(dst)+1+strlen(entp->d_name)+1); sprintf(name_dst,"%s/%s\0",dst,entp->d_name); struct stat stat_src; if(stat(name_src,&stat_src)==-1)//读取源文件属性 { fprintf(stderr,"%s(%d):stat error(%s)!\n",__FILE__,__LINE__,strerror(errno)); exit(EXIT_FAILURE); } if(S_ISREG(stat_src.st_mode))//普通文件 { cp_file(name_src,name_dst,stat_src.st_mode); free(name_src); free(name_dst); } else if(S_ISDIR(stat_src.st_mode))//是目录 { if(-1==mkdir(name_dst,stat_src.st_mode)) { perror("mkdir3"); exit(EXIT_FAILURE); } cp_dir(name_src,name_dst); free(name_dst); free(name_src); } } } int cp_file(char * src1,char *dst2,mode_t mode) { int src_file, dest_file; unsigned char buff[BUFFER_SIZE]; int real_read_len; /* 以只读方式打开源文件 */ src_file = open(src1, O_RDONLY); /* 以只写方式打开目标文件,若此文件不存在则创建该文件,访问权限值为644 */ dest_file = open(dst2, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if(src_file < 0 || dest_file < 0) { printf("Open file error\n"); exit(1); } /* 读取源文件的数据并写到目标文件中,每次读写1KB */ do { real_read_len = read(src_file, buff,BUFFER_SIZE); write(dest_file, buff, real_read_len); }while(real_read_len==BUFFER_SIZE); close(dest_file); close(src_file); return 0; }