aboutsummaryrefslogtreecommitdiff
path: root/cp_mv.c
diff options
context:
space:
mode:
Diffstat (limited to 'cp_mv.c')
-rw-r--r--cp_mv.c359
1 files changed, 174 insertions, 185 deletions
diff --git a/cp_mv.c b/cp_mv.c
index 2ba8662b9..33adf8f55 100644
--- a/cp_mv.c
+++ b/cp_mv.c
@@ -1,3 +1,4 @@
1/* vi: set sw=4 ts=4: */
1/* 2/*
2 * Mini `cp' and `mv' implementation for BusyBox. 3 * Mini `cp' and `mv' implementation for BusyBox.
3 * 4 *
@@ -39,217 +40,205 @@
39 40
40#define is_cp 0 41#define is_cp 0
41#define is_mv 1 42#define is_mv 1
42static const char *dz; /* dollar zero, .bss */ 43static const char *dz; /* dollar zero, .bss */
43static int dz_i; /* index, .bss */ 44static int dz_i; /* index, .bss */
44static const char *cp_mv_usage[] = /* .rodata */ 45static const char *cp_mv_usage[] = /* .rodata */
45{ 46{
46 "cp [OPTION]... SOURCE DEST\n" 47 "cp [OPTION]... SOURCE DEST\n"
47 " or: cp [OPTION]... SOURCE... DIRECTORY\n\n" 48 " or: cp [OPTION]... SOURCE... DIRECTORY\n\n"
48 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" 49 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n"
49 "\n" 50 "\n"
50 "\t-a\tsame as -dpR\n" 51 "\t-a\tsame as -dpR\n"
51 "\t-d\tpreserve links\n" 52 "\t-d\tpreserve links\n"
52 "\t-p\tpreserve file attributes if possible\n" 53 "\t-p\tpreserve file attributes if possible\n"
53 "\t-R\tcopy directories recursively\n" 54 "\t-R\tcopy directories recursively\n",
54 , 55 "mv SOURCE DEST\n"
55 "mv SOURCE DEST\n" 56 " or: mv SOURCE... DIRECTORY\n\n"
56 " or: mv SOURCE... DIRECTORY\n\n" 57 "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n"
57 "Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n" 58 "Warning!! This is not GNU `mv'. It does not preserve hard links.\n"
58 "Warning!! This is not GNU `mv'. It does not preserve hard links.\n"
59}; 59};
60 60
61extern int cp_mv_main(int argc, char **argv) 61extern int cp_mv_main(int argc, char **argv)
62{ 62{
63 __label__ name_too_long__exit; 63 __label__ name_too_long__exit;
64 __label__ exit_false; 64 __label__ exit_false;
65 65
66 int recursiveFlag; 66 int recursiveFlag;
67 int followLinks; 67 int followLinks;
68 int preserveFlag; 68 int preserveFlag;
69
70 const char *baseSrcName;
71 int srcDirFlag;
72
73 char baseDestName[PATH_MAX + 1];
74 size_t baseDestLen;
75 int destDirFlag;
76
77 void fill_baseDest_buf(char *_buf, size_t * _buflen) {
78 const char *srcBasename;
79 if ((srcBasename = strrchr(baseSrcName, '/')) == NULL) {
80 srcBasename = baseSrcName;
81 if (_buf[*_buflen - 1] != '/') {
82 if (++(*_buflen) > PATH_MAX)
83 goto name_too_long__exit;
84 strcat(_buf, "/");
85 }
86 }
87 if (*_buflen + strlen(srcBasename) > PATH_MAX)
88 goto name_too_long__exit;
89 strcat(_buf, srcBasename);
90 return;
91 }
69 92
70 const char *baseSrcName; 93 int fileAction(const char *fileName, struct stat *statbuf) {
71 int srcDirFlag; 94 __label__ return_false;
95 char destName[PATH_MAX + 1];
96 size_t destLen;
97 const char *srcBasename;
98
99 strcpy(destName, baseDestName);
100 destLen = strlen(destName);
101
102 if (srcDirFlag == TRUE) {
103 if (recursiveFlag == FALSE) {
104 fprintf(stderr, omitting_directory, "cp", baseSrcName);
105 return TRUE;
106 }
107 srcBasename = (strstr(fileName, baseSrcName)
108 + strlen(baseSrcName));
109
110 if (destLen + strlen(srcBasename) > PATH_MAX) {
111 fprintf(stderr, name_too_long, "cp");
112 goto return_false;
113 }
114 strcat(destName, srcBasename);
115 } else if (destDirFlag == TRUE) {
116 fill_baseDest_buf(&destName[0], &destLen);
117 } else {
118 srcBasename = baseSrcName;
119 }
120 return copyFile(fileName, destName, preserveFlag, followLinks);
72 121
73 char baseDestName[PATH_MAX + 1]; 122 return_false:
74 size_t baseDestLen; 123 return FALSE;
75 int destDirFlag; 124 }
76 125
77 void fill_baseDest_buf(char *_buf, size_t *_buflen) 126 int rmfileAction(const char *fileName, struct stat *statbuf) {
78 { 127 if (unlink(fileName) < 0) {
79 const char *srcBasename; 128 perror(fileName);
80 if ((srcBasename = strrchr(baseSrcName, '/')) == NULL) 129 return FALSE;
81 {
82 srcBasename = baseSrcName;
83 if (_buf[*_buflen - 1] != '/')
84 {
85 if (++(*_buflen) > PATH_MAX)
86 goto name_too_long__exit;
87 strcat(_buf, "/");
88 } 130 }
89 } 131 return TRUE;
90 if (*_buflen + strlen(srcBasename) > PATH_MAX)
91 goto name_too_long__exit;
92 strcat(_buf, srcBasename);
93 return;
94 } 132 }
95 133
96 int fileAction(const char *fileName, struct stat *statbuf) 134 int rmdirAction(const char *fileName, struct stat *statbuf) {
97 { 135 if (rmdir(fileName) < 0) {
98 __label__ return_false; 136 perror(fileName);
99 char destName[PATH_MAX + 1]; 137 return FALSE;
100 size_t destLen;
101 const char *srcBasename;
102
103 strcpy(destName, baseDestName);
104 destLen = strlen(destName);
105
106 if (srcDirFlag == TRUE)
107 {
108 if (recursiveFlag == FALSE)
109 {
110 fprintf(stderr, omitting_directory, "cp", baseSrcName);
111 return TRUE;
112 }
113 srcBasename = (strstr(fileName, baseSrcName)
114 + strlen(baseSrcName));
115 if (destLen + strlen(srcBasename) > PATH_MAX)
116 {
117 fprintf(stderr, name_too_long, "cp");
118 goto return_false;
119 } 138 }
120 strcat(destName, srcBasename); 139 return TRUE;
121 }
122 else if (destDirFlag == TRUE)
123 {
124 fill_baseDest_buf(&destName[0], &destLen);
125 }
126 else
127 {
128 srcBasename = baseSrcName;
129 }
130 return copyFile(fileName, destName, preserveFlag, followLinks);
131
132 return_false:
133 return FALSE;
134 } 140 }
135 141
136 int rmfileAction(const char *fileName, struct stat* statbuf) 142 if ((dz = strrchr(*argv, '/')) == NULL)
137 { 143 dz = *argv;
138 if (unlink(fileName) < 0 ) { 144 else
139 perror(fileName); 145 dz++;
140 return FALSE; 146 if (*dz == 'c' && *(dz + 1) == 'p')
141 } 147 dz_i = is_cp;
142 return TRUE; 148 else
143 } 149 dz_i = is_mv;
144 150 if (argc < 3)
145 int rmdirAction(const char *fileName, struct stat* statbuf) 151 usage(cp_mv_usage[dz_i]);
146 { 152 argc--;
147 if (rmdir(fileName) < 0 ) { 153 argv++;
148 perror(fileName); 154
149 return FALSE; 155 if (dz_i == is_cp) {
150 } 156 recursiveFlag = preserveFlag = FALSE;
151 return TRUE; 157 followLinks = TRUE;
152 } 158 while (**argv == '-') {
153 159 while (*++(*argv)) {
154 if ((dz = strrchr(*argv, '/')) == NULL) dz = *argv; else dz++; 160 switch (**argv) {
155 if (*dz == 'c' && *(dz + 1) == 'p') dz_i = is_cp; else dz_i = is_mv; 161 case 'a':
156 if (argc < 3) usage(cp_mv_usage[dz_i]); 162 followLinks = FALSE;
157 argc--; 163 preserveFlag = TRUE;
158 argv++; 164 recursiveFlag = TRUE;
159 165 break;
160 if (dz_i == is_cp) 166 case 'd':
161 { 167 followLinks = FALSE;
162 recursiveFlag = preserveFlag = FALSE; 168 break;
163 followLinks = TRUE; 169 case 'p':
164 while (**argv == '-') 170 preserveFlag = TRUE;
165 { 171 break;
166 while (*++(*argv)) 172 case 'R':
167 { 173 recursiveFlag = TRUE;
168 switch (**argv) 174 break;
169 { 175 default:
170 case 'a': 176 usage(cp_mv_usage[is_cp]);
171 followLinks = FALSE; 177 }
172 preserveFlag = TRUE; 178 }
173 recursiveFlag = TRUE; 179 argc--;
174 break; 180 argv++;
175 case 'd':
176 followLinks = FALSE;
177 break;
178 case 'p':
179 preserveFlag = TRUE;
180 break;
181 case 'R':
182 recursiveFlag = TRUE;
183 break;
184 default:
185 usage(cp_mv_usage[is_cp]);
186 } 181 }
187 } 182 } else { /* (dz_i == is_mv) */
188 argc--;
189 argv++;
190 }
191 }
192 else /* (dz_i == is_mv) */
193 {
194 recursiveFlag = preserveFlag = TRUE;
195 followLinks = FALSE;
196 }
197 183
198 if (strlen(argv[argc - 1]) > PATH_MAX) 184 recursiveFlag = preserveFlag = TRUE;
199 { 185 followLinks = FALSE;
200 fprintf(stderr, name_too_long, "cp"); 186 }
201 goto exit_false;
202 }
203 strcpy(baseDestName, argv[argc - 1]);
204 baseDestLen = strlen(baseDestName);
205 if (baseDestLen == 0) goto exit_false;
206 187
207 destDirFlag = isDirectory(baseDestName, TRUE); 188 if (strlen(argv[argc - 1]) > PATH_MAX) {
208 if ((argc > 3) && destDirFlag == FALSE) 189 fprintf(stderr, name_too_long, "cp");
209 { 190 goto exit_false;
210 fprintf(stderr, not_a_directory, "cp", baseDestName); 191 }
211 goto exit_false; 192 strcpy(baseDestName, argv[argc - 1]);
212 } 193 baseDestLen = strlen(baseDestName);
194 if (baseDestLen == 0)
195 goto exit_false;
196
197 destDirFlag = isDirectory(baseDestName, TRUE);
198 if ((argc > 3) && destDirFlag == FALSE) {
199 fprintf(stderr, not_a_directory, "cp", baseDestName);
200 goto exit_false;
201 }
213 202
214 while (argc-- > 1) 203 while (argc-- > 1) {
215 { 204 size_t srcLen;
216 size_t srcLen; 205 int flags_memo;
217 int flags_memo;
218 206
219 baseSrcName = *(argv++); 207 baseSrcName = *(argv++);
220 208
221 if ((srcLen = strlen(baseSrcName)) > PATH_MAX) 209 if ((srcLen = strlen(baseSrcName)) > PATH_MAX)
222 goto name_too_long__exit; 210 goto name_too_long__exit;
223 211
224 if (srcLen == 0) continue; 212 if (srcLen == 0)
213 continue;
225 214
226 srcDirFlag = isDirectory(baseSrcName, followLinks); 215 srcDirFlag = isDirectory(baseSrcName, followLinks);
227 216
228 if ((flags_memo = (recursiveFlag == TRUE && 217 if ((flags_memo = (recursiveFlag == TRUE &&
229 srcDirFlag == TRUE && destDirFlag == TRUE))) 218 srcDirFlag == TRUE && destDirFlag == TRUE))) {
230 { 219 fill_baseDest_buf(&baseDestName[0], &baseDestLen);
231 fill_baseDest_buf(&baseDestName[0], &baseDestLen); 220 }
221 if (recursiveAction(baseSrcName,
222 recursiveFlag, followLinks, FALSE,
223 fileAction, fileAction) == FALSE)
224 goto exit_false;
225
226 if (dz_i == is_mv &&
227 recursiveAction(baseSrcName,
228 recursiveFlag, followLinks, TRUE,
229 rmfileAction, rmdirAction) == FALSE)
230 goto exit_false;
231
232 if (flags_memo)
233 *(baseDestName + baseDestLen) = '\0';
232 } 234 }
233 if (recursiveAction(baseSrcName,
234 recursiveFlag, followLinks, FALSE,
235 fileAction, fileAction)
236 == FALSE) goto exit_false;
237
238 if (dz_i == is_mv &&
239 recursiveAction(baseSrcName,
240 recursiveFlag, followLinks, TRUE,
241 rmfileAction, rmdirAction)
242 == FALSE) goto exit_false;
243 235
244 if (flags_memo) *(baseDestName + baseDestLen) = '\0'; 236 exit TRUE;
245 }
246 237
247 exit TRUE; 238 name_too_long__exit:
248 239 fprintf(stderr, name_too_long, "cp");
249 name_too_long__exit: 240 exit_false:
250 fprintf(stderr, name_too_long, "cp"); 241 exit FALSE;
251 exit_false:
252 exit FALSE;
253} 242}
254 243
255// Local Variables: 244// Local Variables: