1 /* vi: set sw=4 ts=4: */
3 * Mini `cp' and `mv' implementation for BusyBox.
6 * Copyright (C) 1999 by Lineo, inc.
7 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
9 * Copyright (C) 2000 by BitterSweet Enterprises, LLC. (GPL)
10 * Extensively modified and rewritten by Karl M. Hegbloom <karlheg@debian.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define BB_DECLARE_EXTERN
30 #define bb_need_name_too_long
31 #define bb_need_omitting_directory
32 #define bb_need_not_a_directory
39 #include <sys/param.h>
43 static const char *dz; /* dollar zero, .bss */
44 static int dz_i; /* index, .bss */
45 static const char *cp_mv_usage[] = /* .rodata */
47 "cp [OPTION]... SOURCE DEST\n"
48 " or: cp [OPTION]... SOURCE... DIRECTORY\n\n"
49 "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n"
51 "\t-a\tsame as -dpR\n"
52 "\t-d\tpreserve links\n"
53 "\t-p\tpreserve file attributes if possible\n"
54 "\t-R\tcopy directories recursively\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"
61 extern int cp_mv_main(int argc, char **argv)
63 __label__ name_too_long__exit;
70 const char *baseSrcName;
73 char baseDestName[PATH_MAX + 1];
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;
87 if (*_buflen + strlen(srcBasename) > PATH_MAX)
88 goto name_too_long__exit;
89 strcat(_buf, srcBasename);
93 int fileAction(const char *fileName, struct stat *statbuf) {
94 __label__ return_false;
95 char destName[PATH_MAX + 1];
97 const char *srcBasename;
99 strcpy(destName, baseDestName);
100 destLen = strlen(destName);
102 if (srcDirFlag == TRUE) {
103 if (recursiveFlag == FALSE) {
104 fprintf(stderr, omitting_directory, "cp", baseSrcName);
107 srcBasename = (strstr(fileName, baseSrcName)
108 + strlen(baseSrcName));
110 if (destLen + strlen(srcBasename) > PATH_MAX) {
111 fprintf(stderr, name_too_long, "cp");
114 strcat(destName, srcBasename);
115 } else if (destDirFlag == TRUE) {
116 fill_baseDest_buf(&destName[0], &destLen);
118 srcBasename = baseSrcName;
120 return copyFile(fileName, destName, preserveFlag, followLinks);
126 int rmfileAction(const char *fileName, struct stat *statbuf) {
127 if (unlink(fileName) < 0) {
134 int rmdirAction(const char *fileName, struct stat *statbuf) {
135 if (rmdir(fileName) < 0) {
142 if ((dz = strrchr(*argv, '/')) == NULL)
146 if (*dz == 'c' && *(dz + 1) == 'p')
151 usage(cp_mv_usage[dz_i]);
156 recursiveFlag = preserveFlag = FALSE;
158 while (**argv == '-') {
164 recursiveFlag = TRUE;
173 recursiveFlag = TRUE;
176 usage(cp_mv_usage[is_cp]);
182 } else { /* (dz_i == is_mv) */
184 recursiveFlag = preserveFlag = TRUE;
188 if (strlen(argv[argc - 1]) > PATH_MAX) {
189 fprintf(stderr, name_too_long, "cp");
192 strcpy(baseDestName, argv[argc - 1]);
193 baseDestLen = strlen(baseDestName);
194 if (baseDestLen == 0)
197 destDirFlag = isDirectory(baseDestName, TRUE);
198 if ((argc > 3) && destDirFlag == FALSE) {
199 fprintf(stderr, not_a_directory, "cp", baseDestName);
207 baseSrcName = *(argv++);
209 if ((srcLen = strlen(baseSrcName)) > PATH_MAX)
210 goto name_too_long__exit;
215 srcDirFlag = isDirectory(baseSrcName, followLinks);
217 if ((flags_memo = (recursiveFlag == TRUE &&
218 srcDirFlag == TRUE && destDirFlag == TRUE))) {
219 fill_baseDest_buf(&baseDestName[0], &baseDestLen);
221 if (recursiveAction(baseSrcName,
222 recursiveFlag, followLinks, FALSE,
223 fileAction, fileAction) == FALSE)
227 recursiveAction(baseSrcName,
228 recursiveFlag, followLinks, TRUE,
229 rmfileAction, rmdirAction) == FALSE)
233 *(baseDestName + baseDestLen) = '\0';
239 fprintf(stderr, name_too_long, "cp");
245 // c-file-style: "k&r"