teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

追加

2016/08/29 02:35

投稿

A.Ichi
A.Ichi

スコア4070

answer CHANGED
@@ -6,4 +6,205 @@
6
6
  ・実行結果からおおその動きが分かりますので、さらにファイルをcpする際に必要そうな値の場所にもprintf文を入れます。
7
7
  ・cpに必要な情報が揃ったところで、次にdirとfileかを判断してる箇所に、ディレクトリ作成、ファイルのコピーを行うサブルーチンを加えます。(mkdirやcpはソースを持って来てサブルーチン化します。)
8
8
 
9
- プログラムを修正する場合、こんな感じでやっております。
9
+ プログラムを修正する場合、こんな感じでやっております。
10
+
11
+ サンプルですのでご参考としてください。
12
+ ```c
13
+ #include <stdio.h>
14
+ #include <stdlib.h>
15
+ #include <string.h>
16
+ #include <unistd.h>
17
+ #include <dirent.h>
18
+ #include <sys/types.h>
19
+ #include <sys/stat.h>
20
+ #include <errno.h>
21
+
22
+ struct strbuf {
23
+ char *ptr;
24
+ size_t len;
25
+ };
26
+
27
+ void traverse(struct strbuf *buf);
28
+ void traverseSub(struct strbuf *buf, int first);
29
+ struct strbuf *strbuf_new(void);
30
+ void strbuf_realloc(struct strbuf *buf, size_t size);
31
+
32
+ void print_error(char *s){
33
+ fprintf(stderr, "%s: %s\n", s, strerror(errno));
34
+ }
35
+
36
+ void die (const char *s){
37
+ perror(s);
38
+ exit(1);
39
+ }
40
+
41
+ char dir1[256];
42
+ char dir2[256];
43
+
44
+ int ccp(char *frfile,char *tofile)
45
+ {
46
+ FILE* fpSrc;
47
+ FILE* fpDest;
48
+ char c;
49
+
50
+ fpSrc = fopen( frfile, "rb" );
51
+ if( fpSrc == NULL ){
52
+ exit( EXIT_FAILURE );
53
+ }
54
+
55
+ fpDest = fopen( tofile, "wb" );
56
+ if( fpDest == NULL ){
57
+ exit( EXIT_FAILURE );
58
+ }
59
+
60
+ while( 1 ){
61
+ /* バイナリデータとして 1Byteずつ読み込み、1Byteずつ書き込む */
62
+ fread( &c, sizeof(c), 1, fpSrc );
63
+ if( feof( fpSrc ) ){
64
+ break;
65
+ }
66
+ if( ferror( fpSrc ) ){
67
+ exit( EXIT_FAILURE );
68
+ }
69
+ fwrite( &c, sizeof(c), 1, fpDest );
70
+ }
71
+
72
+ if( fclose( fpDest ) == EOF ){
73
+ fputs( "ファイルクローズに失敗しました。\n", stderr );
74
+ exit( EXIT_FAILURE );
75
+ }
76
+ if( fclose( fpSrc ) == EOF ){
77
+ fputs( "ファイルクローズに失敗しました。\n", stderr );
78
+ exit( EXIT_FAILURE );
79
+ }
80
+ return 0;
81
+ }
82
+
83
+ int main(int argc, char *argv[]){
84
+ struct strbuf *pathbuf;
85
+
86
+ if(argc != 3){
87
+ fprintf(stderr, "Usage:cpdir dir1 dir2\n");
88
+ exit(1);
89
+ }
90
+ pathbuf = strbuf_new();
91
+ strbuf_realloc(pathbuf, strlen(argv[1]));
92
+ strcpy(pathbuf->ptr, argv[1]);
93
+ strcpy(dir1, argv[1]);
94
+ strcpy(dir2, argv[2]);
95
+ traverse(pathbuf);
96
+ exit(0);
97
+ }
98
+
99
+ void traverse(struct strbuf *pathbuf){
100
+ traverseSub(pathbuf, 1);
101
+ }
102
+
103
+ void traverseSub(struct strbuf *pathbuf, int first){
104
+ DIR *d;
105
+ struct dirent *ent;
106
+ struct stat st;
107
+ char to_name[2048];
108
+
109
+ // printf("traverseSub S\n");
110
+ if (first){
111
+ strcpy(to_name,dir2);
112
+ }else{
113
+ strcpy(to_name,dir2);
114
+ strcpy(to_name+strlen(dir2),pathbuf->ptr+strlen(dir1));
115
+ }
116
+
117
+ d = opendir(pathbuf->ptr);
118
+ if (!d) {
119
+ switch (errno){
120
+ case ENOTDIR:
121
+ return;
122
+ case ENOENT:
123
+ if(first){
124
+ die(pathbuf->ptr);
125
+ } else {
126
+ return;
127
+ }
128
+ case EACCES:
129
+ puts(pathbuf->ptr);
130
+ print_error(pathbuf->ptr);
131
+ return;
132
+ default:
133
+ perror(pathbuf->ptr);
134
+ exit(1);
135
+ }
136
+ }
137
+ //printf("Dir:%s \n", pathbuf->ptr);
138
+ //printf("Dir2:%s \n", to_name);
139
+ puts(pathbuf->ptr);
140
+ if (mkdir(to_name,0755) == 0){
141
+ printf("%s mkdir\n", to_name);
142
+ }
143
+ while(ent = readdir(d)){
144
+ if(strcmp(ent->d_name, ".") == 0)
145
+ continue;
146
+ if(strcmp(ent->d_name, "..") == 0)
147
+ continue;
148
+ strbuf_realloc(pathbuf, pathbuf->len + 1 + strlen(ent->d_name) + 1);
149
+ // special handling for the root directory
150
+ if(strcmp(pathbuf->ptr, "/") != 0){
151
+ strcat(pathbuf->ptr, "/");
152
+ }
153
+ strcat(pathbuf->ptr, ent->d_name);
154
+ if(lstat(pathbuf->ptr, &st) < 0){
155
+ switch (errno){
156
+ case ENOENT:
157
+ break;
158
+ case EACCES:
159
+ print_error(pathbuf->ptr);
160
+ break;
161
+ default:
162
+ die(pathbuf->ptr);
163
+ }
164
+ } else {
165
+ if (S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) {
166
+ traverseSub(pathbuf, 0);
167
+ } else {
168
+ puts(pathbuf->ptr);
169
+ strcpy(to_name,dir2);
170
+ strcpy(to_name+strlen(dir2),pathbuf->ptr+strlen(dir1));
171
+ if (ccp(pathbuf->ptr, to_name)){
172
+ printf("File:%s\n",to_name);
173
+ }
174
+ }
175
+ }
176
+ *strrchr(pathbuf->ptr, '/') = '\0';
177
+ }
178
+ closedir(d);
179
+ //printf("traverseSub E\n");
180
+ }
181
+ #define INITLEN 1024
182
+
183
+ struct strbuf * strbuf_new(void){
184
+ struct strbuf *buf;
185
+
186
+ buf = (struct strbuf*)malloc(sizeof(struct strbuf));
187
+ if (!buf) {
188
+ die("malloc(3)");
189
+ }
190
+ buf->ptr = malloc(INITLEN);
191
+ if(!buf->ptr){
192
+ die("malloc(3)");
193
+ }
194
+ buf->len = INITLEN;
195
+ return buf;
196
+ }
197
+
198
+ void strbuf_realloc(struct strbuf *buf, size_t len){
199
+ char *tmp;
200
+
201
+ if(buf->len > len)
202
+ return;
203
+ tmp = realloc(buf->ptr, len);
204
+ if (!tmp) {
205
+ die("realloc(3)");
206
+ }
207
+ buf->ptr = tmp;
208
+ buf->len = len;
209
+ }
210
+ ```