/* cp.c -- file copying (main routines) This is the cp utility
Copyright (C) 1989-2018 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Written by Torbjorn Granlund, David MacKenzie, and Jim Meyering. */ The GNUv3 license
#include <config.h> Provides system specific information
#include <stdio.h> Provides standard I/O capability
#include <sys/types.h> Provides system data types
#include <getopt.h> ...!includes auto-comment...
#include <selinux/selinux.h> ...!includes auto-comment......!includes auto-comment...
#include "system.h" ...!includes auto-comment...
#include "argmatch.h" ...!includes auto-comment...
#include "backupfile.h" ...!includes auto-comment...
#include "copy.h" ...!includes auto-comment...
#include "cp-hash.h" ...!includes auto-comment......!includes auto-comment...
#include "die.h" ...!includes auto-comment...
#include "error.h" ...!includes auto-comment...
#include "filenamecat.h" ...!includes auto-comment...
#include "ignore-value.h" ...!includes auto-comment...
#include "quote.h" ...!includes auto-comment...
#include "stat-time.h" ...!includes auto-comment...
#include "utimens.h" ...!includes auto-comment...
#include "acl.h" ...!includes auto-comment...
#if ! HAVE_LCHOWN Line 39
# define lchown(name, uid, gid) chown (name, uid, gid) Line 40
#endif Line 41
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "cp" Line 44
#define AUTHORS \ Line 46
proper_name ("Torbjorn Granlund"), \ Line 47
proper_name ("David MacKenzie"), \ Line 48
proper_name ("Jim Meyering") Line 49
/* Used by do_copy, make_dir_parents_private, and re_protect
to keep a list of leading directories whose protections
need to be fixed after copying. */
struct dir_attr Line 54
{
struct stat st; Line 56
bool restore_mode; Line 57
size_t slash_offset; Line 58
struct dir_attr *next; Line 59
}; Block 1
/* For long options that have no equivalent short option, use a
non-character as a pseudo short option, starting with CHAR_MAX + 1. */
enum Line 64
{
ATTRIBUTES_ONLY_OPTION = CHAR_MAX + 1, Line 66
COPY_CONTENTS_OPTION, Line 67
NO_PRESERVE_ATTRIBUTES_OPTION, Line 68
PARENTS_OPTION, Line 69
PRESERVE_ATTRIBUTES_OPTION, Line 70
REFLINK_OPTION, Line 71
SPARSE_OPTION, Line 72
STRIP_TRAILING_SLASHES_OPTION, Line 73
UNLINK_DEST_BEFORE_OPENING Line 74
}; Block 2
/* True if the kernel is SELinux enabled. */
static bool selinux_enabled; Line 78
/* If true, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
as its destination instead of the usual "e_dir/e_file." */
static bool parents_option = false; Line 82
/* Remove any trailing slashes from each SOURCE argument. */
static bool remove_trailing_slashes; Line 85
static char const *const sparse_type_string[] = Line 87
{
"never", "auto", "always", NULL Line 89
}; Block 3
static enum Sparse_type const sparse_type[] = Line 91
{
SPARSE_NEVER, SPARSE_AUTO, SPARSE_ALWAYS Line 93
}; Block 4
ARGMATCH_VERIFY (sparse_type_string, sparse_type); Line 95
static char const *const reflink_type_string[] = Line 97
{
"auto", "always", "never", NULL Line 99
}; Block 5
static enum Reflink_type const reflink_type[] = Line 101
{
REFLINK_AUTO, REFLINK_ALWAYS, REFLINK_NEVER Line 103
}; Block 6
ARGMATCH_VERIFY (reflink_type_string, reflink_type); Line 105
static struct option const long_opts[] = Line 107
{
{"archive", no_argument, NULL, 'a'}, Line 109
{"attributes-only", no_argument, NULL, ATTRIBUTES_ONLY_OPTION}, Line 110
{"backup", optional_argument, NULL, 'b'}, Line 111
{"copy-contents", no_argument, NULL, COPY_CONTENTS_OPTION}, Line 112
{"dereference", no_argument, NULL, 'L'}, Line 113
{"force", no_argument, NULL, 'f'}, Line 114
{"interactive", no_argument, NULL, 'i'}, Line 115
{"link", no_argument, NULL, 'l'}, Line 116
{"no-clobber", no_argument, NULL, 'n'}, Line 117
{"no-dereference", no_argument, NULL, 'P'}, Line 118
{"no-preserve", required_argument, NULL, NO_PRESERVE_ATTRIBUTES_OPTION}, Line 119
{"no-target-directory", no_argument, NULL, 'T'}, Line 120
{"one-file-system", no_argument, NULL, 'x'}, Line 121
{"parents", no_argument, NULL, PARENTS_OPTION}, Line 122
{"path", no_argument, NULL, PARENTS_OPTION}, /* Deprecated. */ Line 123
{"preserve", optional_argument, NULL, PRESERVE_ATTRIBUTES_OPTION}, Line 124
{"recursive", no_argument, NULL, 'R'}, Line 125
{"remove-destination", no_argument, NULL, UNLINK_DEST_BEFORE_OPENING}, Line 126
{"sparse", required_argument, NULL, SPARSE_OPTION}, Line 127
{"reflink", optional_argument, NULL, REFLINK_OPTION}, Line 128
{"strip-trailing-slashes", no_argument, NULL, STRIP_TRAILING_SLASHES_OPTION}, Line 129
{"suffix", required_argument, NULL, 'S'}, Line 130
{"symbolic-link", no_argument, NULL, 's'}, Line 131
{"target-directory", required_argument, NULL, 't'}, Line 132
{"update", no_argument, NULL, 'u'}, Line 133
{"verbose", no_argument, NULL, 'v'}, Line 134
{GETOPT_SELINUX_CONTEXT_OPTION_DECL}, Line 135
{GETOPT_HELP_OPTION_DECL}, Line 136
{GETOPT_VERSION_OPTION_DECL}, Line 137
{NULL, 0, NULL, 0} Line 138
}; Block 7
void Line 141
usage (int status) Line 142
{
if (status != EXIT_SUCCESS) Line 144
emit_try_help (); ...!common auto-comment...
else Line 146
{
printf (_("\ Line 148
Usage: %s [OPTION]... [-T] SOURCE DEST\n\ Line 149
or: %s [OPTION]... SOURCE... DIRECTORY\n\ Line 150
or: %s [OPTION]... -t DIRECTORY SOURCE...\n\ Line 151
"), Line 152
program_name, program_name, program_name); Line 153
fputs (_("\ Line 154
Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\ Line 155
"), stdout); Line 156
emit_mandatory_arg_note (); ...!common auto-comment...
fputs (_("\ Line 160
-a, --archive same as -dR --preserve=all\n\ Line 161
--attributes-only don't copy the file data, just the attributes\n\ Line 162
--backup[=CONTROL] make a backup of each existing destination file\ Line 163
\n\
-b like --backup but does not accept an argument\n\ Line 165
--copy-contents copy contents of special files when recursive\n\ Line 166
-d same as --no-dereference --preserve=links\n\ Line 167
"), stdout); Line 168
fputs (_("\ Line 169
-f, --force if an existing destination file cannot be\n\ Line 170
opened, remove it and try again (this option\n\Line 171
is ignored when the -n option is also used)\n\ Line 172
-i, --interactive prompt before overwrite (overrides a previous -n\Line 173...!syscalls auto-comment...
\n\
option)\n\ Line 175
-H follow command-line symbolic links in SOURCE\n\ Line 176
"), stdout); Line 177
fputs (_("\ Line 178
-l, --link hard link files instead of copying\n\ Line 179
-L, --dereference always follow symbolic links in SOURCE\n\ Line 180
"), stdout); Line 181
fputs (_("\ Line 182
-n, --no-clobber do not overwrite an existing file (overrides\n\ Line 183
a previous -i option)\n\ Line 184
-P, --no-dereference never follow symbolic links in SOURCE\n\ Line 185
"), stdout); Line 186
fputs (_("\ Line 187
-p same as --preserve=mode,ownership,timestamps\n\ Line 188
--preserve[=ATTR_LIST] preserve the specified attributes (default:\n\ Line 189
mode,ownership,timestamps), if possible\n\ Line 190
additional attributes: context, links, xattr,\ Line 191
\n\
all\n\ Line 193
"), stdout); Line 194
fputs (_("\ Line 195
--no-preserve=ATTR_LIST don't preserve the specified attributes\n\ Line 196
--parents use full source file name under DIRECTORY\n\ Line 197
"), stdout); Line 198
fputs (_("\ Line 199
-R, -r, --recursive copy directories recursively\n\ Line 200
--reflink[=WHEN] control clone/CoW copies. See below\n\ Line 201
--remove-destination remove each existing destination file before\n\ Line 202
attempting to open it (contrast with --force)\ Line 203
\n"), stdout); Line 204
fputs (_("\ Line 205
--sparse=WHEN control creation of sparse files. See below\n\ Line 206
--strip-trailing-slashes remove any trailing slashes from each SOURCE\n\ Line 207
argument\n\ Line 208
"), stdout); Line 209
fputs (_("\ Line 210
-s, --symbolic-link make symbolic links instead of copying\n\ Line 211
-S, --suffix=SUFFIX override the usual backup suffix\n\ Line 212
-t, --target-directory=DIRECTORY copy all SOURCE arguments into DIRECTORY\n\ Line 213
-T, --no-target-directory treat DEST as a normal file\n\ Line 214
"), stdout); Line 215
fputs (_("\ Line 216
-u, --update copy only when the SOURCE file is newer\n\ Line 217
than the destination file or when the\n\ Line 218
destination file is missing\n\ Line 219
-v, --verbose explain what is being done\n\ Line 220
-x, --one-file-system stay on this file system\n\ Line 221
"), stdout); Line 222
fputs (_("\ Line 223
-Z set SELinux security context of destination\n\ Line 224
file to default type\n\ Line 225
--context[=CTX] like -Z, or if CTX is specified then set the\n\ Line 226
SELinux or SMACK security context to CTX\n\ Line 227
"), stdout); Line 228
fputs (HELP_OPTION_DESCRIPTION, stdout); Line 229
fputs (VERSION_OPTION_DESCRIPTION, stdout); Line 230
fputs (_("\ Line 231
\n\
By default, sparse SOURCE files are detected by a crude heuristic and the\n\ Line 233
corresponding DEST file is made sparse as well. That is the behavior\n\ Line 234
selected by --sparse=auto. Specify --sparse=always to create a sparse DEST\n\ Line 235
file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\ Line 236
Use --sparse=never to inhibit creation of sparse files.\n\ Line 237
"), stdout); Line 238
fputs (_("\ Line 239
\n\
When --reflink[=always] is specified, perform a lightweight copy, where the\n\ Line 241
data blocks are copied only when modified. If this is not possible the copy\n\ Line 242
fails, or if --reflink=auto is specified, fall back to a standard copy.\n\ Line 243
Use --reflink=never to ensure a standard copy is performed.\n\ Line 244
"), stdout); Line 245
emit_backup_suffix_note (); Line 246
fputs (_("\ Line 247
\n\
As a special case, cp makes a backup of SOURCE when the force and backup\n\ Line 249
options are given and SOURCE and DEST are the same name for an existing,\n\ Line 250
regular file.\n\ Line 251
"), stdout); Line 252
emit_ancillary_info (PROGRAM_NAME); Line 253
}
exit (status); Line 255
} Block 8
/* Ensure that the parent directories of CONST_DST_NAME have the
correct protections, for the --parents option. This is done
after all copying has been completed, to allow permissions
that don't include user write/execute.
SRC_OFFSET is the index in CONST_DST_NAME of the beginning of the
source directory name.
ATTR_LIST is a null-terminated linked list of structures that
indicates the end of the filename of each intermediate directory
in CONST_DST_NAME that may need to have its attributes changed.
The command 'cp --parents --preserve a/b/c d/e_dir' changes the
attributes of the directories d/e_dir/a and d/e_dir/a/b to match
the corresponding source directories regardless of whether they
existed before the 'cp' command was given.
Return true if the parent of CONST_DST_NAME and any intermediate
directories specified by ATTR_LIST have the proper permissions
when done. */
static bool Line 278
re_protect (char const *const_dst_name, size_t src_offset, Line 279
struct dir_attr *attr_list, const struct cp_options *x) Line 280
{
struct dir_attr *p; Line 282
char *dst_name; /* A copy of CONST_DST_NAME we can change. */ Line 283
char *src_name; /* The source name in 'dst_name'. */ Line 284
ASSIGN_STRDUPA (dst_name, const_dst_name); Line 286
src_name = dst_name + src_offset; Line 287
for (p = attr_list; p; p = p->next) Line 289
{
dst_name[p->slash_offset] = '\0'; Line 291
/* Adjust the times (and if possible, ownership) for the copy.
chown turns off set[ug]id bits for non-root,
so do the chmod last. */
if (x->preserve_timestamps) Line 297
{
struct timespec timespec[2]; Line 299
timespec[0] = get_stat_atime (&p->st); Line 301
timespec[1] = get_stat_mtime (&p->st); Line 302
if (utimens (dst_name, timespec)) Line 304
{
error (0, errno, _("failed to preserve times for %s"), Line 306
quoteaf (dst_name)); Line 307
return false; Line 308
}
}
if (x->preserve_ownership) Line 312
{
if (lchown (dst_name, p->st.st_uid, p->st.st_gid) != 0) Line 314
{
if (! chown_failure_ok (x)) Line 316
{
error (0, errno, _("failed to preserve ownership for %s"), Line 318
quoteaf (dst_name)); Line 319
return false; Line 320
}
/* Failing to preserve ownership is OK. Still, try to preserve
the group, but ignore the possible error. */
ignore_value (lchown (dst_name, -1, p->st.st_gid)); Line 324
}
}
if (x->preserve_mode) Line 328
{
if (copy_acl (src_name, -1, dst_name, -1, p->st.st_mode) != 0) Line 330
return false; Line 331
}
else if (p->restore_mode) Line 333
{
if (lchmod (dst_name, p->st.st_mode) != 0) Line 335
{
error (0, errno, _("failed to preserve permissions for %s"), Line 337
quoteaf (dst_name)); Line 338
return false; Line 339
}
}
dst_name[p->slash_offset] = '/'; Line 343
}
return true; Line 345
} Block 9
/* Ensure that the parent directory of CONST_DIR exists, for
the --parents option.
SRC_OFFSET is the index in CONST_DIR (which is a destination
directory) of the beginning of the source directory name.
Create any leading directories that don't already exist.
If VERBOSE_FMT_STRING is nonzero, use it as a printf format
string for printing a message after successfully making a directory.
The format should take two string arguments: the names of the
source and destination directories.
Creates a linked list of attributes of intermediate directories,
*ATTR_LIST, for re_protect to use after calling copy.
Sets *NEW_DST if this function creates parent of CONST_DIR.
Return true if parent of CONST_DIR exists as a directory with the proper
permissions when done. */
/* FIXME: Synch this function with the one in ../lib/mkdir-p.c. */
static bool Line 367
make_dir_parents_private (char const *const_dir, size_t src_offset, Line 368
char const *verbose_fmt_string, Line 369
struct dir_attr **attr_list, bool *new_dst, Line 370
const struct cp_options *x) Line 371
{
struct stat stats; Line 373
char *dir; /* A copy of CONST_DIR we can change. */ Line 374
char *src; /* Source name in DIR. */ Line 375
char *dst_dir; /* Leading directory of DIR. */ Line 376
size_t dirlen; /* Length of DIR. */ Line 377
ASSIGN_STRDUPA (dir, const_dir); Line 379
src = dir + src_offset; Line 381
dirlen = dir_len (dir); Line 383
dst_dir = alloca (dirlen + 1); Line 384
memcpy (dst_dir, dir, dirlen); Line 385
dst_dir[dirlen] = '\0'; Line 386
*attr_list = NULL; Line 388
/* XXX: If all dirs are present at the destination,
no permissions or security contexts will be updated. */
if (stat (dst_dir, &stats) != 0) Line 392...!syscalls auto-comment...
{
/* A parent of CONST_DIR does not exist.
Make all missing intermediate directories. */
char *slash; Line 396
slash = src; Line 398
while (*slash == '/') Line 399
slash++; Line 400
while ((slash = strchr (slash, '/'))) Line 401
{
struct dir_attr *new IF_LINT ( = NULL); Line 403
bool missing_dir; Line 404
*slash = '\0'; Line 406
missing_dir = (stat (dir, &stats) != 0); Line 407...!syscalls auto-comment...
if (missing_dir || x->preserve_ownership || x->preserve_mode Line 409
|| x->preserve_timestamps) Line 410
{
/* Add this directory to the list of directories whose
modes might need fixing later. */
struct stat src_st; Line 414
int src_errno = (stat (src, &src_st) != 0 Line 415...!syscalls auto-comment...
? errno Line 416
: S_ISDIR (src_st.st_mode) Line 417
? 0
: ENOTDIR); Line 419
if (src_errno) Line 420
{
error (0, src_errno, _("failed to get attributes of %s"), Line 422
quoteaf (src)); Line 423
return false; Line 424
}
new = xmalloc (sizeof *new); Line 427
new->st = src_st; Line 428
new->slash_offset = slash - dir; Line 429
new->restore_mode = false; Line 430
new->next = *attr_list; Line 431
*attr_list = new; Line 432
}
/* If required set the default context for created dirs. */
if (! set_process_security_ctx (src, dir, Line 436
missing_dir ? new->st.st_mode : 0, Line 437
missing_dir, x)) Line 438
return false; Line 439
if (missing_dir) Line 441
{
mode_t src_mode; Line 443
mode_t omitted_permissions; Line 444
mode_t mkdir_mode; Line 445
/* This component does not exist. We must set
*new_dst and new->st.st_mode inside this loop because,
for example, in the command 'cp --parents ../a/../b/c e_dir',
make_dir_parents_private creates only e_dir/../a if
./b already exists. */
*new_dst = true; Line 452
src_mode = new->st.st_mode; Line 453
/* If the ownership or special mode bits might change,
omit some permissions at first, so unauthorized users
cannot nip in before the file is ready. */
omitted_permissions = (src_mode Line 458
& (x->preserve_ownership Line 459
? S_IRWXG | S_IRWXO Line 460
: x->preserve_mode Line 461
? S_IWGRP | S_IWOTH Line 462
: 0)); Line 463
/* POSIX says mkdir's behavior is implementation-defined when
(src_mode & ~S_IRWXUGO) != 0. However, common practice is
to ask mkdir to copy all the CHMOD_MODE_BITS, letting mkdir
decide what to do with S_ISUID | S_ISGID | S_ISVTX. */
mkdir_mode = x->explicit_no_preserve_mode ? S_IRWXUGO : src_mode; Line 469
mkdir_mode &= CHMOD_MODE_BITS & ~omitted_permissions; Line 470
if (mkdir (dir, mkdir_mode) != 0) Line 471...!syscalls auto-comment...
{
error (0, errno, _("cannot make directory %s"), Line 473
quoteaf (dir)); Line 474
return false; Line 475
}
else Line 477
{
if (verbose_fmt_string != NULL) Line 479
printf (verbose_fmt_string, src, dir); Line 480
}
/* We need search and write permissions to the new directory
for writing the directory's contents. Check if these
permissions are there. */
if (lstat (dir, &stats)) Line 487...!syscalls auto-comment...
{
error (0, errno, _("failed to get attributes of %s"), Line 489
quoteaf (dir)); Line 490
return false; Line 491
}
if (! x->preserve_mode) Line 495
{
if (omitted_permissions & ~stats.st_mode) Line 497
omitted_permissions &= ~ cached_umask (); Line 498
if (omitted_permissions & ~stats.st_mode Line 499
|| (stats.st_mode & S_IRWXU) != S_IRWXU) Line 500
{
new->st.st_mode = stats.st_mode | omitted_permissions; Line 502
new->restore_mode = true; Line 503
}
}
if ((stats.st_mode & S_IRWXU) != S_IRWXU) Line 507
{
/* Make the new directory searchable and writable.
The original permissions will be restored later. */
if (lchmod (dir, stats.st_mode | S_IRWXU) != 0) Line 512
{
error (0, errno, _("setting permissions for %s"), Line 514
quoteaf (dir)); Line 515
return false; Line 516
}
}
}
else if (!S_ISDIR (stats.st_mode)) Line 520
{
error (0, 0, _("%s exists but is not a directory"), Line 522
quoteaf (dir)); Line 523
return false; Line 524
}
else Line 526
*new_dst = false; Line 527
/* For existing dirs, set the security context as per that already
set for the process global context. */
if (! *new_dst Line 531
&& (x->set_security_context || x->preserve_security_context)) Line 532
{
if (! set_file_security_ctx (dir, x->preserve_security_context, Line 534
false, x) Line 535
&& x->require_preserve_context) Line 536
return false; Line 537
}
*slash++ = '/'; Line 540
/* Avoid unnecessary calls to 'stat' when given
file names containing multiple adjacent slashes. */
while (*slash == '/') Line 544
slash++; Line 545
}
}
/* We get here if the parent of DIR already exists. */
else if (!S_ISDIR (stats.st_mode)) Line 551
{
error (0, 0, _("%s exists but is not a directory"), quoteaf (dst_dir)); Line 553
return false; Line 554
}
else Line 556
{
*new_dst = false; Line 558
}
return true; Line 560
} Block 10
/* FILE is the last operand of this command.
Return true if FILE is a directory.
Without -f, report an error and exit if FILE exists
but can't be accessed.
If the file exists and is accessible store the file's status into *ST.
Otherwise, set *NEW_DST. */
static bool Line 572
target_directory_operand (char const *file, struct stat *st, Line 573
bool *new_dst, bool forcing) Line 574
{
int err = (stat (file, st) == 0 ? 0 : errno); Line 576...!syscalls auto-comment...
bool is_a_dir = !err && S_ISDIR (st->st_mode); Line 577
if (err) Line 578
{
if (err == ENOENT) Line 580
*new_dst = true; Line 581
else if (forcing) Line 582
st->st_mode = 0; /* clear so we don't enter --backup case below. */ Line 583
else Line 584
die (EXIT_FAILURE, err, _("failed to access %s"), quoteaf (file)); Line 585
}
return is_a_dir; Line 587
} Block 11
/* Scan the arguments, and copy each by calling copy.
Return true if successful. */
static bool Line 593
do_copy (int n_files, char **file, const char *target_directory, Line 594
bool no_target_directory, struct cp_options *x) Line 595
{
struct stat sb; Line 597
bool new_dst = false; Line 598
bool ok = true; Line 599
bool forcing = x->unlink_dest_before_opening Line 600
|| x->unlink_dest_after_failed_open; Line 601
if (n_files <= !target_directory) Line 603
{
if (n_files <= 0) Line 605
error (0, 0, _("missing file operand")); Line 606
else Line 607
error (0, 0, _("missing destination file operand after %s"), Line 608
quoteaf (file[0])); Line 609
usage (EXIT_FAILURE); Line 610
}
if (no_target_directory) Line 613
{
if (target_directory) Line 615
die (EXIT_FAILURE, 0, Line 616
_("cannot combine --target-directory (-t) " Line 617
"and --no-target-directory (-T)")); Line 618
if (2 < n_files) Line 619
{
error (0, 0, _("extra operand %s"), quoteaf (file[2])); Line 621
usage (EXIT_FAILURE); Line 622
}
/* Update NEW_DST and SB, which may be checked below. */
ignore_value (target_directory_operand (file[n_files -1], &sb, &new_dst, Line 625
forcing)); Line 626
}
else if (!target_directory) Line 628
{
if (2 <= n_files Line 630
&& target_directory_operand (file[n_files - 1], &sb, &new_dst, Line 631
forcing)) Line 632
target_directory = file[--n_files]; Line 633
else if (2 < n_files) Line 634
die (EXIT_FAILURE, 0, _("target %s is not a directory"), Line 635
quoteaf (file[n_files - 1])); Line 636
}
if (target_directory) Line 639
{
/* cp file1...filen edir
Copy the files 'file1' through 'filen'
to the existing directory 'edir'. */
/* Initialize these hash tables only if we'll need them.
The problems they're used to detect can arise only if
there are two or more files to copy. */
if (2 <= n_files) Line 648
{
dest_info_init (x); Line 650
src_info_init (x); Line 651
}
for (int i = 0; i < n_files; i++) Line 654
{
char *dst_name; Line 656
bool parent_exists = true; /* True if dir_name (dst_name) exists. */ Line 657
struct dir_attr *attr_list; Line 658
char *arg_in_concat = NULL; Line 659
char *arg = file[i]; Line 660
/* Trailing slashes are meaningful (i.e., maybe worth preserving)
only in the source file names. */
if (remove_trailing_slashes) Line 664
strip_trailing_slashes (arg); Line 665
if (parents_option) Line 667
{
char *arg_no_trailing_slash; Line 669
/* Use 'arg' without trailing slashes in constructing destination
file names. Otherwise, we can end up trying to create a
directory via 'mkdir ("dst/foo/"...', which is not portable.
It fails, due to the trailing slash, on at least
NetBSD 1.[34] systems. */
ASSIGN_STRDUPA (arg_no_trailing_slash, arg); Line 676
strip_trailing_slashes (arg_no_trailing_slash); Line 677
/* Append all of 'arg' (minus any trailing slash) to 'dest'. */
dst_name = file_name_concat (target_directory, Line 680
arg_no_trailing_slash, Line 681
&arg_in_concat); Line 682
/* For --parents, we have to make sure that the directory
dir_name (dst_name) exists. We may have to create a few
leading directories. */
parent_exists = Line 687
(make_dir_parents_private Line 688
(dst_name, arg_in_concat - dst_name, Line 689
(x->verbose ? "%s -> %s\n" : NULL), Line 690
&attr_list, &new_dst, x)); Line 691
}
else Line 693
{
char *arg_base; Line 695
/* Append the last component of 'arg' to 'target_directory'. */
ASSIGN_STRDUPA (arg_base, last_component (arg)); Line 697
strip_trailing_slashes (arg_base); Line 698
/* For 'cp -R source/.. dest', don't copy into 'dest/..'. */
dst_name = (STREQ (arg_base, "..") Line 700
? xstrdup (target_directory) Line 701
: file_name_concat (target_directory, arg_base, Line 702
NULL)); Line 703
}
if (!parent_exists) Line 706
{
/* make_dir_parents_private failed, so don't even
attempt the copy. */
ok = false; Line 710
}
else Line 712
{
bool copy_into_self; Line 714
ok &= copy (arg, dst_name, new_dst, x, ©_into_self, NULL); Line 715
if (parents_option) Line 717
ok &= re_protect (dst_name, arg_in_concat - dst_name, Line 718
attr_list, x); Line 719
}
if (parents_option) Line 722
{
while (attr_list) Line 724
{
struct dir_attr *p = attr_list; Line 726
attr_list = attr_list->next; Line 727
free (p); Line 728
}
}
free (dst_name); Line 732
}
}
else /* !target_directory */ Line 735
{
char const *new_dest; Line 737
char const *source = file[0]; Line 738
char const *dest = file[1]; Line 739
bool unused; Line 740
if (parents_option) Line 742
{
error (0, 0, Line 744
_("with --parents, the destination must be a directory")); Line 745
usage (EXIT_FAILURE); Line 746
}
/* When the force and backup options have been specified and
the source and destination are the same name for an existing
regular file, convert the user's command, e.g.,
'cp --force --backup foo foo' to 'cp --force foo fooSUFFIX'
where SUFFIX is determined by any version control options used. */
if (x->unlink_dest_after_failed_open Line 755
&& x->backup_type != no_backups Line 756
&& STREQ (source, dest) Line 757
&& !new_dst && S_ISREG (sb.st_mode)) Line 758
{
static struct cp_options x_tmp; Line 760
new_dest = find_backup_file_name (dest, x->backup_type); Line 762
/* Set x->backup_type to 'no_backups' so that the normal backup
mechanism is not used when performing the actual copy.
backup_type must be set to 'no_backups' only *after* the above
call to find_backup_file_name -- that function uses
backup_type to determine the suffix it applies. */
x_tmp = *x; Line 768
x_tmp.backup_type = no_backups; Line 769
x = &x_tmp; Line 770
}
else Line 772
{
new_dest = dest; Line 774
}
ok = copy (source, new_dest, 0, x, &unused, NULL); Line 777
}
return ok; Line 780
} Block 12
static void Line 783
cp_option_init (struct cp_options *x) Line 784
{
cp_options_default (x); Line 786
x->copy_as_regular = true; Line 787
x->dereference = DEREF_UNDEFINED; Line 788
x->unlink_dest_before_opening = false; Line 789
x->unlink_dest_after_failed_open = false; Line 790
x->hard_link = false; Line 791
x->interactive = I_UNSPECIFIED; Line 792
x->move_mode = false; Line 793
x->install_mode = false; Line 794
x->one_file_system = false; Line 795
x->reflink_mode = REFLINK_NEVER; Line 796
x->preserve_ownership = false; Line 798
x->preserve_links = false; Line 799
x->preserve_mode = false; Line 800
x->preserve_timestamps = false; Line 801
x->explicit_no_preserve_mode = false; Line 802
x->preserve_security_context = false; /* -a or --preserve=context. */ Line 803
x->require_preserve_context = false; /* --preserve=context. */ Line 804
x->set_security_context = false; /* -Z, set sys default context. */ Line 805
x->preserve_xattr = false; Line 806
x->reduce_diagnostics = false; Line 807
x->require_preserve_xattr = false; Line 808
x->data_copy_required = true; Line 810
x->require_preserve = false; Line 811
x->recursive = false; Line 812
x->sparse_mode = SPARSE_AUTO; Line 813
x->symbolic_link = false; Line 814
x->set_mode = false; Line 815
x->mode = 0; Line 816
/* Not used. */
x->stdin_tty = false; Line 819
x->update = false; Line 821
x->verbose = false; Line 822
/* By default, refuse to open a dangling destination symlink, because
in general one cannot do that safely, give the current semantics of
open's O_EXCL flag, (which POSIX doesn't even allow cp to use, btw).
But POSIX requires it. */
x->open_dangling_dest_symlink = getenv ("POSIXLY_CORRECT") != NULL; Line 828
x->dest_info = NULL; Line 830
x->src_info = NULL; Line 831
} Block 13
/* Given a string, ARG, containing a comma-separated list of arguments
to the --preserve option, set the appropriate fields of X to ON_OFF. */
static void Line 836
decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off) Line 837
{
enum File_attribute Line 839
{
PRESERVE_MODE, Line 841
PRESERVE_TIMESTAMPS, Line 842
PRESERVE_OWNERSHIP, Line 843
PRESERVE_LINK, Line 844
PRESERVE_CONTEXT, Line 845
PRESERVE_XATTR, Line 846
PRESERVE_ALL Line 847
};
static enum File_attribute const preserve_vals[] = Line 849
{
PRESERVE_MODE, PRESERVE_TIMESTAMPS, Line 851
PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_CONTEXT, PRESERVE_XATTR, Line 852
PRESERVE_ALL Line 853
};
/* Valid arguments to the '--preserve' option. */
static char const* const preserve_args[] = Line 856
{
"mode", "timestamps", Line 858
"ownership", "links", "context", "xattr", "all", NULL Line 859
};
ARGMATCH_VERIFY (preserve_args, preserve_vals); Line 861
char *arg_writable = xstrdup (arg); Line 863
char *s = arg_writable; Line 864
do
{
/* find next comma */
char *comma = strchr (s, ','); Line 868
enum File_attribute val; Line 869
/* If we found a comma, put a NUL in its place and advance. */
if (comma) Line 872
*comma++ = 0; Line 873
/* process S. */
val = XARGMATCH (on_off ? "--preserve" : "--no-preserve", Line 876
s, preserve_args, preserve_vals); Line 877
switch (val) Line 878
{
case PRESERVE_MODE: Line 880
x->preserve_mode = on_off; Line 881
x->explicit_no_preserve_mode = !on_off; Line 882
break; Line 883
case PRESERVE_TIMESTAMPS: Line 885
x->preserve_timestamps = on_off; Line 886
break; Line 887
case PRESERVE_OWNERSHIP: Line 889
x->preserve_ownership = on_off; Line 890
break; Line 891
case PRESERVE_LINK: Line 893
x->preserve_links = on_off; Line 894
break; Line 895
case PRESERVE_CONTEXT: Line 897
x->require_preserve_context = on_off; Line 898
x->preserve_security_context = on_off; Line 899
break; Line 900
case PRESERVE_XATTR: Line 902
x->preserve_xattr = on_off; Line 903
x->require_preserve_xattr = on_off; Line 904
break; Line 905
case PRESERVE_ALL: Line 907
x->preserve_mode = on_off; Line 908
x->preserve_timestamps = on_off; Line 909
x->preserve_ownership = on_off; Line 910
x->preserve_links = on_off; Line 911
x->explicit_no_preserve_mode = !on_off; Line 912
if (selinux_enabled) Line 913
x->preserve_security_context = on_off; Line 914
x->preserve_xattr = on_off; Line 915
break; Line 916
default: Line 918
abort (); ...!common auto-comment...
}
s = comma; Line 921
}
while (s); Line 923
free (arg_writable); Line 925
} Block 14
int
main (int argc, char **argv) Line 929
{
int c; Line 931
bool ok; Line 932
bool make_backups = false; Line 933
char const *backup_suffix = NULL; Line 934
char *version_control_string = NULL; Line 935
struct cp_options x; Line 936
bool copy_contents = false; Line 937
char *target_directory = NULL; Line 938
bool no_target_directory = false; Line 939
char const *scontext = NULL; Line 940
initialize_main (&argc, &argv); VMS-specific entry point handling wildcard expansion
set_program_name (argv[0]); Retains program name and discards path
setlocale (LC_ALL, ""); Sets up internationalization (i18n)
bindtextdomain (PACKAGE, LOCALEDIR); Assigns i18n directorySets text domain for _() [gettext()] function
textdomain (PACKAGE); Sets text domain for _() [gettext()] function
atexit (close_stdin); Close stdout on exit (see gnulib)
selinux_enabled = (0 < is_selinux_enabled ()); ...!common auto-comment...
cp_option_init (&x); Line 951
while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:TZ", Line 953
long_opts, NULL)) Line 954
!= -1) Line 955
{
switch (c) Line 957
{
case SPARSE_OPTION: Line 959
x.sparse_mode = XARGMATCH ("--sparse", optarg, Line 960
sparse_type_string, sparse_type); Line 961
break; Line 962
case REFLINK_OPTION: Line 964
if (optarg == NULL) Line 965
x.reflink_mode = REFLINK_ALWAYS; Line 966
else Line 967
x.reflink_mode = XARGMATCH ("--reflink", optarg, Line 968
reflink_type_string, reflink_type); Line 969
break; Line 970
case 'a': Line 972
/* Like -dR --preserve=all with reduced failure diagnostics. */
x.dereference = DEREF_NEVER; Line 974
x.preserve_links = true; Line 975
x.preserve_ownership = true; Line 976
x.preserve_mode = true; Line 977
x.preserve_timestamps = true; Line 978
x.require_preserve = true; Line 979
if (selinux_enabled) Line 980
x.preserve_security_context = true; Line 981
x.preserve_xattr = true; Line 982
x.reduce_diagnostics = true; Line 983
x.recursive = true; Line 984
break; Line 985
case 'b': Line 987
make_backups = true; Line 988
if (optarg) Line 989
version_control_string = optarg; Line 990
break; Line 991
case ATTRIBUTES_ONLY_OPTION: Line 993
x.data_copy_required = false; Line 994
break; Line 995
case COPY_CONTENTS_OPTION: Line 997
copy_contents = true; Line 998
break; Line 999
case 'd': Line 1001
x.preserve_links = true; Line 1002
x.dereference = DEREF_NEVER; Line 1003
break; Line 1004
case 'f': Line 1006
x.unlink_dest_after_failed_open = true; Line 1007
break; Line 1008
case 'H': Line 1010
x.dereference = DEREF_COMMAND_LINE_ARGUMENTS; Line 1011
break; Line 1012
case 'i': Line 1014
x.interactive = I_ASK_USER; Line 1015
break; Line 1016
case 'l': Line 1018
x.hard_link = true; Line 1019
break; Line 1020
case 'L': Line 1022
x.dereference = DEREF_ALWAYS; Line 1023
break; Line 1024
case 'n': Line 1026
x.interactive = I_ALWAYS_NO; Line 1027
break; Line 1028
case 'P': Line 1030
x.dereference = DEREF_NEVER; Line 1031
break; Line 1032
case NO_PRESERVE_ATTRIBUTES_OPTION: Line 1034
decode_preserve_arg (optarg, &x, false); Line 1035
break; Line 1036
case PRESERVE_ATTRIBUTES_OPTION: Line 1038
if (optarg == NULL) Line 1039
{
/* Fall through to the case for 'p' below. */
}
else Line 1043
{
decode_preserve_arg (optarg, &x, true); Line 1045
x.require_preserve = true; Line 1046
break; Line 1047
}
FALLTHROUGH; Line 1049
case 'p': Line 1051
x.preserve_ownership = true; Line 1052
x.preserve_mode = true; Line 1053
x.preserve_timestamps = true; Line 1054
x.require_preserve = true; Line 1055
break; Line 1056
case PARENTS_OPTION: Line 1058
parents_option = true; Line 1059
break; Line 1060
case 'r': Line 1062
case 'R': Line 1063
x.recursive = true; Line 1064
break; Line 1065
case UNLINK_DEST_BEFORE_OPENING: Line 1067
x.unlink_dest_before_opening = true; Line 1068
break; Line 1069
case STRIP_TRAILING_SLASHES_OPTION: Line 1071
remove_trailing_slashes = true; Line 1072
break; Line 1073
case 's': Line 1075
x.symbolic_link = true; Line 1076
break; Line 1077
case 't': Line 1079
if (target_directory) Line 1080
die (EXIT_FAILURE, 0, Line 1081
_("multiple target directories specified")); Line 1082
else Line 1083
{
struct stat st; Line 1085
if (stat (optarg, &st) != 0) Line 1086...!syscalls auto-comment...
die (EXIT_FAILURE, errno, _("failed to access %s"), Line 1087
quoteaf (optarg)); Line 1088
if (! S_ISDIR (st.st_mode)) Line 1089
die (EXIT_FAILURE, 0, _("target %s is not a directory"), Line 1090
quoteaf (optarg)); Line 1091
}
target_directory = optarg; Line 1093
break; Line 1094
case 'T': Line 1096
no_target_directory = true; Line 1097
break; Line 1098
case 'u': Line 1100
x.update = true; Line 1101
break; Line 1102
case 'v': Line 1104
x.verbose = true; Line 1105
break; Line 1106
case 'x': Line 1108
x.one_file_system = true; Line 1109
break; Line 1110
case 'Z': Line 1112
/* politely decline if we're not on a selinux-enabled kernel. */
if (selinux_enabled) Line 1114
{
if (optarg) Line 1116
scontext = optarg; Line 1117
else Line 1118
x.set_security_context = true; Line 1119
}
else if (optarg) Line 1121
{
error (0, 0, Line 1123
_("warning: ignoring --context; " Line 1124
"it requires an SELinux-enabled kernel")); Line 1125
}
break; Line 1127
case 'S': Line 1129
make_backups = true; Line 1130
backup_suffix = optarg; Line 1131
break; Line 1132
case_GETOPT_HELP_CHAR; Line 1134
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); Line 1136
default: Line 1138
usage (EXIT_FAILURE); Line 1139
}
}
if (x.hard_link && x.symbolic_link) Line 1143
{
error (0, 0, _("cannot make both hard and symbolic links")); Line 1145
usage (EXIT_FAILURE); Line 1146
}
if (x.interactive == I_ALWAYS_NO) Line 1149
x.update = false; Line 1150
if (make_backups && x.interactive == I_ALWAYS_NO) Line 1152
{
error (0, 0, Line 1154
_("options --backup and --no-clobber are mutually exclusive")); Line 1155
usage (EXIT_FAILURE); Line 1156
}
if (x.reflink_mode == REFLINK_ALWAYS && x.sparse_mode != SPARSE_AUTO) Line 1159
{
error (0, 0, _("--reflink can be used only with --sparse=auto")); Line 1161
usage (EXIT_FAILURE); Line 1162
}
x.backup_type = (make_backups Line 1165
? xget_version (_("backup type"), Line 1166
version_control_string) Line 1167
: no_backups); Line 1168
set_simple_backup_suffix (backup_suffix); Line 1169
if (x.dereference == DEREF_UNDEFINED) Line 1171
{
if (x.recursive && ! x.hard_link) Line 1173
/* This is compatible with FreeBSD. */
x.dereference = DEREF_NEVER; Line 1175
else Line 1176
x.dereference = DEREF_ALWAYS; Line 1177
}
if (x.recursive) Line 1180
x.copy_as_regular = copy_contents; Line 1181
/* Ensure -Z overrides -a. */
if ((x.set_security_context || scontext) Line 1184
&& ! x.require_preserve_context) Line 1185
x.preserve_security_context = false; Line 1186
if (x.preserve_security_context && (x.set_security_context || scontext)) Line 1188
die (EXIT_FAILURE, 0, Line 1189
_("cannot set target context and preserve it")); Line 1190
if (x.require_preserve_context && ! selinux_enabled) Line 1192
die (EXIT_FAILURE, 0, Line 1193
_("cannot preserve security context " Line 1194
"without an SELinux-enabled kernel")); Line 1195
/* FIXME: This handles new files. But what about existing files?
I.e., if updating a tree, new files would have the specified context,
but shouldn't existing files be updated for consistency like this?
if (scontext)
restorecon (dst_path, 0, true);
*/
if (scontext && setfscreatecon (se_const (scontext)) < 0) Line 1203
die (EXIT_FAILURE, errno, Line 1204
_("failed to set default file creation context to %s"), Line 1205
quote (scontext)); Line 1206
#if !USE_XATTR Line 1208
if (x.require_preserve_xattr) Line 1209
die (EXIT_FAILURE, 0, _("cannot preserve extended attributes, cp is " Line 1210
"built without xattr support")); Line 1211
#endif Line 1212
/* Allocate space for remembering copied and created files. */
hash_init (); Line 1216
ok = do_copy (argc - optind, argv + optind, Line 1218
target_directory, no_target_directory, &x); Line 1219
#ifdef lint Line 1221
forget_all (); Line 1222
#endif Line 1223
return ok ? EXIT_SUCCESS : EXIT_FAILURE; Line 1225
} Block 15