Line data Source code
1 : /* cp.c -- file copying (main routines)
2 : Copyright (C) 89, 90, 91, 1995-2008 Free Software Foundation, Inc.
3 :
4 : This program is free software: you can redistribute it and/or modify
5 : it under the terms of the GNU General Public License as published by
6 : the Free Software Foundation, either version 3 of the License, or
7 : (at your option) any later version.
8 :
9 : This program is distributed in the hope that it will be useful,
10 : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : GNU General Public License for more details.
13 :
14 : You should have received a copy of the GNU General Public License
15 : along with this program. If not, see <http://www.gnu.org/licenses/>.
16 :
17 : Written by Torbjorn Granlund, David MacKenzie, and Jim Meyering. */
18 :
19 : #include <config.h>
20 : #include <stdio.h>
21 : #include <sys/types.h>
22 : #include <getopt.h>
23 : #include <selinux/selinux.h>
24 :
25 : #include "system.h"
26 : #include "argmatch.h"
27 : #include "backupfile.h"
28 : #include "copy.h"
29 : #include "cp-hash.h"
30 : #include "error.h"
31 : #include "filenamecat.h"
32 : #include "lchmod.h"
33 : #include "quote.h"
34 : #include "stat-time.h"
35 : #include "utimens.h"
36 : #include "acl.h"
37 :
38 : #if ! HAVE_LCHOWN
39 : # define lchown(name, uid, gid) chown (name, uid, gid)
40 : #endif
41 :
42 : #define ASSIGN_BASENAME_STRDUPA(Dest, File_name) \
43 : do \
44 : { \
45 : char *tmp_abns_; \
46 : ASSIGN_STRDUPA (tmp_abns_, (File_name)); \
47 : Dest = last_component (tmp_abns_); \
48 : strip_trailing_slashes (Dest); \
49 : } \
50 : while (0)
51 :
52 : /* The official name of this program (e.g., no `g' prefix). */
53 : #define PROGRAM_NAME "cp"
54 :
55 : #define AUTHORS "Torbjorn Granlund", "David MacKenzie", "Jim Meyering"
56 :
57 : /* Used by do_copy, make_dir_parents_private, and re_protect
58 : to keep a list of leading directories whose protections
59 : need to be fixed after copying. */
60 : struct dir_attr
61 : {
62 : struct stat st;
63 : bool restore_mode;
64 : size_t slash_offset;
65 : struct dir_attr *next;
66 : };
67 :
68 : /* For long options that have no equivalent short option, use a
69 : non-character as a pseudo short option, starting with CHAR_MAX + 1. */
70 : enum
71 : {
72 : COPY_CONTENTS_OPTION = CHAR_MAX + 1,
73 : NO_PRESERVE_ATTRIBUTES_OPTION,
74 : PARENTS_OPTION,
75 : PRESERVE_ATTRIBUTES_OPTION,
76 : REPLY_OPTION,
77 : SPARSE_OPTION,
78 : STRIP_TRAILING_SLASHES_OPTION,
79 : UNLINK_DEST_BEFORE_OPENING
80 : };
81 :
82 : /* Initial number of entries in each hash table entry's table of inodes. */
83 : #define INITIAL_HASH_MODULE 100
84 :
85 : /* Initial number of entries in the inode hash table. */
86 : #define INITIAL_ENTRY_TAB_SIZE 70
87 :
88 : /* The invocation name of this program. */
89 : char *program_name;
90 :
91 : /* True if the kernel is SELinux enabled. */
92 : static bool selinux_enabled;
93 :
94 : /* If true, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
95 : as its destination instead of the usual "e_dir/e_file." */
96 : static bool parents_option = false;
97 :
98 : /* Remove any trailing slashes from each SOURCE argument. */
99 : static bool remove_trailing_slashes;
100 :
101 : static char const *const sparse_type_string[] =
102 : {
103 : "never", "auto", "always", NULL
104 : };
105 : static enum Sparse_type const sparse_type[] =
106 : {
107 : SPARSE_NEVER, SPARSE_AUTO, SPARSE_ALWAYS
108 : };
109 : ARGMATCH_VERIFY (sparse_type_string, sparse_type);
110 :
111 : /* Valid arguments to the `--reply' option. */
112 : static char const* const reply_args[] =
113 : {
114 : "yes", "no", "query", NULL
115 : };
116 : /* The values that correspond to the above strings. */
117 : static int const reply_vals[] =
118 : {
119 : I_ALWAYS_YES, I_ALWAYS_NO, I_ASK_USER
120 : };
121 : ARGMATCH_VERIFY (reply_args, reply_vals);
122 :
123 : static struct option const long_opts[] =
124 : {
125 : {"archive", no_argument, NULL, 'a'},
126 : {"backup", optional_argument, NULL, 'b'},
127 : {"copy-contents", no_argument, NULL, COPY_CONTENTS_OPTION},
128 : {"dereference", no_argument, NULL, 'L'},
129 : {"force", no_argument, NULL, 'f'},
130 : {"interactive", no_argument, NULL, 'i'},
131 : {"link", no_argument, NULL, 'l'},
132 : {"no-dereference", no_argument, NULL, 'P'},
133 : {"no-preserve", required_argument, NULL, NO_PRESERVE_ATTRIBUTES_OPTION},
134 : {"no-target-directory", no_argument, NULL, 'T'},
135 : {"one-file-system", no_argument, NULL, 'x'},
136 : {"parents", no_argument, NULL, PARENTS_OPTION},
137 : {"path", no_argument, NULL, PARENTS_OPTION}, /* Deprecated. */
138 : {"preserve", optional_argument, NULL, PRESERVE_ATTRIBUTES_OPTION},
139 : {"recursive", no_argument, NULL, 'R'},
140 : {"remove-destination", no_argument, NULL, UNLINK_DEST_BEFORE_OPENING},
141 : {"reply", required_argument, NULL, REPLY_OPTION}, /* Deprecated 2005-07-03,
142 : remove in 2008. */
143 : {"sparse", required_argument, NULL, SPARSE_OPTION},
144 : {"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION},
145 : {"suffix", required_argument, NULL, 'S'},
146 : {"symbolic-link", no_argument, NULL, 's'},
147 : {"target-directory", required_argument, NULL, 't'},
148 : {"update", no_argument, NULL, 'u'},
149 : {"verbose", no_argument, NULL, 'v'},
150 : {GETOPT_HELP_OPTION_DECL},
151 : {GETOPT_VERSION_OPTION_DECL},
152 : {NULL, 0, NULL, 0}
153 : };
154 :
155 : void
156 73 : usage (int status)
157 : {
158 73 : if (status != EXIT_SUCCESS)
159 72 : fprintf (stderr, _("Try `%s --help' for more information.\n"),
160 : program_name);
161 : else
162 : {
163 1 : printf (_("\
164 : Usage: %s [OPTION]... [-T] SOURCE DEST\n\
165 : or: %s [OPTION]... SOURCE... DIRECTORY\n\
166 : or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
167 : "),
168 : program_name, program_name, program_name);
169 1 : fputs (_("\
170 : Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
171 : \n\
172 : "), stdout);
173 1 : fputs (_("\
174 : Mandatory arguments to long options are mandatory for short options too.\n\
175 : "), stdout);
176 1 : fputs (_("\
177 : -a, --archive same as -dpR\n\
178 : --backup[=CONTROL] make a backup of each existing destination file\n\
179 : -b like --backup but does not accept an argument\n\
180 : --copy-contents copy contents of special files when recursive\n\
181 : -d same as --no-dereference --preserve=links\n\
182 : "), stdout);
183 1 : fputs (_("\
184 : -f, --force if an existing destination file cannot be\n\
185 : opened, remove it and try again\n\
186 : -i, --interactive prompt before overwrite\n\
187 : -H follow command-line symbolic links in SOURCE\n\
188 : "), stdout);
189 1 : fputs (_("\
190 : -l, --link link files instead of copying\n\
191 : -L, --dereference always follow symbolic links in SOURCE\n\
192 : "), stdout);
193 1 : fputs (_("\
194 : -P, --no-dereference never follow symbolic links in SOURCE\n\
195 : "), stdout);
196 1 : fputs (_("\
197 : -p same as --preserve=mode,ownership,timestamps\n\
198 : --preserve[=ATTR_LIST] preserve the specified attributes (default:\n\
199 : mode,ownership,timestamps), if possible\n\
200 : additional attributes: context, links, all\n\
201 : "), stdout);
202 1 : fputs (_("\
203 : --no-preserve=ATTR_LIST don't preserve the specified attributes\n\
204 : --parents use full source file name under DIRECTORY\n\
205 : "), stdout);
206 1 : fputs (_("\
207 : -R, -r, --recursive copy directories recursively\n\
208 : --remove-destination remove each existing destination file before\n\
209 : attempting to open it (contrast with --force)\n\
210 : "), stdout);
211 1 : fputs (_("\
212 : --sparse=WHEN control creation of sparse files\n\
213 : --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\
214 : argument\n\
215 : "), stdout);
216 1 : fputs (_("\
217 : -s, --symbolic-link make symbolic links instead of copying\n\
218 : -S, --suffix=SUFFIX override the usual backup suffix\n\
219 : -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
220 : -T, --no-target-directory treat DEST as a normal file\n\
221 : "), stdout);
222 1 : fputs (_("\
223 : -u, --update copy only when the SOURCE file is newer\n\
224 : than the destination file or when the\n\
225 : destination file is missing\n\
226 : -v, --verbose explain what is being done\n\
227 : -x, --one-file-system stay on this file system\n\
228 : "), stdout);
229 1 : fputs (HELP_OPTION_DESCRIPTION, stdout);
230 1 : fputs (VERSION_OPTION_DESCRIPTION, stdout);
231 1 : fputs (_("\
232 : \n\
233 : By default, sparse SOURCE files are detected by a crude heuristic and the\n\
234 : corresponding DEST file is made sparse as well. That is the behavior\n\
235 : selected by --sparse=auto. Specify --sparse=always to create a sparse DEST\n\
236 : file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\
237 : Use --sparse=never to inhibit creation of sparse files.\n\
238 : \n\
239 : "), stdout);
240 1 : fputs (_("\
241 : The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
242 : The version control method may be selected via the --backup option or through\n\
243 : the VERSION_CONTROL environment variable. Here are the values:\n\
244 : \n\
245 : "), stdout);
246 1 : fputs (_("\
247 : none, off never make backups (even if --backup is given)\n\
248 : numbered, t make numbered backups\n\
249 : existing, nil numbered if numbered backups exist, simple otherwise\n\
250 : simple, never always make simple backups\n\
251 : "), stdout);
252 1 : fputs (_("\
253 : \n\
254 : As a special case, cp makes a backup of SOURCE when the force and backup\n\
255 : options are given and SOURCE and DEST are the same name for an existing,\n\
256 : regular file.\n\
257 : "), stdout);
258 1 : emit_bug_reporting_address ();
259 : }
260 73 : exit (status);
261 : }
262 :
263 : /* Ensure that the parent directories of CONST_DST_NAME have the
264 : correct protections, for the --parents option. This is done
265 : after all copying has been completed, to allow permissions
266 : that don't include user write/execute.
267 :
268 : SRC_OFFSET is the index in CONST_DST_NAME of the beginning of the
269 : source directory name.
270 :
271 : ATTR_LIST is a null-terminated linked list of structures that
272 : indicates the end of the filename of each intermediate directory
273 : in CONST_DST_NAME that may need to have its attributes changed.
274 : The command `cp --parents --preserve a/b/c d/e_dir' changes the
275 : attributes of the directories d/e_dir/a and d/e_dir/a/b to match
276 : the corresponding source directories regardless of whether they
277 : existed before the `cp' command was given.
278 :
279 : Return true if the parent of CONST_DST_NAME and any intermediate
280 : directories specified by ATTR_LIST have the proper permissions
281 : when done. */
282 :
283 : static bool
284 0 : re_protect (char const *const_dst_name, size_t src_offset,
285 : struct dir_attr *attr_list, const struct cp_options *x)
286 : {
287 : struct dir_attr *p;
288 : char *dst_name; /* A copy of CONST_DST_NAME we can change. */
289 : char *src_name; /* The source name in `dst_name'. */
290 :
291 0 : ASSIGN_STRDUPA (dst_name, const_dst_name);
292 0 : src_name = dst_name + src_offset;
293 :
294 0 : for (p = attr_list; p; p = p->next)
295 : {
296 0 : dst_name[p->slash_offset] = '\0';
297 :
298 : /* Adjust the times (and if possible, ownership) for the copy.
299 : chown turns off set[ug]id bits for non-root,
300 : so do the chmod last. */
301 :
302 0 : if (x->preserve_timestamps)
303 : {
304 : struct timespec timespec[2];
305 :
306 0 : timespec[0] = get_stat_atime (&p->st);
307 0 : timespec[1] = get_stat_mtime (&p->st);
308 :
309 0 : if (utimens (dst_name, timespec))
310 : {
311 0 : error (0, errno, _("failed to preserve times for %s"),
312 : quote (dst_name));
313 0 : return false;
314 : }
315 : }
316 :
317 0 : if (x->preserve_ownership)
318 : {
319 0 : if (lchown (dst_name, p->st.st_uid, p->st.st_gid) != 0)
320 : {
321 0 : if (! chown_failure_ok (x))
322 : {
323 0 : error (0, errno, _("failed to preserve ownership for %s"),
324 : quote (dst_name));
325 0 : return false;
326 : }
327 : /* Failing to preserve ownership is OK. Still, try to preserve
328 : the group, but ignore the possible error. */
329 0 : (void) lchown (dst_name, -1, p->st.st_gid);
330 : }
331 : }
332 :
333 0 : if (x->preserve_mode)
334 : {
335 0 : if (copy_acl (src_name, -1, dst_name, -1, p->st.st_mode) != 0)
336 0 : return false;
337 : }
338 0 : else if (p->restore_mode)
339 : {
340 0 : if (lchmod (dst_name, p->st.st_mode) != 0)
341 : {
342 0 : error (0, errno, _("failed to preserve permissions for %s"),
343 : quote (dst_name));
344 0 : return false;
345 : }
346 : }
347 :
348 0 : dst_name[p->slash_offset] = '/';
349 : }
350 0 : return true;
351 : }
352 :
353 : /* Ensure that the parent directory of CONST_DIR exists, for
354 : the --parents option.
355 :
356 : SRC_OFFSET is the index in CONST_DIR (which is a destination
357 : directory) of the beginning of the source directory name.
358 : Create any leading directories that don't already exist.
359 : If VERBOSE_FMT_STRING is nonzero, use it as a printf format
360 : string for printing a message after successfully making a directory.
361 : The format should take two string arguments: the names of the
362 : source and destination directories.
363 : Creates a linked list of attributes of intermediate directories,
364 : *ATTR_LIST, for re_protect to use after calling copy.
365 : Sets *NEW_DST if this function creates parent of CONST_DIR.
366 :
367 : Return true if parent of CONST_DIR exists as a directory with the proper
368 : permissions when done. */
369 :
370 : /* FIXME: Synch this function with the one in ../lib/mkdir-p.c. */
371 :
372 : static bool
373 0 : make_dir_parents_private (char const *const_dir, size_t src_offset,
374 : char const *verbose_fmt_string,
375 : struct dir_attr **attr_list, bool *new_dst,
376 : const struct cp_options *x)
377 : {
378 : struct stat stats;
379 : char *dir; /* A copy of CONST_DIR we can change. */
380 : char *src; /* Source name in DIR. */
381 : char *dst_dir; /* Leading directory of DIR. */
382 : size_t dirlen; /* Length of DIR. */
383 :
384 0 : ASSIGN_STRDUPA (dir, const_dir);
385 :
386 0 : src = dir + src_offset;
387 :
388 0 : dirlen = dir_len (dir);
389 0 : dst_dir = alloca (dirlen + 1);
390 0 : memcpy (dst_dir, dir, dirlen);
391 0 : dst_dir[dirlen] = '\0';
392 :
393 0 : *attr_list = NULL;
394 :
395 0 : if (stat (dst_dir, &stats) != 0)
396 : {
397 : /* A parent of CONST_DIR does not exist.
398 : Make all missing intermediate directories. */
399 : char *slash;
400 :
401 0 : slash = src;
402 0 : while (*slash == '/')
403 0 : slash++;
404 0 : while ((slash = strchr (slash, '/')))
405 : {
406 : struct dir_attr *new IF_LINT (= NULL);
407 : bool missing_dir;
408 :
409 0 : *slash = '\0';
410 0 : missing_dir = (stat (dir, &stats) != 0);
411 :
412 0 : if (missing_dir | x->preserve_ownership | x->preserve_mode
413 0 : | x->preserve_timestamps)
414 : {
415 : /* Add this directory to the list of directories whose
416 : modes might need fixing later. */
417 : struct stat src_st;
418 0 : int src_errno = (stat (src, &src_st) != 0
419 0 : ? errno
420 0 : : S_ISDIR (src_st.st_mode)
421 : ? 0
422 0 : : ENOTDIR);
423 0 : if (src_errno)
424 : {
425 0 : error (0, src_errno, _("failed to get attributes of %s"),
426 : quote (src));
427 0 : return false;
428 : }
429 :
430 0 : new = xmalloc (sizeof *new);
431 0 : new->st = src_st;
432 0 : new->slash_offset = slash - dir;
433 0 : new->restore_mode = false;
434 0 : new->next = *attr_list;
435 0 : *attr_list = new;
436 : }
437 :
438 0 : if (missing_dir)
439 : {
440 : mode_t src_mode;
441 : mode_t omitted_permissions;
442 : mode_t mkdir_mode;
443 :
444 : /* This component does not exist. We must set
445 : *new_dst and new->st.st_mode inside this loop because,
446 : for example, in the command `cp --parents ../a/../b/c e_dir',
447 : make_dir_parents_private creates only e_dir/../a if
448 : ./b already exists. */
449 0 : *new_dst = true;
450 0 : src_mode = new->st.st_mode;
451 :
452 : /* If the ownership or special mode bits might change,
453 : omit some permissions at first, so unauthorized users
454 : cannot nip in before the file is ready. */
455 0 : omitted_permissions = (src_mode
456 0 : & (x->preserve_ownership
457 0 : ? S_IRWXG | S_IRWXO
458 0 : : x->preserve_mode
459 : ? S_IWGRP | S_IWOTH
460 : : 0));
461 :
462 : /* POSIX says mkdir's behavior is implementation-defined when
463 : (src_mode & ~S_IRWXUGO) != 0. However, common practice is
464 : to ask mkdir to copy all the CHMOD_MODE_BITS, letting mkdir
465 : decide what to do with S_ISUID | S_ISGID | S_ISVTX. */
466 0 : mkdir_mode = src_mode & CHMOD_MODE_BITS & ~omitted_permissions;
467 0 : if (mkdir (dir, mkdir_mode) != 0)
468 : {
469 0 : error (0, errno, _("cannot make directory %s"),
470 : quote (dir));
471 0 : return false;
472 : }
473 : else
474 : {
475 0 : if (verbose_fmt_string != NULL)
476 0 : printf (verbose_fmt_string, src, dir);
477 : }
478 :
479 : /* We need search and write permissions to the new directory
480 : for writing the directory's contents. Check if these
481 : permissions are there. */
482 :
483 0 : if (lstat (dir, &stats))
484 : {
485 0 : error (0, errno, _("failed to get attributes of %s"),
486 : quote (dir));
487 0 : return false;
488 : }
489 :
490 :
491 0 : if (! x->preserve_mode)
492 : {
493 0 : if (omitted_permissions & ~stats.st_mode)
494 0 : omitted_permissions &= ~ cached_umask ();
495 0 : if (omitted_permissions & ~stats.st_mode
496 0 : || (stats.st_mode & S_IRWXU) != S_IRWXU)
497 : {
498 0 : new->st.st_mode = stats.st_mode | omitted_permissions;
499 0 : new->restore_mode = true;
500 : }
501 : }
502 :
503 0 : if ((stats.st_mode & S_IRWXU) != S_IRWXU)
504 : {
505 : /* Make the new directory searchable and writable.
506 : The original permissions will be restored later. */
507 :
508 0 : if (lchmod (dir, stats.st_mode | S_IRWXU) != 0)
509 : {
510 0 : error (0, errno, _("setting permissions for %s"),
511 : quote (dir));
512 0 : return false;
513 : }
514 : }
515 : }
516 0 : else if (!S_ISDIR (stats.st_mode))
517 : {
518 0 : error (0, 0, _("%s exists but is not a directory"),
519 : quote (dir));
520 0 : return false;
521 : }
522 : else
523 0 : *new_dst = false;
524 0 : *slash++ = '/';
525 :
526 : /* Avoid unnecessary calls to `stat' when given
527 : file names containing multiple adjacent slashes. */
528 0 : while (*slash == '/')
529 0 : slash++;
530 : }
531 : }
532 :
533 : /* We get here if the parent of DIR already exists. */
534 :
535 0 : else if (!S_ISDIR (stats.st_mode))
536 : {
537 0 : error (0, 0, _("%s exists but is not a directory"), quote (dst_dir));
538 0 : return false;
539 : }
540 : else
541 : {
542 0 : *new_dst = false;
543 : }
544 0 : return true;
545 : }
546 :
547 : /* FILE is the last operand of this command.
548 : Return true if FILE is a directory.
549 : But report an error and exit if there is a problem accessing FILE,
550 : or if FILE does not exist but would have to refer to an existing
551 : directory if it referred to anything at all.
552 :
553 : If the file exists, store the file's status into *ST.
554 : Otherwise, set *NEW_DST. */
555 :
556 : static bool
557 100 : target_directory_operand (char const *file, struct stat *st, bool *new_dst)
558 : {
559 100 : int err = (stat (file, st) == 0 ? 0 : errno);
560 100 : bool is_a_dir = !err && S_ISDIR (st->st_mode);
561 100 : if (err)
562 : {
563 33 : if (err != ENOENT)
564 0 : error (EXIT_FAILURE, err, _("accessing %s"), quote (file));
565 33 : *new_dst = true;
566 : }
567 100 : return is_a_dir;
568 : }
569 :
570 : /* Scan the arguments, and copy each by calling copy.
571 : Return true if successful. */
572 :
573 : static bool
574 159 : do_copy (int n_files, char **file, const char *target_directory,
575 : bool no_target_directory, struct cp_options *x)
576 : {
577 : struct stat sb;
578 159 : bool new_dst = false;
579 159 : bool ok = true;
580 :
581 159 : if (n_files <= !target_directory)
582 : {
583 55 : if (n_files <= 0)
584 37 : error (0, 0, _("missing file operand"));
585 : else
586 18 : error (0, 0, _("missing destination file operand after %s"),
587 : quote (file[0]));
588 55 : usage (EXIT_FAILURE);
589 : }
590 :
591 104 : if (no_target_directory)
592 : {
593 2 : if (target_directory)
594 0 : error (EXIT_FAILURE, 0,
595 : _("Cannot combine --target-directory (-t) "
596 : "and --no-target-directory (-T)"));
597 2 : if (2 < n_files)
598 : {
599 0 : error (0, 0, _("extra operand %s"), quote (file[2]));
600 0 : usage (EXIT_FAILURE);
601 : }
602 : }
603 102 : else if (!target_directory)
604 : {
605 100 : if (2 <= n_files
606 100 : && target_directory_operand (file[n_files - 1], &sb, &new_dst))
607 20 : target_directory = file[--n_files];
608 80 : else if (2 < n_files)
609 3 : error (EXIT_FAILURE, 0, _("target %s is not a directory"),
610 3 : quote (file[n_files - 1]));
611 : }
612 :
613 101 : if (target_directory)
614 : {
615 : /* cp file1...filen edir
616 : Copy the files `file1' through `filen'
617 : to the existing directory `edir'. */
618 : int i;
619 :
620 : /* Initialize these hash tables only if we'll need them.
621 : The problems they're used to detect can arise only if
622 : there are two or more files to copy. */
623 22 : if (2 <= n_files)
624 : {
625 7 : dest_info_init (x);
626 7 : src_info_init (x);
627 : }
628 :
629 51 : for (i = 0; i < n_files; i++)
630 : {
631 : char *dst_name;
632 29 : bool parent_exists = true; /* True if dir_name (dst_name) exists. */
633 : struct dir_attr *attr_list;
634 29 : char *arg_in_concat = NULL;
635 29 : char *arg = file[i];
636 :
637 : /* Trailing slashes are meaningful (i.e., maybe worth preserving)
638 : only in the source file names. */
639 29 : if (remove_trailing_slashes)
640 0 : strip_trailing_slashes (arg);
641 :
642 29 : if (parents_option)
643 : {
644 : char *arg_no_trailing_slash;
645 :
646 : /* Use `arg' without trailing slashes in constructing destination
647 : file names. Otherwise, we can end up trying to create a
648 : directory via `mkdir ("dst/foo/"...', which is not portable.
649 : It fails, due to the trailing slash, on at least
650 : NetBSD 1.[34] systems. */
651 0 : ASSIGN_STRDUPA (arg_no_trailing_slash, arg);
652 0 : strip_trailing_slashes (arg_no_trailing_slash);
653 :
654 : /* Append all of `arg' (minus any trailing slash) to `dest'. */
655 0 : dst_name = file_name_concat (target_directory,
656 : arg_no_trailing_slash,
657 : &arg_in_concat);
658 :
659 : /* For --parents, we have to make sure that the directory
660 : dir_name (dst_name) exists. We may have to create a few
661 : leading directories. */
662 0 : parent_exists =
663 0 : (make_dir_parents_private
664 0 : (dst_name, arg_in_concat - dst_name,
665 0 : (x->verbose ? "%s -> %s\n" : NULL),
666 : &attr_list, &new_dst, x));
667 : }
668 : else
669 : {
670 : char *arg_base;
671 : /* Append the last component of `arg' to `target_directory'. */
672 :
673 29 : ASSIGN_BASENAME_STRDUPA (arg_base, arg);
674 : /* For `cp -R source/.. dest', don't copy into `dest/..'. */
675 58 : dst_name = (STREQ (arg_base, "..")
676 : ? xstrdup (target_directory)
677 29 : : file_name_concat (target_directory, arg_base,
678 : NULL));
679 : }
680 :
681 29 : if (!parent_exists)
682 : {
683 : /* make_dir_parents_private failed, so don't even
684 : attempt the copy. */
685 0 : ok = false;
686 : }
687 : else
688 : {
689 : bool copy_into_self;
690 29 : ok &= copy (arg, dst_name, new_dst, x, ©_into_self, NULL);
691 :
692 29 : if (parents_option)
693 0 : ok &= re_protect (dst_name, arg_in_concat - dst_name,
694 : attr_list, x);
695 : }
696 :
697 29 : if (parents_option)
698 : {
699 0 : while (attr_list)
700 : {
701 0 : struct dir_attr *p = attr_list;
702 0 : attr_list = attr_list->next;
703 0 : free (p);
704 : }
705 : }
706 :
707 29 : free (dst_name);
708 : }
709 : }
710 : else /* !target_directory */
711 : {
712 : char const *new_dest;
713 79 : char const *source = file[0];
714 79 : char const *dest = file[1];
715 : bool unused;
716 :
717 79 : if (parents_option)
718 : {
719 0 : error (0, 0,
720 : _("with --parents, the destination must be a directory"));
721 0 : usage (EXIT_FAILURE);
722 : }
723 :
724 : /* When the force and backup options have been specified and
725 : the source and destination are the same name for an existing
726 : regular file, convert the user's command, e.g.,
727 : `cp --force --backup foo foo' to `cp --force foo fooSUFFIX'
728 : where SUFFIX is determined by any version control options used. */
729 :
730 79 : if (x->unlink_dest_after_failed_open
731 5 : && x->backup_type != no_backups
732 3 : && STREQ (source, dest)
733 2 : && !new_dst && S_ISREG (sb.st_mode))
734 1 : {
735 : static struct cp_options x_tmp;
736 :
737 1 : new_dest = find_backup_file_name (dest, x->backup_type);
738 : /* Set x->backup_type to `no_backups' so that the normal backup
739 : mechanism is not used when performing the actual copy.
740 : backup_type must be set to `no_backups' only *after* the above
741 : call to find_backup_file_name -- that function uses
742 : backup_type to determine the suffix it applies. */
743 1 : x_tmp = *x;
744 1 : x_tmp.backup_type = no_backups;
745 1 : x = &x_tmp;
746 : }
747 : else
748 : {
749 78 : new_dest = dest;
750 : }
751 :
752 79 : ok = copy (source, new_dest, 0, x, &unused, NULL);
753 : }
754 :
755 101 : return ok;
756 : }
757 :
758 : static void
759 183 : cp_option_init (struct cp_options *x)
760 : {
761 183 : cp_options_default (x);
762 183 : x->copy_as_regular = true;
763 183 : x->dereference = DEREF_UNDEFINED;
764 183 : x->unlink_dest_before_opening = false;
765 183 : x->unlink_dest_after_failed_open = false;
766 183 : x->hard_link = false;
767 183 : x->interactive = I_UNSPECIFIED;
768 183 : x->move_mode = false;
769 183 : x->one_file_system = false;
770 :
771 183 : x->preserve_ownership = false;
772 183 : x->preserve_links = false;
773 183 : x->preserve_mode = false;
774 183 : x->preserve_timestamps = false;
775 183 : x->preserve_security_context = false;
776 183 : x->require_preserve_context = false;
777 :
778 183 : x->require_preserve = false;
779 183 : x->recursive = false;
780 183 : x->sparse_mode = SPARSE_AUTO;
781 183 : x->symbolic_link = false;
782 183 : x->set_mode = false;
783 183 : x->mode = 0;
784 :
785 : /* Not used. */
786 183 : x->stdin_tty = false;
787 :
788 183 : x->update = false;
789 183 : x->verbose = false;
790 :
791 : /* By default, refuse to open a dangling destination symlink, because
792 : in general one cannot do that safely, give the current semantics of
793 : open's O_EXCL flag, (which POSIX doesn't even allow cp to use, btw).
794 : But POSIX requires it. */
795 183 : x->open_dangling_dest_symlink = getenv ("POSIXLY_CORRECT") != NULL;
796 :
797 183 : x->dest_info = NULL;
798 183 : x->src_info = NULL;
799 183 : }
800 :
801 : /* Given a string, ARG, containing a comma-separated list of arguments
802 : to the --preserve option, set the appropriate fields of X to ON_OFF. */
803 : static void
804 11 : decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
805 : {
806 : enum File_attribute
807 : {
808 : PRESERVE_MODE,
809 : PRESERVE_TIMESTAMPS,
810 : PRESERVE_OWNERSHIP,
811 : PRESERVE_LINK,
812 : PRESERVE_CONTEXT,
813 : PRESERVE_ALL
814 : };
815 : static enum File_attribute const preserve_vals[] =
816 : {
817 : PRESERVE_MODE, PRESERVE_TIMESTAMPS,
818 : PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_CONTEXT, PRESERVE_ALL
819 : };
820 : /* Valid arguments to the `--preserve' option. */
821 : static char const* const preserve_args[] =
822 : {
823 : "mode", "timestamps",
824 : "ownership", "links", "context", "all", NULL
825 : };
826 : ARGMATCH_VERIFY (preserve_args, preserve_vals);
827 :
828 11 : char *arg_writable = xstrdup (arg);
829 11 : char *s = arg_writable;
830 : do
831 : {
832 : /* find next comma */
833 12 : char *comma = strchr (s, ',');
834 : enum File_attribute val;
835 :
836 : /* If we found a comma, put a NUL in its place and advance. */
837 12 : if (comma)
838 2 : *comma++ = 0;
839 :
840 : /* process S. */
841 12 : val = XARGMATCH ("--preserve", s, preserve_args, preserve_vals);
842 8 : switch (val)
843 : {
844 3 : case PRESERVE_MODE:
845 3 : x->preserve_mode = on_off;
846 3 : break;
847 :
848 1 : case PRESERVE_TIMESTAMPS:
849 1 : x->preserve_timestamps = on_off;
850 1 : break;
851 :
852 1 : case PRESERVE_OWNERSHIP:
853 1 : x->preserve_ownership = on_off;
854 1 : break;
855 :
856 1 : case PRESERVE_LINK:
857 1 : x->preserve_links = on_off;
858 1 : break;
859 :
860 1 : case PRESERVE_CONTEXT:
861 1 : x->preserve_security_context = on_off;
862 1 : x->require_preserve_context = on_off;
863 1 : break;
864 :
865 1 : case PRESERVE_ALL:
866 1 : x->preserve_mode = on_off;
867 1 : x->preserve_timestamps = on_off;
868 1 : x->preserve_ownership = on_off;
869 1 : x->preserve_links = on_off;
870 1 : if (selinux_enabled)
871 0 : x->preserve_security_context = on_off;
872 1 : break;
873 :
874 0 : default:
875 0 : abort ();
876 : }
877 8 : s = comma;
878 : }
879 8 : while (s);
880 :
881 7 : free (arg_writable);
882 7 : }
883 :
884 : int
885 183 : main (int argc, char **argv)
886 : {
887 : int c;
888 : bool ok;
889 183 : bool make_backups = false;
890 : char *backup_suffix_string;
891 183 : char *version_control_string = NULL;
892 : struct cp_options x;
893 183 : bool copy_contents = false;
894 183 : char *target_directory = NULL;
895 183 : bool no_target_directory = false;
896 :
897 : initialize_main (&argc, &argv);
898 183 : program_name = argv[0];
899 183 : setlocale (LC_ALL, "");
900 : bindtextdomain (PACKAGE, LOCALEDIR);
901 : textdomain (PACKAGE);
902 :
903 183 : atexit (close_stdin);
904 :
905 183 : selinux_enabled = (0 < is_selinux_enabled ());
906 183 : cp_option_init (&x);
907 :
908 : /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
909 : we'll actually use backup_suffix_string. */
910 183 : backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
911 :
912 490 : while ((c = getopt_long (argc, argv, "abdfHilLprst:uvxPRS:T",
913 : long_opts, NULL))
914 : != -1)
915 : {
916 144 : switch (c)
917 : {
918 3 : case SPARSE_OPTION:
919 3 : x.sparse_mode = XARGMATCH ("--sparse", optarg,
920 : sparse_type_string, sparse_type);
921 2 : break;
922 :
923 35 : case 'a': /* Like -dpPR. */
924 35 : x.dereference = DEREF_NEVER;
925 35 : x.preserve_links = true;
926 35 : x.preserve_ownership = true;
927 35 : x.preserve_mode = true;
928 35 : x.preserve_timestamps = true;
929 35 : x.require_preserve = true;
930 35 : x.recursive = true;
931 35 : break;
932 :
933 22 : case 'b':
934 22 : make_backups = true;
935 22 : if (optarg)
936 6 : version_control_string = optarg;
937 22 : break;
938 :
939 0 : case COPY_CONTENTS_OPTION:
940 0 : copy_contents = true;
941 0 : break;
942 :
943 3 : case 'd':
944 3 : x.preserve_links = true;
945 3 : x.dereference = DEREF_NEVER;
946 3 : break;
947 :
948 7 : case 'f':
949 7 : x.unlink_dest_after_failed_open = true;
950 7 : break;
951 :
952 2 : case 'H':
953 2 : x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
954 2 : break;
955 :
956 7 : case 'i':
957 7 : x.interactive = I_ASK_USER;
958 7 : break;
959 :
960 6 : case 'l':
961 6 : x.hard_link = true;
962 6 : break;
963 :
964 1 : case 'L':
965 1 : x.dereference = DEREF_ALWAYS;
966 1 : break;
967 :
968 1 : case 'P':
969 1 : x.dereference = DEREF_NEVER;
970 1 : break;
971 :
972 2 : case NO_PRESERVE_ATTRIBUTES_OPTION:
973 2 : decode_preserve_arg (optarg, &x, false);
974 1 : break;
975 :
976 10 : case PRESERVE_ATTRIBUTES_OPTION:
977 10 : if (optarg == NULL)
978 : {
979 : /* Fall through to the case for `p' below. */
980 : }
981 : else
982 : {
983 9 : decode_preserve_arg (optarg, &x, true);
984 6 : x.require_preserve = true;
985 6 : break;
986 : }
987 :
988 : case 'p':
989 2 : x.preserve_ownership = true;
990 2 : x.preserve_mode = true;
991 2 : x.preserve_timestamps = true;
992 2 : x.require_preserve = true;
993 2 : break;
994 :
995 1 : case PARENTS_OPTION:
996 1 : parents_option = true;
997 1 : break;
998 :
999 1 : case 'r':
1000 : case 'R':
1001 1 : x.recursive = true;
1002 1 : break;
1003 :
1004 2 : case REPLY_OPTION: /* Deprecated */
1005 2 : x.interactive = XARGMATCH ("--reply", optarg,
1006 : reply_args, reply_vals);
1007 1 : error (0, 0,
1008 : _("the --reply option is deprecated; use -i or -f instead"));
1009 1 : break;
1010 :
1011 1 : case UNLINK_DEST_BEFORE_OPENING:
1012 1 : x.unlink_dest_before_opening = true;
1013 1 : break;
1014 :
1015 1 : case STRIP_TRAILING_SLASHES_OPTION:
1016 1 : remove_trailing_slashes = true;
1017 1 : break;
1018 :
1019 8 : case 's':
1020 8 : x.symbolic_link = true;
1021 8 : break;
1022 :
1023 7 : case 't':
1024 7 : if (target_directory)
1025 0 : error (EXIT_FAILURE, 0,
1026 : _("multiple target directories specified"));
1027 : else
1028 : {
1029 : struct stat st;
1030 7 : if (stat (optarg, &st) != 0)
1031 3 : error (EXIT_FAILURE, errno, _("accessing %s"), quote (optarg));
1032 4 : if (! S_ISDIR (st.st_mode))
1033 1 : error (EXIT_FAILURE, 0, _("target %s is not a directory"),
1034 : quote (optarg));
1035 : }
1036 3 : target_directory = optarg;
1037 3 : break;
1038 :
1039 3 : case 'T':
1040 3 : no_target_directory = true;
1041 3 : break;
1042 :
1043 6 : case 'u':
1044 6 : x.update = true;
1045 6 : break;
1046 :
1047 2 : case 'v':
1048 2 : x.verbose = true;
1049 2 : break;
1050 :
1051 1 : case 'x':
1052 1 : x.one_file_system = true;
1053 1 : break;
1054 :
1055 1 : case 'S':
1056 1 : make_backups = true;
1057 1 : backup_suffix_string = optarg;
1058 1 : break;
1059 :
1060 1 : case_GETOPT_HELP_CHAR;
1061 :
1062 1 : case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1063 :
1064 8 : default:
1065 8 : usage (EXIT_FAILURE);
1066 : }
1067 : }
1068 :
1069 163 : if (x.hard_link & x.symbolic_link)
1070 : {
1071 1 : error (0, 0, _("cannot make both hard and symbolic links"));
1072 1 : usage (EXIT_FAILURE);
1073 : }
1074 :
1075 162 : if (backup_suffix_string)
1076 1 : simple_backup_suffix = xstrdup (backup_suffix_string);
1077 :
1078 160 : x.backup_type = (make_backups
1079 : ? xget_version (_("backup type"),
1080 : version_control_string)
1081 162 : : no_backups);
1082 :
1083 160 : if (x.dereference == DEREF_UNDEFINED)
1084 : {
1085 123 : if (x.recursive)
1086 : /* This is compatible with FreeBSD. */
1087 1 : x.dereference = DEREF_NEVER;
1088 : else
1089 122 : x.dereference = DEREF_ALWAYS;
1090 : }
1091 :
1092 160 : if (x.recursive)
1093 33 : x.copy_as_regular = copy_contents;
1094 :
1095 : /* If --force (-f) was specified and we're in link-creation mode,
1096 : first remove any existing destination file. */
1097 160 : if (x.unlink_dest_after_failed_open & (x.hard_link | x.symbolic_link))
1098 1 : x.unlink_dest_before_opening = true;
1099 :
1100 160 : if (x.preserve_security_context)
1101 : {
1102 1 : if (!selinux_enabled)
1103 1 : error (EXIT_FAILURE, 0,
1104 : _("cannot preserve security context "
1105 : "without an SELinux-enabled kernel"));
1106 : }
1107 :
1108 : /* Allocate space for remembering copied and created files. */
1109 :
1110 159 : hash_init ();
1111 :
1112 159 : ok = do_copy (argc - optind, argv + optind,
1113 : target_directory, no_target_directory, &x);
1114 :
1115 101 : forget_all ();
1116 :
1117 101 : exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
1118 : }
|