source: MondoRescue/branches/3.3/mindi-busybox/coreutils/cp.c@ 3647

Last change on this file since 3647 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 6.3 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini cp implementation for busybox
4 *
5 * Copyright (C) 2000 by Matt Kraai <kraai@alumni.carnegiemellon.edu>
6 * SELinux support by Yuichi Nakamura <ynakam@hitachisoft.jp>
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9 */
10
11/* http://www.opengroup.org/onlinepubs/007904975/utilities/cp.html */
12
13/* Mar 16, 2003 Manuel Novoa III (mjn3@codepoet.org)
14 *
15 * Size reduction.
16 */
17
18//usage:#define cp_trivial_usage
19//usage: "[OPTIONS] SOURCE... DEST"
20//usage:#define cp_full_usage "\n\n"
21//usage: "Copy SOURCE(s) to DEST\n"
22//usage: "\n -a Same as -dpR"
23//usage: IF_SELINUX(
24//usage: "\n -c Preserve security context"
25//usage: )
26//usage: "\n -R,-r Recurse"
27//usage: "\n -d,-P Preserve symlinks (default if -R)"
28//usage: "\n -L Follow all symlinks"
29//usage: "\n -H Follow symlinks on command line"
30//usage: "\n -p Preserve file attributes if possible"
31//usage: "\n -f Overwrite"
32//usage: "\n -i Prompt before overwrite"
33//usage: "\n -l,-s Create (sym)links"
34//usage: "\n -u Copy only newer files"
35
36#include "libbb.h"
37#include "libcoreutils/coreutils.h"
38
39/* This is a NOEXEC applet. Be very careful! */
40
41int cp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
42int cp_main(int argc, char **argv)
43{
44 struct stat source_stat;
45 struct stat dest_stat;
46 const char *last;
47 const char *dest;
48 int s_flags;
49 int d_flags;
50 int flags;
51 int status;
52 enum {
53 FILEUTILS_CP_OPTNUM = sizeof(FILEUTILS_CP_OPTSTR)-1,
54#if ENABLE_FEATURE_CP_LONG_OPTIONS
55 /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */
56 OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1),
57#endif
58 };
59
60 // Need at least two arguments
61 // Soft- and hardlinking doesn't mix
62 // -P and -d are the same (-P is POSIX, -d is GNU)
63 // -r and -R are the same
64 // -R (and therefore -r) turns on -d (coreutils does this)
65 // -a = -pdR
66 opt_complementary = "-2:l--s:s--l:Pd:rRd:Rd:apdR";
67#if ENABLE_FEATURE_CP_LONG_OPTIONS
68 applet_long_options =
69 "archive\0" No_argument "a"
70 "force\0" No_argument "f"
71 "interactive\0" No_argument "i"
72 "link\0" No_argument "l"
73 "dereference\0" No_argument "L"
74 "no-dereference\0" No_argument "P"
75 "recursive\0" No_argument "R"
76 "symbolic-link\0" No_argument "s"
77 "verbose\0" No_argument "v"
78 "update\0" No_argument "u"
79 "remove-destination\0" No_argument "\xff"
80 "parents\0" No_argument "\xfe"
81 ;
82#endif
83 flags = getopt32(argv, FILEUTILS_CP_OPTSTR);
84 /* Options of cp from GNU coreutils 6.10:
85 * -a, --archive
86 * -f, --force
87 * -i, --interactive
88 * -l, --link
89 * -L, --dereference
90 * -P, --no-dereference
91 * -R, -r, --recursive
92 * -s, --symbolic-link
93 * -v, --verbose
94 * -H follow command-line symbolic links in SOURCE
95 * -d same as --no-dereference --preserve=links
96 * -p same as --preserve=mode,ownership,timestamps
97 * -c same as --preserve=context
98 * -u, --update
99 * copy only when the SOURCE file is newer than the destination
100 * file or when the destination file is missing
101 * --remove-destination
102 * remove each existing destination file before attempting to open
103 * --parents
104 * use full source file name under DIRECTORY
105 * NOT SUPPORTED IN BBOX:
106 * --backup[=CONTROL]
107 * make a backup of each existing destination file
108 * -b like --backup but does not accept an argument
109 * --copy-contents
110 * copy contents of special files when recursive
111 * --preserve[=ATTR_LIST]
112 * preserve attributes (default: mode,ownership,timestamps),
113 * if possible additional attributes: security context,links,all
114 * --no-preserve=ATTR_LIST
115 * --sparse=WHEN
116 * control creation of sparse files
117 * --strip-trailing-slashes
118 * remove any trailing slashes from each SOURCE argument
119 * -S, --suffix=SUFFIX
120 * override the usual backup suffix
121 * -t, --target-directory=DIRECTORY
122 * copy all SOURCE arguments into DIRECTORY
123 * -T, --no-target-directory
124 * treat DEST as a normal file
125 * -x, --one-file-system
126 * stay on this file system
127 * -Z, --context=CONTEXT
128 * (SELinux) set SELinux security context of copy to CONTEXT
129 */
130 argc -= optind;
131 argv += optind;
132 /* Reverse this bit. If there is -d, bit is not set: */
133 flags ^= FILEUTILS_DEREFERENCE;
134 /* coreutils 6.9 compat:
135 * by default, "cp" derefs symlinks (creates regular dest files),
136 * but "cp -R" does not. We switch off deref if -r or -R (see above).
137 * However, "cp -RL" must still deref symlinks: */
138 if (flags & FILEUTILS_DEREF_SOFTLINK) /* -L */
139 flags |= FILEUTILS_DEREFERENCE;
140
141#if ENABLE_SELINUX
142 if (flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) {
143 selinux_or_die();
144 }
145#endif
146
147 status = EXIT_SUCCESS;
148 last = argv[argc - 1];
149 /* If there are only two arguments and... */
150 if (argc == 2) {
151 s_flags = cp_mv_stat2(*argv, &source_stat,
152 (flags & FILEUTILS_DEREFERENCE) ? stat : lstat);
153 if (s_flags < 0)
154 return EXIT_FAILURE;
155 d_flags = cp_mv_stat(last, &dest_stat);
156 if (d_flags < 0)
157 return EXIT_FAILURE;
158
159#if ENABLE_FEATURE_CP_LONG_OPTIONS
160 //bb_error_msg("flags:%x FILEUTILS_RMDEST:%x OPT_parents:%x",
161 // flags, FILEUTILS_RMDEST, OPT_parents);
162 if (flags & OPT_parents) {
163 if (!(d_flags & 2)) {
164 bb_error_msg_and_die("with --parents, the destination must be a directory");
165 }
166 }
167 if (flags & FILEUTILS_RMDEST) {
168 flags |= FILEUTILS_FORCE;
169 }
170#endif
171
172 /* ...if neither is a directory... */
173 if (!((s_flags | d_flags) & 2)
174 /* ...or: recursing, the 1st is a directory, and the 2nd doesn't exist... */
175 || ((flags & FILEUTILS_RECUR) && (s_flags & 2) && !d_flags)
176 ) {
177 /* Do a simple copy */
178 dest = last;
179 goto DO_COPY; /* NB: argc==2 -> *++argv==last */
180 }
181 }
182
183 while (1) {
184#if ENABLE_FEATURE_CP_LONG_OPTIONS
185 if (flags & OPT_parents) {
186 char *dest_dup;
187 char *dest_dir;
188 dest = concat_path_file(last, *argv);
189 dest_dup = xstrdup(dest);
190 dest_dir = dirname(dest_dup);
191 if (bb_make_directory(dest_dir, -1, FILEUTILS_RECUR)) {
192 return EXIT_FAILURE;
193 }
194 free(dest_dup);
195 goto DO_COPY;
196 }
197#endif
198 dest = concat_path_file(last, bb_get_last_path_component_strip(*argv));
199 DO_COPY:
200 if (copy_file(*argv, dest, flags) < 0) {
201 status = EXIT_FAILURE;
202 }
203 if (*++argv == last) {
204 /* possibly leaking dest... */
205 break;
206 }
207 /* don't move up: dest may be == last and not malloced! */
208 free((void*)dest);
209 }
210
211 /* Exit. We are NOEXEC, not NOFORK. We do exit at the end of main() */
212 return status;
213}
Note: See TracBrowser for help on using the repository browser.