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 }