linux 实现cp命令递归复制
1 #include<func.h> 2 3 #define LENGTH 4096 4 5 int DFS_copy(char* path1, char* path2); //递归复制 6 7 int main(int argc, char* argv[]) { 8 ARGS_CHECK(argc, 3); //检查参数是否错误 9 10 struct stat statbuf; 11 stat(argv[1], &statbuf); 12 if (S_ISDIR(statbuf.st_mode)) { //若参数1是目录,直接进行递归 13 DFS_copy(argv[1], argv[2]); 14 15 } 16 else { //否则参数1就是普通文件 17 stat(argv[2], &statbuf); 18 if (S_ISDIR(statbuf.st_mode)) { //若参数2是目录 19 char newpath1[1024] = { 0 }; 20 char newpath2[1024] = { 0 }; 21 sprintf(newpath1, "%s", argv[1]);//重建待复制的源文件的地址 22 sprintf(newpath2, "%s%s%s", argv[2], "/", argv[1]);//重建目的文件的地址 23 24 int fdr = open(newpath1, O_RDONLY); //只读方式打开源文件 25 ERROR_CHECK(fdr, -1, "open fdr"); 26 int fdw = open(newpath2, O_WRONLY | O_CREAT | O_TRUNC, 0666);//只写方式打开目的文件,若不存在就创建,给予权限0666 27 ERROR_CHECK(fdw, -1, "open fdw"); 28 char buf[4096] = { 0 }; //数据缓存 29 while (1) { 30 memset(buf, 0, sizeof(buf)); //每次清空内容 31 int ret = read(fdr, buf, sizeof(buf)); //读内容,返回成功读到的字节数 32 if (ret == 0) { 33 break; 34 } 35 write(fdw, buf, ret); //写入到目的文件 36 } 37 close(fdr); //关闭文件 38 close(fdw); 39 } 40 else { //若参数2是普通文件,则就是两个普通文件的复制 41 int fdr = open(argv[1], O_RDONLY); //只读方式打开源文件 42 ERROR_CHECK(fdr, -1, "open fdr"); 43 int fdw = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);//只写方式打开目的文件,若不存在就创建,给予权限0666 44 ERROR_CHECK(fdw, -1, "open fdw"); 45 char buf[4096] = { 0 }; //数据缓存 46 while (1) { 47 memset(buf, 0, sizeof(buf)); //每次清空内容 48 int ret = read(fdr, buf, sizeof(buf)); //读内容,返回成功读到的字节数 49 if (ret == 0) { 50 break; 51 } 52 write(fdw, buf, ret); //写入到目的文件 53 } 54 close(fdr); //关闭文件 55 close(fdw); 56 } 57 58 } 59 60 return 0; 61 } 62 63 int DFS_copy(char* path1, char* path2) { 64 DIR* pdir1 = opendir(path1); //打开源目录流 65 ERROR_CHECK(pdir1, NULL, "opendir1"); //检查返回值是否出错 66 if (NULL == opendir(path2)) { //打开目的文件的目录流,若不是目录就创建文件夹 67 int ret = mkdir(path2, 0777); //创建目的文件夹 68 ERROR_CHECK(ret, -1, "mkdir"); 69 } 70 DIR* pdir2 = opendir(path2); //打开目的文件夹的目录流 71 ERROR_CHECK(pdir2, NULL, "opendir2"); //检查返回值是否出错 72 struct dirent* pdirent; //存储目录项信息 73 while ((pdirent = readdir(pdir1)) != NULL) { //遍历所有目录项 74 //过滤.和..目录,不然复制的时候会死循环 75 if (strcmp(pdirent->d_name, ".") == 0 || strcmp(pdirent->d_name, "..") == 0) { 76 continue; 77 } 78 79 char newpath1[1024] = { 0 }; 80 char newpath2[1024] = { 0 }; 81 sprintf(newpath1, "%s%s%s", path1, "/", pdirent->d_name);//重建待复制的源文件的地址 82 sprintf(newpath2, "%s%s%s", path2, "/", pdirent->d_name);//重建目的文件的地址 83 if (pdirent->d_type == DT_DIR) { //判断当前目录项是否是个目录 84 DFS_copy(newpath1, newpath2); //是目录就进行递归复制 85 } 86 else { //不是目录就直接复制 87 //------------------read/write方式复制文件------------------ 88 // int fdr = open(newpath1, O_RDONLY); //只读方式打开源文件 89 // ERROR_CHECK(fdr, -1, "open fdr"); 90 // int fdw = open(newpath2, O_WRONLY | O_CREAT | O_TRUNC, 0666);//只写方式打开目的文件,若不存在就创建,给予权限0666 91 // ERROR_CHECK(fdw, -1, "open fdw"); 92 // char buf[4096] = { 0 }; //数据缓存 93 // while (1) { 94 // memset(buf, 0, sizeof(buf)); //每次清空内容 95 // int ret = read(fdr, buf, sizeof(buf)); //读内容,返回成功读到的字节数 96 // if (ret == 0) { 97 // break; 98 // } 99 // write(fdw, buf, ret); //写入到目的文件 100 // } 101 // close(fdr); //关闭文件 102 // close(fdw); 103 //-------------------------------------------------------- 104 //------------------mmap方式复制文件----------------------- 105 int fdr = open(newpath1, O_RDONLY); 106 ERROR_CHECK(fdr, -1, "open fdr"); 107 int fdw = open(newpath2, O_RDWR | O_CREAT | O_TRUNC, 0666); 108 ERROR_CHECK(fdw, -1, "open fdw"); 109 110 struct stat statbuf; 111 fstat(fdr, &statbuf); //和stat函数一样,只是参数变为文件描述符 112 ftruncate(fdw, statbuf.st_size); 113 off_t fsize = 0; 114 int cp_size; 115 while (fsize < statbuf.st_size) { 116 if (statbuf.st_size - fsize >= LENGTH) { 117 cp_size = LENGTH; 118 } 119 else { 120 cp_size = statbuf.st_size - fsize; 121 } 122 123 char* src = (char*)mmap(NULL, cp_size, PROT_READ, MAP_SHARED, fdr, fsize); 124 ERROR_CHECK(src, MAP_FAILED, "mmap"); 125 126 char* dest = (char*)mmap(NULL, cp_size, PROT_WRITE | PROT_READ, MAP_SHARED, fdw, fsize); 127 ERROR_CHECK(dest, MAP_FAILED, "mmap"); 128 129 memcpy(dest, src, cp_size); 130 // for(int i = 0; i < cp_size; i++){ //另一种转移数据的方式 131 // dest[i] = src[i]; 132 // } 133 munmap(src, cp_size); 134 munmap(dest, cp_size); 135 fsize += cp_size; 136 } 137 138 //-------------------------------------------------------- 139 } 140 } 141 closedir(pdir1); //关闭目录流 142 closedir(pdir2); 143 return 0; 144 }