diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-26 14:31:04 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-26 14:31:04 +0200 |
commit | 48f116198d53697d59d03f4e0ff6cd8c04e79660 (patch) | |
tree | d5d8bec787ec70bf90338d2d3c4d9060e3495dc2 /coreutils | |
parent | 67f7186403dec3f61f6ea9e9a3f555bd0b0541bc (diff) | |
download | busybox-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.in | 10 | ||||
-rw-r--r-- | coreutils/cp.c | 66 |
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 | ||
81 | config 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 | |||
81 | config CUT | 89 | config 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 | |||
24 | int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 23 | int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
25 | int cp_main(int argc, char **argv) | 24 | int 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() */ |