aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-09-26 14:31:04 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-09-26 14:31:04 +0200
commit48f116198d53697d59d03f4e0ff6cd8c04e79660 (patch)
treed5d8bec787ec70bf90338d2d3c4d9060e3495dc2 /coreutils
parent67f7186403dec3f61f6ea9e9a3f555bd0b0541bc (diff)
downloadbusybox-w32-48f116198d53697d59d03f4e0ff6cd8c04e79660.tar.gz
busybox-w32-48f116198d53697d59d03f4e0ff6cd8c04e79660.tar.bz2
busybox-w32-48f116198d53697d59d03f4e0ff6cd8c04e79660.zip
cp: add support for --parents and long option synonyms of short opts
By Ian Wienand (ianw AT vmware.com) function old new delta cp_main 257 369 +112 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/0 up/down: 112/0) Total: 112 bytes text data bss dec hex filename 823000 458 6948 830406 cabc6 busybox_old 823283 458 6948 830689 cace1 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/Config.in10
-rw-r--r--coreutils/cp.c66
2 files changed, 61 insertions, 15 deletions
diff --git a/coreutils/Config.in b/coreutils/Config.in
index cacfb9661..64a9421c7 100644
--- a/coreutils/Config.in
+++ b/coreutils/Config.in
@@ -78,6 +78,14 @@ config CP
78 help 78 help
79 cp is used to copy files and directories. 79 cp is used to copy files and directories.
80 80
81config FEATURE_CP_LONG_OPTIONS
82 bool "Enable long options for cp"
83 default n
84 depends on CP
85 help
86 Enable long options for cp.
87 Also add support for --parents option.
88
81config CUT 89config CUT
82 bool "cut" 90 bool "cut"
83 default n 91 default n
@@ -113,7 +121,7 @@ config FEATURE_DD_SIGNAL_HANDLING
113 default y 121 default y
114 depends on DD 122 depends on DD
115 help 123 help
116 sending a SIGUSR1 signal to a running `dd' process makes it 124 Sending a SIGUSR1 signal to a running `dd' process makes it
117 print to standard error the number of records read and written 125 print to standard error the number of records read and written
118 so far, then to resume copying. 126 so far, then to resume copying.
119 127
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 71a29396f..2c0b90bc9 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -20,7 +20,6 @@
20 20
21/* This is a NOEXEC applet. Be very careful! */ 21/* This is a NOEXEC applet. Be very careful! */
22 22
23
24int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 23int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
25int cp_main(int argc, char **argv) 24int cp_main(int argc, char **argv)
26{ 25{
@@ -31,12 +30,16 @@ int cp_main(int argc, char **argv)
31 int s_flags; 30 int s_flags;
32 int d_flags; 31 int d_flags;
33 int flags; 32 int flags;
34 int status = 0; 33 int status;
35 enum { 34 enum {
36 OPT_a = 1 << (sizeof(FILEUTILS_CP_OPTSTR)-1), 35 OPT_a = 1 << (sizeof(FILEUTILS_CP_OPTSTR)-1),
37 OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)), 36 OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)),
38 OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1), 37 OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1),
39 OPT_H = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2), 38 OPT_H = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2),
39 OPT_v = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
40#if ENABLE_FEATURE_CP_LONG_OPTIONS
41 OPT_parents = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+4),
42#endif
40 }; 43 };
41 44
42 // Need at least two arguments 45 // Need at least two arguments
@@ -46,6 +49,20 @@ int cp_main(int argc, char **argv)
46 // -R (and therefore -r) turns on -d (coreutils does this) 49 // -R (and therefore -r) turns on -d (coreutils does this)
47 // -a = -pdR 50 // -a = -pdR
48 opt_complementary = "-2:l--s:s--l:Pd:rRd:Rd:apdR:HL"; 51 opt_complementary = "-2:l--s:s--l:Pd:rRd:Rd:apdR:HL";
52#if ENABLE_FEATURE_CP_LONG_OPTIONS
53 applet_long_options =
54 "archive\0" No_argument "a"
55 "force\0" No_argument "f"
56 "interactive\0" No_argument "i"
57 "link\0" No_argument "l"
58 "dereference\0" No_argument "L"
59 "no-dereference\0" No_argument "P"
60 "recursive\0" No_argument "R"
61 "symbolic-link\0" No_argument "s"
62 "verbose\0" No_argument "v"
63 "parents\0" No_argument "\xff"
64 ;
65#endif
49 // -v (--verbose) is ignored 66 // -v (--verbose) is ignored
50 flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPHv"); 67 flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPHv");
51 /* Options of cp from GNU coreutils 6.10: 68 /* Options of cp from GNU coreutils 6.10:
@@ -62,8 +79,9 @@ int cp_main(int argc, char **argv)
62 * -d same as --no-dereference --preserve=links 79 * -d same as --no-dereference --preserve=links
63 * -p same as --preserve=mode,ownership,timestamps 80 * -p same as --preserve=mode,ownership,timestamps
64 * -c same as --preserve=context 81 * -c same as --preserve=context
82 * --parents
83 * use full source file name under DIRECTORY
65 * NOT SUPPORTED IN BBOX: 84 * NOT SUPPORTED IN BBOX:
66 * long options are not supported (even those above).
67 * --backup[=CONTROL] 85 * --backup[=CONTROL]
68 * make a backup of each existing destination file 86 * make a backup of each existing destination file
69 * -b like --backup but does not accept an argument 87 * -b like --backup but does not accept an argument
@@ -73,8 +91,6 @@ int cp_main(int argc, char **argv)
73 * preserve attributes (default: mode,ownership,timestamps), 91 * preserve attributes (default: mode,ownership,timestamps),
74 * if possible additional attributes: security context,links,all 92 * if possible additional attributes: security context,links,all
75 * --no-preserve=ATTR_LIST 93 * --no-preserve=ATTR_LIST
76 * --parents
77 * use full source file name under DIRECTORY
78 * --remove-destination 94 * --remove-destination
79 * remove each existing destination file before attempting to open 95 * remove each existing destination file before attempting to open
80 * --sparse=WHEN 96 * --sparse=WHEN
@@ -115,39 +131,61 @@ int cp_main(int argc, char **argv)
115 } 131 }
116#endif 132#endif
117 133
134 status = EXIT_SUCCESS;
118 last = argv[argc - 1]; 135 last = argv[argc - 1];
119 /* If there are only two arguments and... */ 136 /* If there are only two arguments and... */
120 if (argc == 2) { 137 if (argc == 2) {
121 s_flags = cp_mv_stat2(*argv, &source_stat, 138 s_flags = cp_mv_stat2(*argv, &source_stat,
122 (flags & FILEUTILS_DEREFERENCE) ? stat : lstat); 139 (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
123 if (s_flags < 0) 140 if (s_flags < 0)
124 return EXIT_FAILURE; 141 return EXIT_FAILURE;
125 d_flags = cp_mv_stat(last, &dest_stat); 142 d_flags = cp_mv_stat(last, &dest_stat);
126 if (d_flags < 0) 143 if (d_flags < 0)
127 return EXIT_FAILURE; 144 return EXIT_FAILURE;
128 145
129 /* ...if neither is a directory or... */ 146#if ENABLE_FEATURE_CP_LONG_OPTIONS
130 if ( !((s_flags | d_flags) & 2) || 147 if (flags & OPT_parents) {
131 /* ...recursing, the 1st is a directory, and the 2nd doesn't exist... */ 148 if (!(d_flags & 2)) {
132 ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags) 149 bb_error_msg_and_die("with --parents, the destination must be a directory");
150 }
151 }
152#endif
153
154 /* ...if neither is a directory... */
155 if (!((s_flags | d_flags) & 2)
156 /* ...or: recursing, the 1st is a directory, and the 2nd doesn't exist... */
157 || ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags)
133 ) { 158 ) {
134 /* ...do a simple copy. */ 159 /* Do a simple copy */
135 dest = last; 160 dest = last;
136 goto DO_COPY; /* NB: argc==2 -> *++argv==last */ 161 goto DO_COPY; /* NB: argc==2 -> *++argv==last */
137 } 162 }
138 } 163 }
139 164
140 while (1) { 165 while (1) {
166#if ENABLE_FEATURE_CP_LONG_OPTIONS
167 if (flags & OPT_parents) {
168 char *dest_dup;
169 char *dest_dir;
170 dest = concat_path_file(last, *argv);
171 dest_dup = xstrdup(dest);
172 dest_dir = dirname(dest_dup);
173 if (bb_make_directory(dest_dir, -1, FILEUTILS_RECUR)) {
174 return EXIT_FAILURE;
175 }
176 free(dest_dup);
177 goto DO_COPY;
178 }
179#endif
141 dest = concat_path_file(last, bb_get_last_path_component_strip(*argv)); 180 dest = concat_path_file(last, bb_get_last_path_component_strip(*argv));
142 DO_COPY: 181 DO_COPY:
143 if (copy_file(*argv, dest, flags) < 0) { 182 if (copy_file(*argv, dest, flags) < 0) {
144 status = 1; 183 status = EXIT_FAILURE;
145 } 184 }
185 free((void*)dest);
146 if (*++argv == last) { 186 if (*++argv == last) {
147 /* possibly leaking dest... */
148 break; 187 break;
149 } 188 }
150 free((void*)dest);
151 } 189 }
152 190
153 /* Exit. We are NOEXEC, not NOFORK. We do exit at the end of main() */ 191 /* Exit. We are NOEXEC, not NOFORK. We do exit at the end of main() */