1 /* cp.c -- file copying (main routines)
2 Copyright (C) 89, 90, 91, 1995-2009 Free Software Foundation, Inc.
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.
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.
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/>.
17 Written by Torbjorn Granlund, David MacKenzie, and Jim Meyering. */
21 #include <sys/types.h>
23 #include <selinux/selinux.h>
27 #include "backupfile.h"
31 #include "filenamecat.h"
32 #include "ignore-value.h"
34 #include "stat-time.h"
39 # define lchown(name, uid, gid) chown (name, uid, gid)
42 #define ASSIGN_BASENAME_STRDUPA(Dest, File_name) \
46 ASSIGN_STRDUPA (tmp_abns_, (File_name)); \
47 Dest = last_component (tmp_abns_); \
48 strip_trailing_slashes (Dest); \
52 /* The official name of this program (e.g., no `g' prefix). */
53 #define PROGRAM_NAME "cp"
56 proper_name_utf8 ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
57 proper_name ("David MacKenzie"), \
58 proper_name ("Jim Meyering")
60 /* Used by do_copy, make_dir_parents_private, and re_protect
61 to keep a list of leading directories whose protections
62 need to be fixed after copying. */
68 struct dir_attr
*next
;
71 /* For long options that have no equivalent short option, use a
72 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
75 COPY_CONTENTS_OPTION
= CHAR_MAX
+ 1,
76 NO_PRESERVE_ATTRIBUTES_OPTION
,
78 PRESERVE_ATTRIBUTES_OPTION
,
81 STRIP_TRAILING_SLASHES_OPTION
,
82 UNLINK_DEST_BEFORE_OPENING
85 /* True if the kernel is SELinux enabled. */
86 static bool selinux_enabled
;
88 /* If true, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
89 as its destination instead of the usual "e_dir/e_file." */
90 static bool parents_option
= false;
92 /* Remove any trailing slashes from each SOURCE argument. */
93 static bool remove_trailing_slashes
;
95 static char const *const sparse_type_string
[] =
97 "never", "auto", "always", NULL
99 static enum Sparse_type
const sparse_type
[] =
101 SPARSE_NEVER
, SPARSE_AUTO
, SPARSE_ALWAYS
103 ARGMATCH_VERIFY (sparse_type_string
, sparse_type
);
105 static struct option
const long_opts
[] =
107 {"archive", no_argument
, NULL
, 'a'},
108 {"backup", optional_argument
, NULL
, 'b'},
109 {"copy-contents", no_argument
, NULL
, COPY_CONTENTS_OPTION
},
110 {"dereference", no_argument
, NULL
, 'L'},
111 {"force", no_argument
, NULL
, 'f'},
112 {"interactive", no_argument
, NULL
, 'i'},
113 {"link", no_argument
, NULL
, 'l'},
114 {"no-clobber", no_argument
, NULL
, 'n'},
115 {"no-dereference", no_argument
, NULL
, 'P'},
116 {"no-preserve", required_argument
, NULL
, NO_PRESERVE_ATTRIBUTES_OPTION
},
117 {"no-target-directory", no_argument
, NULL
, 'T'},
118 {"one-file-system", no_argument
, NULL
, 'x'},
119 {"parents", no_argument
, NULL
, PARENTS_OPTION
},
120 {"path", no_argument
, NULL
, PARENTS_OPTION
}, /* Deprecated. */
121 {"preserve", optional_argument
, NULL
, PRESERVE_ATTRIBUTES_OPTION
},
122 {"recursive", no_argument
, NULL
, 'R'},
123 {"remove-destination", no_argument
, NULL
, UNLINK_DEST_BEFORE_OPENING
},
124 {"sparse", required_argument
, NULL
, SPARSE_OPTION
},
125 {"reflink", no_argument
, NULL
, REFLINK_OPTION
},
126 {"strip-trailing-slashes", no_argument
, NULL
, STRIP_TRAILING_SLASHES_OPTION
},
127 {"suffix", required_argument
, NULL
, 'S'},
128 {"symbolic-link", no_argument
, NULL
, 's'},
129 {"target-directory", required_argument
, NULL
, 't'},
130 {"update", no_argument
, NULL
, 'u'},
131 {"verbose", no_argument
, NULL
, 'v'},
132 {GETOPT_HELP_OPTION_DECL
},
133 {GETOPT_VERSION_OPTION_DECL
},
140 if (status
!= EXIT_SUCCESS
)
141 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
146 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
147 or: %s [OPTION]... SOURCE... DIRECTORY\n\
148 or: %s [OPTION]... -t DIRECTORY SOURCE...\n\
150 program_name
, program_name
, program_name
);
152 Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
156 Mandatory arguments to long options are mandatory for short options too.\n\
159 -a, --archive same as -dR --preserve=all\n\
160 --backup[=CONTROL] make a backup of each existing destination file\n\
161 -b like --backup but does not accept an argument\n\
162 --copy-contents copy contents of special files when recursive\n\
163 -d same as --no-dereference --preserve=links\n\
166 -f, --force if an existing destination file cannot be\n\
167 opened, remove it and try again (redundant if\n\
168 the -n option is used)\n\
169 -i, --interactive prompt before overwrite (overrides a previous -n\n\
171 -H follow command-line symbolic links in SOURCE\n\
174 -l, --link link files instead of copying\n\
175 -L, --dereference always follow symbolic links in SOURCE\n\
178 -n, --no-clobber do not overwrite an existing file (overrides\n\
179 a previous -i option)\n\
180 -P, --no-dereference never follow symbolic links in SOURCE\n\
183 -p same as --preserve=mode,ownership,timestamps\n\
184 --preserve[=ATTR_LIST] preserve the specified attributes (default:\n\
185 mode,ownership,timestamps), if possible\n\
186 additional attributes: context, links, xattr,\n\
190 --no-preserve=ATTR_LIST don't preserve the specified attributes\n\
191 --parents use full source file name under DIRECTORY\n\
194 -R, -r, --recursive copy directories recursively\n\
195 --reflink perform a lightweight (CoW/clone) copy\n\
196 --remove-destination remove each existing destination file before\n\
197 attempting to open it (contrast with --force)\n\
200 --sparse=WHEN control creation of sparse files\n\
201 --strip-trailing-slashes remove any trailing slashes from each SOURCE\n\
205 -s, --symbolic-link make symbolic links instead of copying\n\
206 -S, --suffix=SUFFIX override the usual backup suffix\n\
207 -t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\
208 -T, --no-target-directory treat DEST as a normal file\n\
211 -u, --update copy only when the SOURCE file is newer\n\
212 than the destination file or when the\n\
213 destination file is missing\n\
214 -v, --verbose explain what is being done\n\
215 -x, --one-file-system stay on this file system\n\
217 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
218 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
221 By default, sparse SOURCE files are detected by a crude heuristic and the\n\
222 corresponding DEST file is made sparse as well. That is the behavior\n\
223 selected by --sparse=auto. Specify --sparse=always to create a sparse DEST\n\
224 file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\
225 Use --sparse=never to inhibit creation of sparse files.\n\
229 The backup suffix is `~', unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n\
230 The version control method may be selected via the --backup option or through\n\
231 the VERSION_CONTROL environment variable. Here are the values:\n\
235 none, off never make backups (even if --backup is given)\n\
236 numbered, t make numbered backups\n\
237 existing, nil numbered if numbered backups exist, simple otherwise\n\
238 simple, never always make simple backups\n\
242 As a special case, cp makes a backup of SOURCE when the force and backup\n\
243 options are given and SOURCE and DEST are the same name for an existing,\n\
246 emit_bug_reporting_address ();
251 /* Ensure that the parent directories of CONST_DST_NAME have the
252 correct protections, for the --parents option. This is done
253 after all copying has been completed, to allow permissions
254 that don't include user write/execute.
256 SRC_OFFSET is the index in CONST_DST_NAME of the beginning of the
257 source directory name.
259 ATTR_LIST is a null-terminated linked list of structures that
260 indicates the end of the filename of each intermediate directory
261 in CONST_DST_NAME that may need to have its attributes changed.
262 The command `cp --parents --preserve a/b/c d/e_dir' changes the
263 attributes of the directories d/e_dir/a and d/e_dir/a/b to match
264 the corresponding source directories regardless of whether they
265 existed before the `cp' command was given.
267 Return true if the parent of CONST_DST_NAME and any intermediate
268 directories specified by ATTR_LIST have the proper permissions
272 re_protect (char const *const_dst_name
, size_t src_offset
,
273 struct dir_attr
*attr_list
, const struct cp_options
*x
)
276 char *dst_name
; /* A copy of CONST_DST_NAME we can change. */
277 char *src_name
; /* The source name in `dst_name'. */
279 ASSIGN_STRDUPA (dst_name
, const_dst_name
);
280 src_name
= dst_name
+ src_offset
;
282 for (p
= attr_list
; p
; p
= p
->next
)
284 dst_name
[p
->slash_offset
] = '\0';
286 /* Adjust the times (and if possible, ownership) for the copy.
287 chown turns off set[ug]id bits for non-root,
288 so do the chmod last. */
290 if (x
->preserve_timestamps
)
292 struct timespec timespec
[2];
294 timespec
[0] = get_stat_atime (&p
->st
);
295 timespec
[1] = get_stat_mtime (&p
->st
);
297 if (utimens (dst_name
, timespec
))
299 error (0, errno
, _("failed to preserve times for %s"),
305 if (x
->preserve_ownership
)
307 if (lchown (dst_name
, p
->st
.st_uid
, p
->st
.st_gid
) != 0)
309 if (! chown_failure_ok (x
))
311 error (0, errno
, _("failed to preserve ownership for %s"),
315 /* Failing to preserve ownership is OK. Still, try to preserve
316 the group, but ignore the possible error. */
317 ignore_value (lchown (dst_name
, -1, p
->st
.st_gid
));
321 if (x
->preserve_mode
)
323 if (copy_acl (src_name
, -1, dst_name
, -1, p
->st
.st_mode
) != 0)
326 else if (p
->restore_mode
)
328 if (lchmod (dst_name
, p
->st
.st_mode
) != 0)
330 error (0, errno
, _("failed to preserve permissions for %s"),
336 dst_name
[p
->slash_offset
] = '/';
341 /* Ensure that the parent directory of CONST_DIR exists, for
342 the --parents option.
344 SRC_OFFSET is the index in CONST_DIR (which is a destination
345 directory) of the beginning of the source directory name.
346 Create any leading directories that don't already exist.
347 If VERBOSE_FMT_STRING is nonzero, use it as a printf format
348 string for printing a message after successfully making a directory.
349 The format should take two string arguments: the names of the
350 source and destination directories.
351 Creates a linked list of attributes of intermediate directories,
352 *ATTR_LIST, for re_protect to use after calling copy.
353 Sets *NEW_DST if this function creates parent of CONST_DIR.
355 Return true if parent of CONST_DIR exists as a directory with the proper
356 permissions when done. */
358 /* FIXME: Synch this function with the one in ../lib/mkdir-p.c. */
361 make_dir_parents_private (char const *const_dir
, size_t src_offset
,
362 char const *verbose_fmt_string
,
363 struct dir_attr
**attr_list
, bool *new_dst
,
364 const struct cp_options
*x
)
367 char *dir
; /* A copy of CONST_DIR we can change. */
368 char *src
; /* Source name in DIR. */
369 char *dst_dir
; /* Leading directory of DIR. */
370 size_t dirlen
; /* Length of DIR. */
372 ASSIGN_STRDUPA (dir
, const_dir
);
374 src
= dir
+ src_offset
;
376 dirlen
= dir_len (dir
);
377 dst_dir
= alloca (dirlen
+ 1);
378 memcpy (dst_dir
, dir
, dirlen
);
379 dst_dir
[dirlen
] = '\0';
383 if (stat (dst_dir
, &stats
) != 0)
385 /* A parent of CONST_DIR does not exist.
386 Make all missing intermediate directories. */
390 while (*slash
== '/')
392 while ((slash
= strchr (slash
, '/')))
394 struct dir_attr
*new IF_LINT (= NULL
);
398 missing_dir
= (stat (dir
, &stats
) != 0);
400 if (missing_dir
| x
->preserve_ownership
| x
->preserve_mode
401 | x
->preserve_timestamps
)
403 /* Add this directory to the list of directories whose
404 modes might need fixing later. */
406 int src_errno
= (stat (src
, &src_st
) != 0
408 : S_ISDIR (src_st
.st_mode
)
413 error (0, src_errno
, _("failed to get attributes of %s"),
418 new = xmalloc (sizeof *new);
420 new->slash_offset
= slash
- dir
;
421 new->restore_mode
= false;
422 new->next
= *attr_list
;
429 mode_t omitted_permissions
;
432 /* This component does not exist. We must set
433 *new_dst and new->st.st_mode inside this loop because,
434 for example, in the command `cp --parents ../a/../b/c e_dir',
435 make_dir_parents_private creates only e_dir/../a if
436 ./b already exists. */
438 src_mode
= new->st
.st_mode
;
440 /* If the ownership or special mode bits might change,
441 omit some permissions at first, so unauthorized users
442 cannot nip in before the file is ready. */
443 omitted_permissions
= (src_mode
444 & (x
->preserve_ownership
450 /* POSIX says mkdir's behavior is implementation-defined when
451 (src_mode & ~S_IRWXUGO) != 0. However, common practice is
452 to ask mkdir to copy all the CHMOD_MODE_BITS, letting mkdir
453 decide what to do with S_ISUID | S_ISGID | S_ISVTX. */
454 mkdir_mode
= src_mode
& CHMOD_MODE_BITS
& ~omitted_permissions
;
455 if (mkdir (dir
, mkdir_mode
) != 0)
457 error (0, errno
, _("cannot make directory %s"),
463 if (verbose_fmt_string
!= NULL
)
464 printf (verbose_fmt_string
, src
, dir
);
467 /* We need search and write permissions to the new directory
468 for writing the directory's contents. Check if these
469 permissions are there. */
471 if (lstat (dir
, &stats
))
473 error (0, errno
, _("failed to get attributes of %s"),
479 if (! x
->preserve_mode
)
481 if (omitted_permissions
& ~stats
.st_mode
)
482 omitted_permissions
&= ~ cached_umask ();
483 if (omitted_permissions
& ~stats
.st_mode
484 || (stats
.st_mode
& S_IRWXU
) != S_IRWXU
)
486 new->st
.st_mode
= stats
.st_mode
| omitted_permissions
;
487 new->restore_mode
= true;
491 if ((stats
.st_mode
& S_IRWXU
) != S_IRWXU
)
493 /* Make the new directory searchable and writable.
494 The original permissions will be restored later. */
496 if (lchmod (dir
, stats
.st_mode
| S_IRWXU
) != 0)
498 error (0, errno
, _("setting permissions for %s"),
504 else if (!S_ISDIR (stats
.st_mode
))
506 error (0, 0, _("%s exists but is not a directory"),
514 /* Avoid unnecessary calls to `stat' when given
515 file names containing multiple adjacent slashes. */
516 while (*slash
== '/')
521 /* We get here if the parent of DIR already exists. */
523 else if (!S_ISDIR (stats
.st_mode
))
525 error (0, 0, _("%s exists but is not a directory"), quote (dst_dir
));
535 /* FILE is the last operand of this command.
536 Return true if FILE is a directory.
537 But report an error and exit if there is a problem accessing FILE,
538 or if FILE does not exist but would have to refer to an existing
539 directory if it referred to anything at all.
541 If the file exists, store the file's status into *ST.
542 Otherwise, set *NEW_DST. */
545 target_directory_operand (char const *file
, struct stat
*st
, bool *new_dst
)
547 int err
= (stat (file
, st
) == 0 ? 0 : errno
);
548 bool is_a_dir
= !err
&& S_ISDIR (st
->st_mode
);
552 error (EXIT_FAILURE
, err
, _("accessing %s"), quote (file
));
558 /* Scan the arguments, and copy each by calling copy.
559 Return true if successful. */
562 do_copy (int n_files
, char **file
, const char *target_directory
,
563 bool no_target_directory
, struct cp_options
*x
)
566 bool new_dst
= false;
569 if (n_files
<= !target_directory
)
572 error (0, 0, _("missing file operand"));
574 error (0, 0, _("missing destination file operand after %s"),
576 usage (EXIT_FAILURE
);
579 if (no_target_directory
)
581 if (target_directory
)
582 error (EXIT_FAILURE
, 0,
583 _("cannot combine --target-directory (-t) "
584 "and --no-target-directory (-T)"));
587 error (0, 0, _("extra operand %s"), quote (file
[2]));
588 usage (EXIT_FAILURE
);
591 else if (!target_directory
)
594 && target_directory_operand (file
[n_files
- 1], &sb
, &new_dst
))
595 target_directory
= file
[--n_files
];
596 else if (2 < n_files
)
597 error (EXIT_FAILURE
, 0, _("target %s is not a directory"),
598 quote (file
[n_files
- 1]));
601 if (target_directory
)
603 /* cp file1...filen edir
604 Copy the files `file1' through `filen'
605 to the existing directory `edir'. */
608 /* Initialize these hash tables only if we'll need them.
609 The problems they're used to detect can arise only if
610 there are two or more files to copy. */
617 for (i
= 0; i
< n_files
; i
++)
620 bool parent_exists
= true; /* True if dir_name (dst_name) exists. */
621 struct dir_attr
*attr_list
;
622 char *arg_in_concat
= NULL
;
625 /* Trailing slashes are meaningful (i.e., maybe worth preserving)
626 only in the source file names. */
627 if (remove_trailing_slashes
)
628 strip_trailing_slashes (arg
);
632 char *arg_no_trailing_slash
;
634 /* Use `arg' without trailing slashes in constructing destination
635 file names. Otherwise, we can end up trying to create a
636 directory via `mkdir ("dst/foo/"...', which is not portable.
637 It fails, due to the trailing slash, on at least
638 NetBSD 1.[34] systems. */
639 ASSIGN_STRDUPA (arg_no_trailing_slash
, arg
);
640 strip_trailing_slashes (arg_no_trailing_slash
);
642 /* Append all of `arg' (minus any trailing slash) to `dest'. */
643 dst_name
= file_name_concat (target_directory
,
644 arg_no_trailing_slash
,
647 /* For --parents, we have to make sure that the directory
648 dir_name (dst_name) exists. We may have to create a few
649 leading directories. */
651 (make_dir_parents_private
652 (dst_name
, arg_in_concat
- dst_name
,
653 (x
->verbose
? "%s -> %s\n" : NULL
),
654 &attr_list
, &new_dst
, x
));
659 /* Append the last component of `arg' to `target_directory'. */
661 ASSIGN_BASENAME_STRDUPA (arg_base
, arg
);
662 /* For `cp -R source/.. dest', don't copy into `dest/..'. */
663 dst_name
= (STREQ (arg_base
, "..")
664 ? xstrdup (target_directory
)
665 : file_name_concat (target_directory
, arg_base
,
671 /* make_dir_parents_private failed, so don't even
678 ok
&= copy (arg
, dst_name
, new_dst
, x
, ©_into_self
, NULL
);
681 ok
&= re_protect (dst_name
, arg_in_concat
- dst_name
,
689 struct dir_attr
*p
= attr_list
;
690 attr_list
= attr_list
->next
;
698 else /* !target_directory */
700 char const *new_dest
;
701 char const *source
= file
[0];
702 char const *dest
= file
[1];
708 _("with --parents, the destination must be a directory"));
709 usage (EXIT_FAILURE
);
712 /* When the force and backup options have been specified and
713 the source and destination are the same name for an existing
714 regular file, convert the user's command, e.g.,
715 `cp --force --backup foo foo' to `cp --force foo fooSUFFIX'
716 where SUFFIX is determined by any version control options used. */
718 if (x
->unlink_dest_after_failed_open
719 && x
->backup_type
!= no_backups
720 && STREQ (source
, dest
)
721 && !new_dst
&& S_ISREG (sb
.st_mode
))
723 static struct cp_options x_tmp
;
725 new_dest
= find_backup_file_name (dest
, x
->backup_type
);
726 /* Set x->backup_type to `no_backups' so that the normal backup
727 mechanism is not used when performing the actual copy.
728 backup_type must be set to `no_backups' only *after* the above
729 call to find_backup_file_name -- that function uses
730 backup_type to determine the suffix it applies. */
732 x_tmp
.backup_type
= no_backups
;
740 ok
= copy (source
, new_dest
, 0, x
, &unused
, NULL
);
747 cp_option_init (struct cp_options
*x
)
749 cp_options_default (x
);
750 x
->copy_as_regular
= true;
751 x
->dereference
= DEREF_UNDEFINED
;
752 x
->unlink_dest_before_opening
= false;
753 x
->unlink_dest_after_failed_open
= false;
754 x
->hard_link
= false;
755 x
->interactive
= I_UNSPECIFIED
;
756 x
->move_mode
= false;
757 x
->one_file_system
= false;
760 x
->preserve_ownership
= false;
761 x
->preserve_links
= false;
762 x
->preserve_mode
= false;
763 x
->preserve_timestamps
= false;
764 x
->preserve_security_context
= false;
765 x
->require_preserve_context
= false;
766 x
->preserve_xattr
= false;
767 x
->reduce_diagnostics
= false;
768 x
->require_preserve_xattr
= false;
770 x
->require_preserve
= false;
771 x
->recursive
= false;
772 x
->sparse_mode
= SPARSE_AUTO
;
773 x
->symbolic_link
= false;
778 x
->stdin_tty
= false;
783 /* By default, refuse to open a dangling destination symlink, because
784 in general one cannot do that safely, give the current semantics of
785 open's O_EXCL flag, (which POSIX doesn't even allow cp to use, btw).
786 But POSIX requires it. */
787 x
->open_dangling_dest_symlink
= getenv ("POSIXLY_CORRECT") != NULL
;
793 /* Given a string, ARG, containing a comma-separated list of arguments
794 to the --preserve option, set the appropriate fields of X to ON_OFF. */
796 decode_preserve_arg (char const *arg
, struct cp_options
*x
, bool on_off
)
808 static enum File_attribute
const preserve_vals
[] =
810 PRESERVE_MODE
, PRESERVE_TIMESTAMPS
,
811 PRESERVE_OWNERSHIP
, PRESERVE_LINK
, PRESERVE_CONTEXT
, PRESERVE_XATTR
,
814 /* Valid arguments to the `--preserve' option. */
815 static char const* const preserve_args
[] =
817 "mode", "timestamps",
818 "ownership", "links", "context", "xattr", "all", NULL
820 ARGMATCH_VERIFY (preserve_args
, preserve_vals
);
822 char *arg_writable
= xstrdup (arg
);
823 char *s
= arg_writable
;
826 /* find next comma */
827 char *comma
= strchr (s
, ',');
828 enum File_attribute val
;
830 /* If we found a comma, put a NUL in its place and advance. */
835 val
= XARGMATCH ("--preserve", s
, preserve_args
, preserve_vals
);
839 x
->preserve_mode
= on_off
;
842 case PRESERVE_TIMESTAMPS
:
843 x
->preserve_timestamps
= on_off
;
846 case PRESERVE_OWNERSHIP
:
847 x
->preserve_ownership
= on_off
;
851 x
->preserve_links
= on_off
;
854 case PRESERVE_CONTEXT
:
855 x
->preserve_security_context
= on_off
;
856 x
->require_preserve_context
= on_off
;
860 x
->preserve_xattr
= on_off
;
861 x
->require_preserve_xattr
= on_off
;
865 x
->preserve_mode
= on_off
;
866 x
->preserve_timestamps
= on_off
;
867 x
->preserve_ownership
= on_off
;
868 x
->preserve_links
= on_off
;
870 x
->preserve_security_context
= on_off
;
871 x
->preserve_xattr
= on_off
;
885 main (int argc
, char **argv
)
889 bool make_backups
= false;
890 char *backup_suffix_string
;
891 char *version_control_string
= NULL
;
893 bool copy_contents
= false;
894 char *target_directory
= NULL
;
895 bool no_target_directory
= false;
897 initialize_main (&argc
, &argv
);
898 set_program_name (argv
[0]);
899 setlocale (LC_ALL
, "");
900 bindtextdomain (PACKAGE
, LOCALEDIR
);
901 textdomain (PACKAGE
);
903 atexit (close_stdin
);
905 selinux_enabled
= (0 < is_selinux_enabled ());
908 /* FIXME: consider not calling getenv for SIMPLE_BACKUP_SUFFIX unless
909 we'll actually use backup_suffix_string. */
910 backup_suffix_string
= getenv ("SIMPLE_BACKUP_SUFFIX");
912 while ((c
= getopt_long (argc
, argv
, "abdfHilLnprst:uvxPRS:T",
919 x
.sparse_mode
= XARGMATCH ("--sparse", optarg
,
920 sparse_type_string
, sparse_type
);
927 case 'a': /* Like -dR --preserve=all with reduced failure diagnostics. */
928 x
.dereference
= DEREF_NEVER
;
929 x
.preserve_links
= true;
930 x
.preserve_ownership
= true;
931 x
.preserve_mode
= true;
932 x
.preserve_timestamps
= true;
933 x
.require_preserve
= true;
935 x
.preserve_security_context
= true;
936 x
.preserve_xattr
= true;
937 x
.reduce_diagnostics
= true;
944 version_control_string
= optarg
;
947 case COPY_CONTENTS_OPTION
:
948 copy_contents
= true;
952 x
.preserve_links
= true;
953 x
.dereference
= DEREF_NEVER
;
957 x
.unlink_dest_after_failed_open
= true;
961 x
.dereference
= DEREF_COMMAND_LINE_ARGUMENTS
;
965 x
.interactive
= I_ASK_USER
;
973 x
.dereference
= DEREF_ALWAYS
;
977 x
.interactive
= I_ALWAYS_NO
;
981 x
.dereference
= DEREF_NEVER
;
984 case NO_PRESERVE_ATTRIBUTES_OPTION
:
985 decode_preserve_arg (optarg
, &x
, false);
988 case PRESERVE_ATTRIBUTES_OPTION
:
991 /* Fall through to the case for `p' below. */
995 decode_preserve_arg (optarg
, &x
, true);
996 x
.require_preserve
= true;
1001 x
.preserve_ownership
= true;
1002 x
.preserve_mode
= true;
1003 x
.preserve_timestamps
= true;
1004 x
.require_preserve
= true;
1007 case PARENTS_OPTION
:
1008 parents_option
= true;
1016 case UNLINK_DEST_BEFORE_OPENING
:
1017 x
.unlink_dest_before_opening
= true;
1020 case STRIP_TRAILING_SLASHES_OPTION
:
1021 remove_trailing_slashes
= true;
1025 x
.symbolic_link
= true;
1029 if (target_directory
)
1030 error (EXIT_FAILURE
, 0,
1031 _("multiple target directories specified"));
1035 if (stat (optarg
, &st
) != 0)
1036 error (EXIT_FAILURE
, errno
, _("accessing %s"), quote (optarg
));
1037 if (! S_ISDIR (st
.st_mode
))
1038 error (EXIT_FAILURE
, 0, _("target %s is not a directory"),
1041 target_directory
= optarg
;
1045 no_target_directory
= true;
1057 x
.one_file_system
= true;
1061 make_backups
= true;
1062 backup_suffix_string
= optarg
;
1065 case_GETOPT_HELP_CHAR
;
1067 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
1070 usage (EXIT_FAILURE
);
1074 if (x
.hard_link
& x
.symbolic_link
)
1076 error (0, 0, _("cannot make both hard and symbolic links"));
1077 usage (EXIT_FAILURE
);
1080 if (make_backups
&& x
.interactive
== I_ALWAYS_NO
)
1083 _("options --backup and --no-clobber are mutually exclusive"));
1084 usage (EXIT_FAILURE
);
1087 if (x
.reflink
&& x
.sparse_mode
!= SPARSE_AUTO
)
1089 error (0, 0, _("--reflink can be used only with --sparse=auto"));
1090 usage (EXIT_FAILURE
);
1093 if (backup_suffix_string
)
1094 simple_backup_suffix
= xstrdup (backup_suffix_string
);
1096 x
.backup_type
= (make_backups
1097 ? xget_version (_("backup type"),
1098 version_control_string
)
1101 if (x
.dereference
== DEREF_UNDEFINED
)
1104 /* This is compatible with FreeBSD. */
1105 x
.dereference
= DEREF_NEVER
;
1107 x
.dereference
= DEREF_ALWAYS
;
1111 x
.copy_as_regular
= copy_contents
;
1113 /* If --force (-f) was specified and we're in link-creation mode,
1114 first remove any existing destination file. */
1115 if (x
.unlink_dest_after_failed_open
& (x
.hard_link
| x
.symbolic_link
))
1116 x
.unlink_dest_before_opening
= true;
1118 if (x
.preserve_security_context
)
1120 if (!selinux_enabled
)
1121 error (EXIT_FAILURE
, 0,
1122 _("cannot preserve security context "
1123 "without an SELinux-enabled kernel"));
1127 if (x
.require_preserve_xattr
)
1128 error (EXIT_FAILURE
, 0, _("cannot preserve extended attributes, cp is "
1129 "built without xattr support"));
1132 /* Allocate space for remembering copied and created files. */
1136 ok
= do_copy (argc
- optind
, argv
+ optind
,
1137 target_directory
, no_target_directory
, &x
);
1141 exit (ok
? EXIT_SUCCESS
: EXIT_FAILURE
);