diff options
Diffstat (limited to 'cp_mv.c')
-rw-r--r-- | cp_mv.c | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/cp_mv.c b/cp_mv.c new file mode 100644 index 000000000..2ba8662b9 --- /dev/null +++ b/cp_mv.c | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * Mini `cp' and `mv' implementation for BusyBox. | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 1999 by Lineo, inc. | ||
6 | * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> | ||
7 | * | ||
8 | * Copyright (C) 2000 by BitterSweet Enterprises, LLC. (GPL) | ||
9 | * Extensively modified and rewritten by Karl M. Hegbloom <karlheg@debian.org> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include "internal.h" | ||
28 | #define BB_DECLARE_EXTERN | ||
29 | #define bb_need_name_too_long | ||
30 | #define bb_need_omitting_directory | ||
31 | #define bb_need_not_a_directory | ||
32 | #include "messages.c" | ||
33 | |||
34 | #include <stdio.h> | ||
35 | #include <time.h> | ||
36 | #include <utime.h> | ||
37 | #include <dirent.h> | ||
38 | #include <sys/param.h> | ||
39 | |||
40 | #define is_cp 0 | ||
41 | #define is_mv 1 | ||
42 | static const char *dz; /* dollar zero, .bss */ | ||
43 | static int dz_i; /* index, .bss */ | ||
44 | static const char *cp_mv_usage[] = /* .rodata */ | ||
45 | { | ||
46 | "cp [OPTION]... SOURCE DEST\n" | ||
47 | " or: cp [OPTION]... SOURCE... DIRECTORY\n\n" | ||
48 | "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" | ||
49 | "\n" | ||
50 | "\t-a\tsame as -dpR\n" | ||
51 | "\t-d\tpreserve links\n" | ||
52 | "\t-p\tpreserve file attributes if possible\n" | ||
53 | "\t-R\tcopy directories recursively\n" | ||
54 | , | ||
55 | "mv SOURCE DEST\n" | ||
56 | " or: mv SOURCE... DIRECTORY\n\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" | ||
59 | }; | ||
60 | |||
61 | extern int cp_mv_main(int argc, char **argv) | ||
62 | { | ||
63 | __label__ name_too_long__exit; | ||
64 | __label__ exit_false; | ||
65 | |||
66 | int recursiveFlag; | ||
67 | int followLinks; | ||
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 | { | ||
79 | const char *srcBasename; | ||
80 | if ((srcBasename = strrchr(baseSrcName, '/')) == NULL) | ||
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 | } | ||
89 | } | ||
90 | if (*_buflen + strlen(srcBasename) > PATH_MAX) | ||
91 | goto name_too_long__exit; | ||
92 | strcat(_buf, srcBasename); | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | int fileAction(const char *fileName, struct stat *statbuf) | ||
97 | { | ||
98 | __label__ return_false; | ||
99 | char destName[PATH_MAX + 1]; | ||
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 | } | ||
120 | strcat(destName, srcBasename); | ||
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 | } | ||
135 | |||
136 | int rmfileAction(const char *fileName, struct stat* statbuf) | ||
137 | { | ||
138 | if (unlink(fileName) < 0 ) { | ||
139 | perror(fileName); | ||
140 | return FALSE; | ||
141 | } | ||
142 | return TRUE; | ||
143 | } | ||
144 | |||
145 | int rmdirAction(const char *fileName, struct stat* statbuf) | ||
146 | { | ||
147 | if (rmdir(fileName) < 0 ) { | ||
148 | perror(fileName); | ||
149 | return FALSE; | ||
150 | } | ||
151 | return TRUE; | ||
152 | } | ||
153 | |||
154 | if ((dz = strrchr(*argv, '/')) == NULL) dz = *argv; else dz++; | ||
155 | if (*dz == 'c' && *(dz + 1) == 'p') dz_i = is_cp; else dz_i = is_mv; | ||
156 | if (argc < 3) usage(cp_mv_usage[dz_i]); | ||
157 | argc--; | ||
158 | argv++; | ||
159 | |||
160 | if (dz_i == is_cp) | ||
161 | { | ||
162 | recursiveFlag = preserveFlag = FALSE; | ||
163 | followLinks = TRUE; | ||
164 | while (**argv == '-') | ||
165 | { | ||
166 | while (*++(*argv)) | ||
167 | { | ||
168 | switch (**argv) | ||
169 | { | ||
170 | case 'a': | ||
171 | followLinks = FALSE; | ||
172 | preserveFlag = TRUE; | ||
173 | recursiveFlag = TRUE; | ||
174 | break; | ||
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 | } | ||
187 | } | ||
188 | argc--; | ||
189 | argv++; | ||
190 | } | ||
191 | } | ||
192 | else /* (dz_i == is_mv) */ | ||
193 | { | ||
194 | recursiveFlag = preserveFlag = TRUE; | ||
195 | followLinks = FALSE; | ||
196 | } | ||
197 | |||
198 | if (strlen(argv[argc - 1]) > PATH_MAX) | ||
199 | { | ||
200 | fprintf(stderr, name_too_long, "cp"); | ||
201 | goto exit_false; | ||
202 | } | ||
203 | strcpy(baseDestName, argv[argc - 1]); | ||
204 | baseDestLen = strlen(baseDestName); | ||
205 | if (baseDestLen == 0) goto exit_false; | ||
206 | |||
207 | destDirFlag = isDirectory(baseDestName, TRUE); | ||
208 | if ((argc > 3) && destDirFlag == FALSE) | ||
209 | { | ||
210 | fprintf(stderr, not_a_directory, "cp", baseDestName); | ||
211 | goto exit_false; | ||
212 | } | ||
213 | |||
214 | while (argc-- > 1) | ||
215 | { | ||
216 | size_t srcLen; | ||
217 | int flags_memo; | ||
218 | |||
219 | baseSrcName = *(argv++); | ||
220 | |||
221 | if ((srcLen = strlen(baseSrcName)) > PATH_MAX) | ||
222 | goto name_too_long__exit; | ||
223 | |||
224 | if (srcLen == 0) continue; | ||
225 | |||
226 | srcDirFlag = isDirectory(baseSrcName, followLinks); | ||
227 | |||
228 | if ((flags_memo = (recursiveFlag == TRUE && | ||
229 | srcDirFlag == TRUE && destDirFlag == TRUE))) | ||
230 | { | ||
231 | fill_baseDest_buf(&baseDestName[0], &baseDestLen); | ||
232 | } | ||
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 | |||
244 | if (flags_memo) *(baseDestName + baseDestLen) = '\0'; | ||
245 | } | ||
246 | |||
247 | exit TRUE; | ||
248 | |||
249 | name_too_long__exit: | ||
250 | fprintf(stderr, name_too_long, "cp"); | ||
251 | exit_false: | ||
252 | exit FALSE; | ||
253 | } | ||
254 | |||
255 | // Local Variables: | ||
256 | // c-file-style: "k&r" | ||
257 | // c-basic-offset: 4 | ||
258 | // End: | ||