1 /* cp.c  -- file copying (main routines)
2    Copyright (C) 1989-2023 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 <https://www.gnu.org/licenses/>.
16 
17    Written by Torbjörn 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/label.h>
24 
25 #include "system.h"
26 #include "argmatch.h"
27 #include "assure.h"
28 #include "backupfile.h"
29 #include "copy.h"
30 #include "cp-hash.h"
31 #include "filenamecat.h"
32 #include "ignore-value.h"
33 #include "quote.h"
34 #include "stat-time.h"
35 #include "targetdir.h"
36 #include "utimens.h"
37 #include "acl.h"
38 
39 /* The official name of this program (e.g., no 'g' prefix).  */
40 #define PROGRAM_NAME "cp"
41 
42 #define AUTHORS \
43   proper_name_lite ("Torbjorn Granlund", "Torbj\303\266rn Granlund"), \
44   proper_name ("David MacKenzie"), \
45   proper_name ("Jim Meyering")
46 
47 /* Used by do_copy, make_dir_parents_private, and re_protect
48    to keep a list of leading directories whose protections
49    need to be fixed after copying. */
50 struct dir_attr
51 {
52   struct stat st;
53   bool restore_mode;
54   size_t slash_offset;
55   struct dir_attr *next;
56 };
57 
58 /* For long options that have no equivalent short option, use a
59    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
60 enum
61 {
62   ATTRIBUTES_ONLY_OPTION = CHAR_MAX + 1,
63   COPY_CONTENTS_OPTION,
64   DEBUG_OPTION,
65   NO_PRESERVE_ATTRIBUTES_OPTION,
66   PARENTS_OPTION,
67   PRESERVE_ATTRIBUTES_OPTION,
68   REFLINK_OPTION,
69   SPARSE_OPTION,
70   STRIP_TRAILING_SLASHES_OPTION,
71   UNLINK_DEST_BEFORE_OPENING
72 };
73 
74 /* True if the kernel is SELinux enabled.  */
75 static bool selinux_enabled;
76 
77 /* If true, the command "cp x/e_file e_dir" uses "e_dir/x/e_file"
78    as its destination instead of the usual "e_dir/e_file." */
79 static bool parents_option = false;
80 
81 /* Remove any trailing slashes from each SOURCE argument.  */
82 static bool remove_trailing_slashes;
83 
84 static char const *const sparse_type_string[] =
85 {
86   "never", "auto", "always", nullptr
87 };
88 static enum Sparse_type const sparse_type[] =
89 {
90   SPARSE_NEVER, SPARSE_AUTO, SPARSE_ALWAYS
91 };
92 ARGMATCH_VERIFY (sparse_type_string, sparse_type);
93 
94 static char const *const reflink_type_string[] =
95 {
96   "auto", "always", "never", nullptr
97 };
98 static enum Reflink_type const reflink_type[] =
99 {
100   REFLINK_AUTO, REFLINK_ALWAYS, REFLINK_NEVER
101 };
102 ARGMATCH_VERIFY (reflink_type_string, reflink_type);
103 
104 static char const *const update_type_string[] =
105 {
106   "all", "none", "older", nullptr
107 };
108 static enum Update_type const update_type[] =
109 {
110   UPDATE_ALL, UPDATE_NONE, UPDATE_OLDER,
111 };
112 ARGMATCH_VERIFY (update_type_string, update_type);
113 
114 static struct option const long_opts[] =
115 {
116   {"archive", no_argument, nullptr, 'a'},
117   {"attributes-only", no_argument, nullptr, ATTRIBUTES_ONLY_OPTION},
118   {"backup", optional_argument, nullptr, 'b'},
119   {"copy-contents", no_argument, nullptr, COPY_CONTENTS_OPTION},
120   {"debug", no_argument, nullptr, DEBUG_OPTION},
121   {"dereference", no_argument, nullptr, 'L'},
122   {"force", no_argument, nullptr, 'f'},
123   {"interactive", no_argument, nullptr, 'i'},
124   {"link", no_argument, nullptr, 'l'},
125   {"no-clobber", no_argument, nullptr, 'n'},
126   {"no-dereference", no_argument, nullptr, 'P'},
127   {"no-preserve", required_argument, nullptr, NO_PRESERVE_ATTRIBUTES_OPTION},
128   {"no-target-directory", no_argument, nullptr, 'T'},
129   {"one-file-system", no_argument, nullptr, 'x'},
130   {"parents", no_argument, nullptr, PARENTS_OPTION},
131   {"path", no_argument, nullptr, PARENTS_OPTION},   /* Deprecated.  */
132   {"preserve", optional_argument, nullptr, PRESERVE_ATTRIBUTES_OPTION},
133   {"recursive", no_argument, nullptr, 'R'},
134   {"remove-destination", no_argument, nullptr, UNLINK_DEST_BEFORE_OPENING},
135   {"sparse", required_argument, nullptr, SPARSE_OPTION},
136   {"reflink", optional_argument, nullptr, REFLINK_OPTION},
137   {"strip-trailing-slashes", no_argument, nullptr,
138    STRIP_TRAILING_SLASHES_OPTION},
139   {"suffix", required_argument, nullptr, 'S'},
140   {"symbolic-link", no_argument, nullptr, 's'},
141   {"target-directory", required_argument, nullptr, 't'},
142   {"update", optional_argument, nullptr, 'u'},
143   {"verbose", no_argument, nullptr, 'v'},
144   {GETOPT_SELINUX_CONTEXT_OPTION_DECL},
145   {GETOPT_HELP_OPTION_DECL},
146   {GETOPT_VERSION_OPTION_DECL},
147   {nullptr, 0, nullptr, 0}
148 };
149 
150 void
usage(int status)151 usage (int status)
152 {
153   if (status != EXIT_SUCCESS)
154     emit_try_help ();
155   else
156     {
157       printf (_("\
158 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
159   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
160   or:  %s [OPTION]... -t DIRECTORY SOURCE...\n\
161 "),
162               program_name, program_name, program_name);
163       fputs (_("\
164 Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\
165 "), stdout);
166 
167       emit_mandatory_arg_note ();
168 
169       fputs (_("\
170   -a, --archive                same as -dR --preserve=all\n\
171       --attributes-only        don't copy the file data, just the attributes\n\
172       --backup[=CONTROL]       make a backup of each existing destination file\
173 \n\
174   -b                           like --backup but does not accept an argument\n\
175       --copy-contents          copy contents of special files when recursive\n\
176   -d                           same as --no-dereference --preserve=links\n\
177 "), stdout);
178       fputs (_("\
179       --debug                  explain how a file is copied.  Implies -v\n\
180 "), stdout);
181       fputs (_("\
182   -f, --force                  if an existing destination file cannot be\n\
183                                  opened, remove it and try again (this option\n\
184                                  is ignored when the -n option is also used)\n\
185   -i, --interactive            prompt before overwrite (overrides a previous -n\
186 \n\
187                                   option)\n\
188   -H                           follow command-line symbolic links in SOURCE\n\
189 "), stdout);
190       fputs (_("\
191   -l, --link                   hard link files instead of copying\n\
192   -L, --dereference            always follow symbolic links in SOURCE\n\
193 "), stdout);
194       fputs (_("\
195   -n, --no-clobber             do not overwrite an existing file (overrides a\n\
196                                  -u or previous -i option). See also --update\n\
197 "), stdout);
198       fputs (_("\
199   -P, --no-dereference         never follow symbolic links in SOURCE\n\
200 "), stdout);
201       fputs (_("\
202   -p                           same as --preserve=mode,ownership,timestamps\n\
203       --preserve[=ATTR_LIST]   preserve the specified attributes\n\
204 "), stdout);
205       fputs (_("\
206       --no-preserve=ATTR_LIST  don't preserve the specified attributes\n\
207       --parents                use full source file name under DIRECTORY\n\
208 "), stdout);
209       fputs (_("\
210   -R, -r, --recursive          copy directories recursively\n\
211       --reflink[=WHEN]         control clone/CoW copies. See below\n\
212       --remove-destination     remove each existing destination file before\n\
213                                  attempting to open it (contrast with --force)\
214 \n"), stdout);
215       fputs (_("\
216       --sparse=WHEN            control creation of sparse files. See below\n\
217       --strip-trailing-slashes  remove any trailing slashes from each SOURCE\n\
218                                  argument\n\
219 "), stdout);
220       fputs (_("\
221   -s, --symbolic-link          make symbolic links instead of copying\n\
222   -S, --suffix=SUFFIX          override the usual backup suffix\n\
223   -t, --target-directory=DIRECTORY  copy all SOURCE arguments into DIRECTORY\n\
224   -T, --no-target-directory    treat DEST as a normal file\n\
225 "), stdout);
226       fputs (_("\
227   --update[=UPDATE]            control which existing files are updated;\n\
228                                  UPDATE={all,none,older(default)}.  See below\n\
229   -u                           equivalent to --update[=older]\n\
230 "), stdout);
231       fputs (_("\
232   -v, --verbose                explain what is being done\n\
233 "), stdout);
234       fputs (_("\
235   -x, --one-file-system        stay on this file system\n\
236 "), stdout);
237       fputs (_("\
238   -Z                           set SELinux security context of destination\n\
239                                  file to default type\n\
240       --context[=CTX]          like -Z, or if CTX is specified then set the\n\
241                                  SELinux or SMACK security context to CTX\n\
242 "), stdout);
243       fputs (HELP_OPTION_DESCRIPTION, stdout);
244       fputs (VERSION_OPTION_DESCRIPTION, stdout);
245       fputs (_("\
246 \n\
247 ATTR_LIST is a comma-separated list of attributes. Attributes are 'mode' for\n\
248 permissions (including any ACL and xattr permissions), 'ownership' for user\n\
249 and group, 'timestamps' for file timestamps, 'links' for hard links, 'context'\
250 \nfor security context, 'xattr' for extended attributes, and 'all' for all\n\
251 attributes.\n\
252 "), stdout);
253       fputs (_("\
254 \n\
255 By default, sparse SOURCE files are detected by a crude heuristic and the\n\
256 corresponding DEST file is made sparse as well.  That is the behavior\n\
257 selected by --sparse=auto.  Specify --sparse=always to create a sparse DEST\n\
258 file whenever the SOURCE file contains a long enough sequence of zero bytes.\n\
259 Use --sparse=never to inhibit creation of sparse files.\n\
260 "), stdout);
261       emit_update_parameters_note ();
262       fputs (_("\
263 \n\
264 When --reflink[=always] is specified, perform a lightweight copy, where the\n\
265 data blocks are copied only when modified.  If this is not possible the copy\n\
266 fails, or if --reflink=auto is specified, fall back to a standard copy.\n\
267 Use --reflink=never to ensure a standard copy is performed.\n\
268 "), stdout);
269       emit_backup_suffix_note ();
270       fputs (_("\
271 \n\
272 As a special case, cp makes a backup of SOURCE when the force and backup\n\
273 options are given and SOURCE and DEST are the same name for an existing,\n\
274 regular file.\n\
275 "), stdout);
276       emit_ancillary_info (PROGRAM_NAME);
277     }
278   exit (status);
279 }
280 
281 /* Ensure that parents of CONST_DST_NAME have correct protections, for
282    the --parents option.  This is done after all copying has been
283    completed, to allow permissions that don't include user write/execute.
284 
285    DST_SRC_NAME is the suffix of CONST_DST_NAME that is the source file name,
286    DST_DIRFD+DST_RELNAME is equivalent to CONST_DST_NAME, and
287    DST_RELNAME equals DST_SRC_NAME after skipping any leading '/'s.
288 
289    ATTR_LIST is a null-terminated linked list of structures that
290    indicates the end of the filename of each intermediate directory
291    in CONST_DST_NAME that may need to have its attributes changed.
292    The command 'cp --parents --preserve a/b/c d/e_dir' changes the
293    attributes of the directories d/e_dir/a and d/e_dir/a/b to match
294    the corresponding source directories regardless of whether they
295    existed before the 'cp' command was given.
296 
297    Return true if the parent of CONST_DST_NAME and any intermediate
298    directories specified by ATTR_LIST have the proper permissions
299    when done.  */
300 
301 static bool
re_protect(char const * const_dst_name,char const * dst_src_name,int dst_dirfd,char const * dst_relname,struct dir_attr * attr_list,const struct cp_options * x)302 re_protect (char const *const_dst_name, char const *dst_src_name,
303             int dst_dirfd, char const *dst_relname,
304             struct dir_attr *attr_list, const struct cp_options *x)
305 {
306   struct dir_attr *p;
307   char *dst_name;		/* A copy of CONST_DST_NAME we can change. */
308 
309   ASSIGN_STRDUPA (dst_name, const_dst_name);
310 
311   /* The suffix of DST_NAME that is a copy of the source file name,
312      possibly truncated to name a parent directory.  */
313   char const *src_name = dst_name + (dst_src_name - const_dst_name);
314 
315   /* Likewise, but with any leading '/'s skipped.  */
316   char const *relname = dst_name + (dst_relname - const_dst_name);
317 
318   for (p = attr_list; p; p = p->next)
319     {
320       dst_name[p->slash_offset] = '\0';
321 
322       /* Adjust the times (and if possible, ownership) for the copy.
323          chown turns off set[ug]id bits for non-root,
324          so do the chmod last.  */
325 
326       if (x->preserve_timestamps)
327         {
328           struct timespec timespec[2];
329 
330           timespec[0] = get_stat_atime (&p->st);
331           timespec[1] = get_stat_mtime (&p->st);
332 
333           if (utimensat (dst_dirfd, relname, timespec, 0))
334             {
335               error (0, errno, _("failed to preserve times for %s"),
336                      quoteaf (dst_name));
337               return false;
338             }
339         }
340 
341       if (x->preserve_ownership)
342         {
343           if (lchownat (dst_dirfd, relname, p->st.st_uid, p->st.st_gid)
344               != 0)
345             {
346               if (! chown_failure_ok (x))
347                 {
348                   error (0, errno, _("failed to preserve ownership for %s"),
349                          quoteaf (dst_name));
350                   return false;
351                 }
352               /* Failing to preserve ownership is OK. Still, try to preserve
353                  the group, but ignore the possible error. */
354               ignore_value (lchownat (dst_dirfd, relname, -1, p->st.st_gid));
355             }
356         }
357 
358       if (x->preserve_mode)
359         {
360           if (copy_acl (src_name, -1, dst_name, -1, p->st.st_mode) != 0)
361             return false;
362         }
363       else if (p->restore_mode)
364         {
365           if (lchmodat (dst_dirfd, relname, p->st.st_mode) != 0)
366             {
367               error (0, errno, _("failed to preserve permissions for %s"),
368                      quoteaf (dst_name));
369               return false;
370             }
371         }
372 
373       dst_name[p->slash_offset] = '/';
374     }
375   return true;
376 }
377 
378 /* Ensure that the parent directory of CONST_DIR exists, for
379    the --parents option.
380 
381    SRC_OFFSET is the index in CONST_DIR (which is a destination
382    directory) of the beginning of the source directory name.
383    Create any leading directories that don't already exist.
384    DST_DIRFD is a file descriptor for the target directory.
385    If VERBOSE_FMT_STRING is nonzero, use it as a printf format
386    string for printing a message after successfully making a directory.
387    The format should take two string arguments: the names of the
388    source and destination directories.
389    Creates a linked list of attributes of intermediate directories,
390    *ATTR_LIST, for re_protect to use after calling copy.
391    Sets *NEW_DST if this function creates parent of CONST_DIR.
392 
393    Return true if parent of CONST_DIR exists as a directory with the proper
394    permissions when done.  */
395 
396 /* FIXME: Synch this function with the one in ../lib/mkdir-p.c.  */
397 
398 static bool
make_dir_parents_private(char const * const_dir,size_t src_offset,int dst_dirfd,char const * verbose_fmt_string,struct dir_attr ** attr_list,bool * new_dst,const struct cp_options * x)399 make_dir_parents_private (char const *const_dir, size_t src_offset,
400                           int dst_dirfd,
401                           char const *verbose_fmt_string,
402                           struct dir_attr **attr_list, bool *new_dst,
403                           const struct cp_options *x)
404 {
405   struct stat stats;
406   char *dir;		/* A copy of CONST_DIR we can change.  */
407   char *src;		/* Source name in DIR.  */
408   char *dst_dir;	/* Leading directory of DIR.  */
409   idx_t dirlen = dir_len (const_dir);
410 
411   *attr_list = nullptr;
412 
413   /* Succeed immediately if the parent of CONST_DIR must already exist,
414      as the target directory has already been checked.  */
415   if (dirlen <= src_offset)
416     return true;
417 
418   ASSIGN_STRDUPA (dir, const_dir);
419 
420   src = dir + src_offset;
421 
422   dst_dir = alloca (dirlen + 1);
423   memcpy (dst_dir, dir, dirlen);
424   dst_dir[dirlen] = '\0';
425   char const *dst_reldir = dst_dir + src_offset;
426   while (*dst_reldir == '/')
427     dst_reldir++;
428 
429   /* XXX: If all dirs are present at the destination,
430      no permissions or security contexts will be updated.  */
431   if (fstatat (dst_dirfd, dst_reldir, &stats, 0) != 0)
432     {
433       /* A parent of CONST_DIR does not exist.
434          Make all missing intermediate directories. */
435       char *slash;
436 
437       slash = src;
438       while (*slash == '/')
439         slash++;
440       dst_reldir = slash;
441 
442       while ((slash = strchr (slash, '/')))
443         {
444           struct dir_attr *new;
445           bool missing_dir;
446 
447           *slash = '\0';
448           missing_dir = fstatat (dst_dirfd, dst_reldir, &stats, 0) != 0;
449 
450           if (missing_dir || x->preserve_ownership || x->preserve_mode
451               || x->preserve_timestamps)
452             {
453               /* Add this directory to the list of directories whose
454                  modes might need fixing later. */
455               struct stat src_st;
456               int src_errno = (stat (src, &src_st) != 0
457                                ? errno
458                                : S_ISDIR (src_st.st_mode)
459                                ? 0
460                                : ENOTDIR);
461               if (src_errno)
462                 {
463                   error (0, src_errno, _("failed to get attributes of %s"),
464                          quoteaf (src));
465                   return false;
466                 }
467 
468               new = xmalloc (sizeof *new);
469               new->st = src_st;
470               new->slash_offset = slash - dir;
471               new->restore_mode = false;
472               new->next = *attr_list;
473               *attr_list = new;
474             }
475 
476           /* If required set the default context for created dirs.  */
477           if (! set_process_security_ctx (src, dir,
478                                           missing_dir ? new->st.st_mode : 0,
479                                           missing_dir, x))
480             return false;
481 
482           if (missing_dir)
483             {
484               mode_t src_mode;
485               mode_t omitted_permissions;
486               mode_t mkdir_mode;
487 
488               /* This component does not exist.  We must set
489                  *new_dst and new->st.st_mode inside this loop because,
490                  for example, in the command 'cp --parents ../a/../b/c e_dir',
491                  make_dir_parents_private creates only e_dir/../a if
492                  ./b already exists. */
493               *new_dst = true;
494               src_mode = new->st.st_mode;
495 
496               /* If the ownership or special mode bits might change,
497                  omit some permissions at first, so unauthorized users
498                  cannot nip in before the file is ready.  */
499               omitted_permissions = (src_mode
500                                      & (x->preserve_ownership
501                                         ? S_IRWXG | S_IRWXO
502                                         : x->preserve_mode
503                                         ? S_IWGRP | S_IWOTH
504                                         : 0));
505 
506               /* POSIX says mkdir's behavior is implementation-defined when
507                  (src_mode & ~S_IRWXUGO) != 0.  However, common practice is
508                  to ask mkdir to copy all the CHMOD_MODE_BITS, letting mkdir
509                  decide what to do with S_ISUID | S_ISGID | S_ISVTX.  */
510               mkdir_mode = x->explicit_no_preserve_mode ? S_IRWXUGO : src_mode;
511               mkdir_mode &= CHMOD_MODE_BITS & ~omitted_permissions;
512               if (mkdirat (dst_dirfd, dst_reldir, mkdir_mode) != 0)
513                 {
514                   error (0, errno, _("cannot make directory %s"),
515                          quoteaf (dir));
516                   return false;
517                 }
518               else
519                 {
520                   if (verbose_fmt_string != nullptr)
521                     printf (verbose_fmt_string, src, dir);
522                 }
523 
524               /* We need search and write permissions to the new directory
525                  for writing the directory's contents. Check if these
526                  permissions are there.  */
527 
528               if (fstatat (dst_dirfd, dst_reldir, &stats, AT_SYMLINK_NOFOLLOW))
529                 {
530                   error (0, errno, _("failed to get attributes of %s"),
531                          quoteaf (dir));
532                   return false;
533                 }
534 
535 
536               if (! x->preserve_mode)
537                 {
538                   if (omitted_permissions & ~stats.st_mode)
539                     omitted_permissions &= ~ cached_umask ();
540                   if (omitted_permissions & ~stats.st_mode
541                       || (stats.st_mode & S_IRWXU) != S_IRWXU)
542                     {
543                       new->st.st_mode = stats.st_mode | omitted_permissions;
544                       new->restore_mode = true;
545                     }
546                 }
547 
548               mode_t accessible = stats.st_mode | S_IRWXU;
549               if (stats.st_mode != accessible)
550                 {
551                   /* Make the new directory searchable and writable.
552                      The original permissions will be restored later.  */
553 
554                   if (lchmodat (dst_dirfd, dst_reldir, accessible) != 0)
555                     {
556                       error (0, errno, _("setting permissions for %s"),
557                              quoteaf (dir));
558                       return false;
559                     }
560                 }
561             }
562           else if (!S_ISDIR (stats.st_mode))
563             {
564               error (0, 0, _("%s exists but is not a directory"),
565                      quoteaf (dir));
566               return false;
567             }
568           else
569             *new_dst = false;
570 
571           /* For existing dirs, set the security context as per that already
572              set for the process global context.  */
573           if (! *new_dst
574               && (x->set_security_context || x->preserve_security_context))
575             {
576               if (! set_file_security_ctx (dir, false, x)
577                   && x->require_preserve_context)
578                 return false;
579             }
580 
581           *slash++ = '/';
582 
583           /* Avoid unnecessary calls to 'stat' when given
584              file names containing multiple adjacent slashes.  */
585           while (*slash == '/')
586             slash++;
587         }
588     }
589 
590   /* We get here if the parent of DIR already exists.  */
591 
592   else if (!S_ISDIR (stats.st_mode))
593     {
594       error (0, 0, _("%s exists but is not a directory"), quoteaf (dst_dir));
595       return false;
596     }
597   else
598     {
599       *new_dst = false;
600     }
601   return true;
602 }
603 
604 /* Scan the arguments, and copy each by calling copy.
605    Return true if successful.  */
606 
607 static bool
do_copy(int n_files,char ** file,char const * target_directory,bool no_target_directory,struct cp_options * x)608 do_copy (int n_files, char **file, char const *target_directory,
609          bool no_target_directory, struct cp_options *x)
610 {
611   struct stat sb;
612   bool new_dst = false;
613   bool ok = true;
614 
615   if (n_files <= !target_directory)
616     {
617       if (n_files <= 0)
618         error (0, 0, _("missing file operand"));
619       else
620         error (0, 0, _("missing destination file operand after %s"),
621                quoteaf (file[0]));
622       usage (EXIT_FAILURE);
623     }
624 
625   sb.st_mode = 0;
626   int target_dirfd = AT_FDCWD;
627   if (no_target_directory)
628     {
629       if (target_directory)
630         error (EXIT_FAILURE, 0,
631                _("cannot combine --target-directory (-t) "
632                  "and --no-target-directory (-T)"));
633       if (2 < n_files)
634         {
635           error (0, 0, _("extra operand %s"), quoteaf (file[2]));
636           usage (EXIT_FAILURE);
637         }
638     }
639   else if (target_directory)
640     {
641       target_dirfd = target_directory_operand (target_directory, &sb);
642       if (! target_dirfd_valid (target_dirfd))
643         error (EXIT_FAILURE, errno, _("target directory %s"),
644                quoteaf (target_directory));
645     }
646   else
647     {
648       char const *lastfile = file[n_files - 1];
649       int fd = target_directory_operand (lastfile, &sb);
650       if (target_dirfd_valid (fd))
651         {
652           target_dirfd = fd;
653           target_directory = lastfile;
654           n_files--;
655         }
656       else
657         {
658           int err = errno;
659           if (err == ENOENT)
660             new_dst = true;
661 
662           /* The last operand LASTFILE cannot be opened as a directory.
663              If there are more than two operands, report an error.
664 
665              Also, report an error if LASTFILE is known to be a directory
666              even though it could not be opened, which can happen if
667              opening failed with EACCES on a platform lacking O_PATH.
668              In this case use stat to test whether LASTFILE is a
669              directory, in case opening a non-directory with (O_SEARCH
670              | O_DIRECTORY) failed with EACCES not ENOTDIR.  */
671           if (2 < n_files
672               || (O_PATHSEARCH == O_SEARCH && err == EACCES
673                   && (sb.st_mode || stat (lastfile, &sb) == 0)
674                   && S_ISDIR (sb.st_mode)))
675             error (EXIT_FAILURE, err, _("target %s"), quoteaf (lastfile));
676         }
677     }
678 
679   if (target_directory)
680     {
681       /* cp file1...filen edir
682          Copy the files 'file1' through 'filen'
683          to the existing directory 'edir'. */
684 
685       /* Initialize these hash tables only if we'll need them.
686          The problems they're used to detect can arise only if
687          there are two or more files to copy.  */
688       if (2 <= n_files)
689         {
690           dest_info_init (x);
691           src_info_init (x);
692         }
693 
694       for (int i = 0; i < n_files; i++)
695         {
696           char *dst_name;
697           bool parent_exists = true;  /* True if dir_name (dst_name) exists. */
698           struct dir_attr *attr_list;
699           char *arg_in_concat;
700           char *arg = file[i];
701 
702           /* Trailing slashes are meaningful (i.e., maybe worth preserving)
703              only in the source file names.  */
704           if (remove_trailing_slashes)
705             strip_trailing_slashes (arg);
706 
707           if (parents_option)
708             {
709               char *arg_no_trailing_slash;
710 
711               /* Use 'arg' without trailing slashes in constructing destination
712                  file names.  Otherwise, we can end up trying to create a
713                  directory using a name with trailing slash, which fails on
714                  NetBSD 1.[34] systems.  */
715               ASSIGN_STRDUPA (arg_no_trailing_slash, arg);
716               strip_trailing_slashes (arg_no_trailing_slash);
717 
718               /* Append all of 'arg' (minus any trailing slash) to 'dest'.  */
719               dst_name = file_name_concat (target_directory,
720                                            arg_no_trailing_slash,
721                                            &arg_in_concat);
722 
723               /* For --parents, we have to make sure that the directory
724                  dir_name (dst_name) exists.  We may have to create a few
725                  leading directories. */
726               parent_exists =
727                 (make_dir_parents_private
728                  (dst_name, arg_in_concat - dst_name, target_dirfd,
729                   (x->verbose ? "%s -> %s\n" : nullptr),
730                   &attr_list, &new_dst, x));
731             }
732           else
733             {
734               char *arg_base;
735               /* Append the last component of 'arg' to 'target_directory'.  */
736               ASSIGN_STRDUPA (arg_base, last_component (arg));
737               strip_trailing_slashes (arg_base);
738               /* For 'cp -R source/.. dest', don't copy into 'dest/..'. */
739               arg_base += STREQ (arg_base, "..");
740               dst_name = file_name_concat (target_directory, arg_base,
741                                            &arg_in_concat);
742             }
743 
744           if (!parent_exists)
745             {
746               /* make_dir_parents_private failed, so don't even
747                  attempt the copy.  */
748               ok = false;
749             }
750           else
751             {
752               char const *dst_relname = arg_in_concat;
753               while (*dst_relname == '/')
754                 dst_relname++;
755 
756               bool copy_into_self;
757               ok &= copy (arg, dst_name, target_dirfd, dst_relname,
758                           new_dst, x, &copy_into_self, nullptr);
759 
760               if (parents_option)
761                 ok &= re_protect (dst_name, arg_in_concat, target_dirfd,
762                                   dst_relname, attr_list, x);
763             }
764 
765           if (parents_option)
766             {
767               while (attr_list)
768                 {
769                   struct dir_attr *p = attr_list;
770                   attr_list = attr_list->next;
771                   free (p);
772                 }
773             }
774 
775           free (dst_name);
776         }
777     }
778   else /* !target_directory */
779     {
780       char const *source = file[0];
781       char const *dest = file[1];
782       bool unused;
783 
784       if (parents_option)
785         {
786           error (0, 0,
787                  _("with --parents, the destination must be a directory"));
788           usage (EXIT_FAILURE);
789         }
790 
791       /* When the force and backup options have been specified and
792          the source and destination are the same name for an existing
793          regular file, convert the user's command, e.g.,
794          'cp --force --backup foo foo' to 'cp --force foo fooSUFFIX'
795          where SUFFIX is determined by any version control options used.  */
796 
797       if (x->unlink_dest_after_failed_open
798           && x->backup_type != no_backups
799           && STREQ (source, dest)
800           && !new_dst
801           && (sb.st_mode != 0 || stat (dest, &sb) == 0) && S_ISREG (sb.st_mode))
802         {
803           static struct cp_options x_tmp;
804 
805           dest = find_backup_file_name (AT_FDCWD, dest, x->backup_type);
806           /* Set x->backup_type to 'no_backups' so that the normal backup
807              mechanism is not used when performing the actual copy.
808              backup_type must be set to 'no_backups' only *after* the above
809              call to find_backup_file_name -- that function uses
810              backup_type to determine the suffix it applies.  */
811           x_tmp = *x;
812           x_tmp.backup_type = no_backups;
813           x = &x_tmp;
814         }
815 
816       ok = copy (source, dest, AT_FDCWD, dest, -new_dst, x, &unused, nullptr);
817     }
818 
819   return ok;
820 }
821 
822 static void
cp_option_init(struct cp_options * x)823 cp_option_init (struct cp_options *x)
824 {
825   cp_options_default (x);
826   x->copy_as_regular = true;
827   x->dereference = DEREF_UNDEFINED;
828   x->unlink_dest_before_opening = false;
829   x->unlink_dest_after_failed_open = false;
830   x->hard_link = false;
831   x->interactive = I_UNSPECIFIED;
832   x->move_mode = false;
833   x->install_mode = false;
834   x->one_file_system = false;
835   x->reflink_mode = REFLINK_AUTO;
836 
837   x->preserve_ownership = false;
838   x->preserve_links = false;
839   x->preserve_mode = false;
840   x->preserve_timestamps = false;
841   x->explicit_no_preserve_mode = false;
842   x->preserve_security_context = false; /* -a or --preserve=context.  */
843   x->require_preserve_context = false;  /* --preserve=context.  */
844   x->set_security_context = nullptr;       /* -Z, set sys default context. */
845   x->preserve_xattr = false;
846   x->reduce_diagnostics = false;
847   x->require_preserve_xattr = false;
848 
849   x->data_copy_required = true;
850   x->require_preserve = false;
851   x->recursive = false;
852   x->sparse_mode = SPARSE_AUTO;
853   x->symbolic_link = false;
854   x->set_mode = false;
855   x->mode = 0;
856 
857   /* Not used.  */
858   x->stdin_tty = false;
859 
860   x->update = false;
861   x->verbose = false;
862 
863   /* By default, refuse to open a dangling destination symlink, because
864      in general one cannot do that safely, give the current semantics of
865      open's O_EXCL flag, (which POSIX doesn't even allow cp to use, btw).
866      But POSIX requires it.  */
867   x->open_dangling_dest_symlink = getenv ("POSIXLY_CORRECT") != nullptr;
868 
869   x->dest_info = nullptr;
870   x->src_info = nullptr;
871 }
872 
873 /* Given a string, ARG, containing a comma-separated list of arguments
874    to the --preserve option, set the appropriate fields of X to ON_OFF.  */
875 static void
decode_preserve_arg(char const * arg,struct cp_options * x,bool on_off)876 decode_preserve_arg (char const *arg, struct cp_options *x, bool on_off)
877 {
878   enum File_attribute
879     {
880       PRESERVE_MODE,
881       PRESERVE_TIMESTAMPS,
882       PRESERVE_OWNERSHIP,
883       PRESERVE_LINK,
884       PRESERVE_CONTEXT,
885       PRESERVE_XATTR,
886       PRESERVE_ALL
887     };
888   static enum File_attribute const preserve_vals[] =
889     {
890       PRESERVE_MODE, PRESERVE_TIMESTAMPS,
891       PRESERVE_OWNERSHIP, PRESERVE_LINK, PRESERVE_CONTEXT, PRESERVE_XATTR,
892       PRESERVE_ALL
893     };
894   /* Valid arguments to the '--preserve' option. */
895   static char const *const preserve_args[] =
896     {
897       "mode", "timestamps",
898       "ownership", "links", "context", "xattr", "all", nullptr
899     };
900   ARGMATCH_VERIFY (preserve_args, preserve_vals);
901 
902   char *arg_writable = xstrdup (arg);
903   char *s = arg_writable;
904   do
905     {
906       /* find next comma */
907       char *comma = strchr (s, ',');
908       enum File_attribute val;
909 
910       /* If we found a comma, put a NUL in its place and advance.  */
911       if (comma)
912         *comma++ = 0;
913 
914       /* process S.  */
915       val = XARGMATCH (on_off ? "--preserve" : "--no-preserve",
916                        s, preserve_args, preserve_vals);
917       switch (val)
918         {
919         case PRESERVE_MODE:
920           x->preserve_mode = on_off;
921           x->explicit_no_preserve_mode = !on_off;
922           break;
923 
924         case PRESERVE_TIMESTAMPS:
925           x->preserve_timestamps = on_off;
926           break;
927 
928         case PRESERVE_OWNERSHIP:
929           x->preserve_ownership = on_off;
930           break;
931 
932         case PRESERVE_LINK:
933           x->preserve_links = on_off;
934           break;
935 
936         case PRESERVE_CONTEXT:
937           x->require_preserve_context = on_off;
938           x->preserve_security_context = on_off;
939           break;
940 
941         case PRESERVE_XATTR:
942           x->preserve_xattr = on_off;
943           x->require_preserve_xattr = on_off;
944           break;
945 
946         case PRESERVE_ALL:
947           x->preserve_mode = on_off;
948           x->preserve_timestamps = on_off;
949           x->preserve_ownership = on_off;
950           x->preserve_links = on_off;
951           x->explicit_no_preserve_mode = !on_off;
952           if (selinux_enabled)
953             x->preserve_security_context = on_off;
954           x->preserve_xattr = on_off;
955           break;
956 
957         default:
958           affirm (false);
959         }
960       s = comma;
961     }
962   while (s);
963 
964   free (arg_writable);
965 }
966 
967 int
main(int argc,char ** argv)968 main (int argc, char **argv)
969 {
970   int c;
971   bool ok;
972   bool make_backups = false;
973   char const *backup_suffix = nullptr;
974   char *version_control_string = nullptr;
975   struct cp_options x;
976   bool copy_contents = false;
977   char *target_directory = nullptr;
978   bool no_target_directory = false;
979   char const *scontext = nullptr;
980 
981   initialize_main (&argc, &argv);
982   set_program_name (argv[0]);
983   setlocale (LC_ALL, "");
984   bindtextdomain (PACKAGE, LOCALEDIR);
985   textdomain (PACKAGE);
986 
987   atexit (close_stdin);
988 
989   selinux_enabled = (0 < is_selinux_enabled ());
990   cp_option_init (&x);
991 
992   while ((c = getopt_long (argc, argv, "abdfHilLnprst:uvxPRS:TZ",
993                            long_opts, nullptr))
994          != -1)
995     {
996       switch (c)
997         {
998         case SPARSE_OPTION:
999           x.sparse_mode = XARGMATCH ("--sparse", optarg,
1000                                      sparse_type_string, sparse_type);
1001           break;
1002 
1003         case REFLINK_OPTION:
1004           if (optarg == nullptr)
1005             x.reflink_mode = REFLINK_ALWAYS;
1006           else
1007             x.reflink_mode = XARGMATCH ("--reflink", optarg,
1008                                        reflink_type_string, reflink_type);
1009           break;
1010 
1011         case 'a':
1012           /* Like -dR --preserve=all with reduced failure diagnostics.  */
1013           x.dereference = DEREF_NEVER;
1014           x.preserve_links = true;
1015           x.preserve_ownership = true;
1016           x.preserve_mode = true;
1017           x.preserve_timestamps = true;
1018           x.require_preserve = true;
1019           if (selinux_enabled)
1020              x.preserve_security_context = true;
1021           x.preserve_xattr = true;
1022           x.reduce_diagnostics = true;
1023           x.recursive = true;
1024           break;
1025 
1026         case 'b':
1027           make_backups = true;
1028           if (optarg)
1029             version_control_string = optarg;
1030           break;
1031 
1032         case ATTRIBUTES_ONLY_OPTION:
1033           x.data_copy_required = false;
1034           break;
1035 
1036         case DEBUG_OPTION:
1037           x.debug = x.verbose = true;
1038           break;
1039 
1040         case COPY_CONTENTS_OPTION:
1041           copy_contents = true;
1042           break;
1043 
1044         case 'd':
1045           x.preserve_links = true;
1046           x.dereference = DEREF_NEVER;
1047           break;
1048 
1049         case 'f':
1050           x.unlink_dest_after_failed_open = true;
1051           break;
1052 
1053         case 'H':
1054           x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
1055           break;
1056 
1057         case 'i':
1058           x.interactive = I_ASK_USER;
1059           break;
1060 
1061         case 'l':
1062           x.hard_link = true;
1063           break;
1064 
1065         case 'L':
1066           x.dereference = DEREF_ALWAYS;
1067           break;
1068 
1069         case 'n':
1070           x.interactive = I_ALWAYS_NO;
1071           break;
1072 
1073         case 'P':
1074           x.dereference = DEREF_NEVER;
1075           break;
1076 
1077         case NO_PRESERVE_ATTRIBUTES_OPTION:
1078           decode_preserve_arg (optarg, &x, false);
1079           break;
1080 
1081         case PRESERVE_ATTRIBUTES_OPTION:
1082           if (optarg == nullptr)
1083             {
1084               /* Fall through to the case for 'p' below.  */
1085             }
1086           else
1087             {
1088               decode_preserve_arg (optarg, &x, true);
1089               x.require_preserve = true;
1090               break;
1091             }
1092           FALLTHROUGH;
1093 
1094         case 'p':
1095           x.preserve_ownership = true;
1096           x.preserve_mode = true;
1097           x.preserve_timestamps = true;
1098           x.require_preserve = true;
1099           break;
1100 
1101         case PARENTS_OPTION:
1102           parents_option = true;
1103           break;
1104 
1105         case 'r':
1106         case 'R':
1107           x.recursive = true;
1108           break;
1109 
1110         case UNLINK_DEST_BEFORE_OPENING:
1111           x.unlink_dest_before_opening = true;
1112           break;
1113 
1114         case STRIP_TRAILING_SLASHES_OPTION:
1115           remove_trailing_slashes = true;
1116           break;
1117 
1118         case 's':
1119           x.symbolic_link = true;
1120           break;
1121 
1122         case 't':
1123           if (target_directory)
1124             error (EXIT_FAILURE, 0,
1125                    _("multiple target directories specified"));
1126           target_directory = optarg;
1127           break;
1128 
1129         case 'T':
1130           no_target_directory = true;
1131           break;
1132 
1133         case 'u':
1134           if (optarg == nullptr)
1135             x.update = true;
1136           else if (x.interactive != I_ALWAYS_NO)  /* -n takes precedence.  */
1137             {
1138               enum Update_type update_opt;
1139               update_opt = XARGMATCH ("--update", optarg,
1140                                       update_type_string, update_type);
1141               if (update_opt == UPDATE_ALL)
1142                 {
1143                   /* Default cp operation.  */
1144                   x.update = false;
1145                   x.interactive = I_UNSPECIFIED;
1146                 }
1147               else if (update_opt == UPDATE_NONE)
1148                 {
1149                   x.update = false;
1150                   x.interactive = I_ALWAYS_SKIP;
1151                 }
1152               else if (update_opt == UPDATE_OLDER)
1153                 {
1154                   x.update = true;
1155                   x.interactive = I_UNSPECIFIED;
1156                 }
1157             }
1158           break;
1159 
1160         case 'v':
1161           x.verbose = true;
1162           break;
1163 
1164         case 'x':
1165           x.one_file_system = true;
1166           break;
1167 
1168         case 'Z':
1169           /* politely decline if we're not on a selinux-enabled kernel.  */
1170           if (selinux_enabled)
1171             {
1172               if (optarg)
1173                 scontext = optarg;
1174               else
1175                 {
1176                   x.set_security_context = selabel_open (SELABEL_CTX_FILE,
1177                                                          nullptr, 0);
1178                   if (! x.set_security_context)
1179                     error (0, errno, _("warning: ignoring --context"));
1180                 }
1181             }
1182           else if (optarg)
1183             {
1184               error (0, 0,
1185                      _("warning: ignoring --context; "
1186                        "it requires an SELinux-enabled kernel"));
1187             }
1188           break;
1189 
1190         case 'S':
1191           make_backups = true;
1192           backup_suffix = optarg;
1193           break;
1194 
1195         case_GETOPT_HELP_CHAR;
1196 
1197         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1198 
1199         default:
1200           usage (EXIT_FAILURE);
1201         }
1202     }
1203 
1204   /* With --sparse=never, disable reflinking so we create a non sparse copy.
1205      This will also have the effect of disabling copy offload as that may
1206      propagate holes.  For e.g. FreeBSD documents that copy_file_range()
1207      will try to propagate holes.  */
1208   if (x.reflink_mode == REFLINK_AUTO && x.sparse_mode == SPARSE_NEVER)
1209     x.reflink_mode = REFLINK_NEVER;
1210 
1211   if (x.hard_link && x.symbolic_link)
1212     {
1213       error (0, 0, _("cannot make both hard and symbolic links"));
1214       usage (EXIT_FAILURE);
1215     }
1216 
1217   if (x.interactive == I_ALWAYS_NO)
1218     x.update = false;
1219 
1220   if (make_backups && x.interactive == I_ALWAYS_NO)
1221     {
1222       error (0, 0,
1223              _("options --backup and --no-clobber are mutually exclusive"));
1224       usage (EXIT_FAILURE);
1225     }
1226 
1227   if (x.reflink_mode == REFLINK_ALWAYS && x.sparse_mode != SPARSE_AUTO)
1228     {
1229       error (0, 0, _("--reflink can be used only with --sparse=auto"));
1230       usage (EXIT_FAILURE);
1231     }
1232 
1233   x.backup_type = (make_backups
1234                    ? xget_version (_("backup type"),
1235                                    version_control_string)
1236                    : no_backups);
1237   set_simple_backup_suffix (backup_suffix);
1238 
1239   if (x.dereference == DEREF_UNDEFINED)
1240     {
1241       if (x.recursive && ! x.hard_link)
1242         /* This is compatible with FreeBSD.  */
1243         x.dereference = DEREF_NEVER;
1244       else
1245         x.dereference = DEREF_ALWAYS;
1246     }
1247 
1248   if (x.recursive)
1249     x.copy_as_regular = copy_contents;
1250 
1251   /* Ensure -Z overrides -a.  */
1252   if ((x.set_security_context || scontext)
1253       && ! x.require_preserve_context)
1254     x.preserve_security_context = false;
1255 
1256   if (x.preserve_security_context && (x.set_security_context || scontext))
1257     error (EXIT_FAILURE, 0,
1258            _("cannot set target context and preserve it"));
1259 
1260   if (x.require_preserve_context && ! selinux_enabled)
1261     error (EXIT_FAILURE, 0,
1262            _("cannot preserve security context "
1263              "without an SELinux-enabled kernel"));
1264 
1265   /* FIXME: This handles new files.  But what about existing files?
1266      I.e., if updating a tree, new files would have the specified context,
1267      but shouldn't existing files be updated for consistency like this?
1268        if (scontext && !restorecon (nullptr, dst_path, 0))
1269           error (...);
1270    */
1271   if (scontext && setfscreatecon (scontext) < 0)
1272     error (EXIT_FAILURE, errno,
1273            _("failed to set default file creation context to %s"),
1274            quote (scontext));
1275 
1276 #if !USE_XATTR
1277   if (x.require_preserve_xattr)
1278     error (EXIT_FAILURE, 0, _("cannot preserve extended attributes, cp is "
1279                               "built without xattr support"));
1280 #endif
1281 
1282   /* Allocate space for remembering copied and created files.  */
1283 
1284   hash_init ();
1285 
1286   ok = do_copy (argc - optind, argv + optind,
1287                 target_directory, no_target_directory, &x);
1288 
1289   main_exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
1290 }
1291