1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1988, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * David Hitz of Auspex Systems Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 /*
36 * Cp copies source files to target files.
37 *
38 * The global PATH_T structure "to" always contains the path to the
39 * current target file. Since fts(3) does not change directories,
40 * this path can be either absolute or dot-relative.
41 *
42 * The basic algorithm is to initialize "to" and use fts(3) to traverse
43 * the file hierarchy rooted in the argument list. A trivial case is the
44 * case of 'cp file1 file2'. The more interesting case is the case of
45 * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
46 * path (relative to the root of the traversal) is appended to dir (stored
47 * in "to") to form the final target path.
48 */
49
50 #include <sys/types.h>
51 #include <sys/stat.h>
52
53 #include <assert.h>
54 #include <err.h>
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <fts.h>
58 #include <getopt.h>
59 #include <limits.h>
60 #include <signal.h>
61 #include <stdbool.h>
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <unistd.h>
66
67 #include "extern.h"
68
69 static char dot[] = ".";
70
71 #define END(buf) (buf + sizeof(buf))
72 PATH_T to = { .dir = -1, .end = to.path };
73 bool Nflag, fflag, iflag, lflag, nflag, pflag, sflag, vflag;
74 static bool Hflag, Lflag, Pflag, Rflag, rflag, Sflag;
75 volatile sig_atomic_t info;
76
77 enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
78
79 static int copy(char *[], enum op, int, struct stat *);
80 static void siginfo(int __unused);
81
82 enum {
83 SORT_OPT = CHAR_MAX,
84 };
85
86 static const struct option long_opts[] =
87 {
88 { "archive", no_argument, NULL, 'a' },
89 { "force", no_argument, NULL, 'f' },
90 { "interactive", no_argument, NULL, 'i' },
91 { "dereference", no_argument, NULL, 'L' },
92 { "link", no_argument, NULL, 'l' },
93 { "no-clobber", no_argument, NULL, 'n' },
94 { "no-dereference", no_argument, NULL, 'P' },
95 { "recursive", no_argument, NULL, 'R' },
96 { "symbolic-link", no_argument, NULL, 's' },
97 { "verbose", no_argument, NULL, 'v' },
98 { "one-file-system", no_argument, NULL, 'x' },
99 { "sort", no_argument, NULL, SORT_OPT },
100 { 0 }
101 };
102
103 int
main(int argc,char * argv[])104 main(int argc, char *argv[])
105 {
106 struct stat to_stat, tmp_stat;
107 enum op type;
108 int ch, fts_options, r;
109 char *sep, *target;
110 bool have_trailing_slash = false;
111
112 fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
113 while ((ch = getopt_long(argc, argv, "+HLPRafilNnprsvx", long_opts,
114 NULL)) != -1)
115 switch (ch) {
116 case 'H':
117 Hflag = true;
118 Lflag = Pflag = false;
119 break;
120 case 'L':
121 Lflag = true;
122 Hflag = Pflag = false;
123 break;
124 case 'P':
125 Pflag = true;
126 Hflag = Lflag = false;
127 break;
128 case 'R':
129 Rflag = true;
130 break;
131 case 'a':
132 pflag = true;
133 Rflag = true;
134 Pflag = true;
135 Hflag = Lflag = false;
136 break;
137 case 'f':
138 fflag = true;
139 iflag = nflag = false;
140 break;
141 case 'i':
142 iflag = true;
143 fflag = nflag = false;
144 break;
145 case 'l':
146 lflag = true;
147 break;
148 case 'N':
149 Nflag = true;
150 break;
151 case 'n':
152 nflag = true;
153 fflag = iflag = false;
154 break;
155 case 'p':
156 pflag = true;
157 break;
158 case 'r':
159 rflag = Lflag = true;
160 Hflag = Pflag = false;
161 break;
162 case 's':
163 sflag = true;
164 break;
165 case 'v':
166 vflag = true;
167 break;
168 case 'x':
169 fts_options |= FTS_XDEV;
170 break;
171 case SORT_OPT:
172 Sflag = true;
173 break;
174 default:
175 usage();
176 }
177 argc -= optind;
178 argv += optind;
179
180 if (argc < 2)
181 usage();
182
183 if (Rflag && rflag)
184 errx(1, "the -R and -r options may not be specified together");
185 if (lflag && sflag)
186 errx(1, "the -l and -s options may not be specified together");
187 if (rflag)
188 Rflag = true;
189 if (Rflag) {
190 if (Hflag)
191 fts_options |= FTS_COMFOLLOW;
192 if (Lflag) {
193 fts_options &= ~FTS_PHYSICAL;
194 fts_options |= FTS_LOGICAL;
195 }
196 } else if (!Pflag) {
197 fts_options &= ~FTS_PHYSICAL;
198 fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
199 }
200 (void)signal(SIGINFO, siginfo);
201
202 /* Save the target base in "to". */
203 target = argv[--argc];
204 if (*target == '\0') {
205 target = dot;
206 } else if ((sep = strrchr(target, '/')) != NULL && sep[1] == '\0') {
207 have_trailing_slash = true;
208 while (sep > target && *sep == '/')
209 sep--;
210 sep[1] = '\0';
211 }
212 /*
213 * Copy target into to.base, leaving room for a possible separator
214 * which will be appended later in the non-FILE_TO_FILE cases.
215 */
216 if (strlcpy(to.base, target, sizeof(to.base) - 1) >=
217 sizeof(to.base) - 1)
218 errc(1, ENAMETOOLONG, "%s", target);
219
220 /* Set end of argument list for fts(3). */
221 argv[argc] = NULL;
222
223 /*
224 * Cp has two distinct cases:
225 *
226 * cp [-R] source target
227 * cp [-R] source1 ... sourceN directory
228 *
229 * In both cases, source can be either a file or a directory.
230 *
231 * In (1), the target becomes a copy of the source. That is, if the
232 * source is a file, the target will be a file, and likewise for
233 * directories.
234 *
235 * In (2), the real target is not directory, but "directory/source".
236 */
237 r = stat(to.base, &to_stat);
238 if (r == -1 && errno != ENOENT)
239 err(1, "%s", target);
240 if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
241 /*
242 * Case (1). Target is not a directory.
243 */
244 if (argc > 1)
245 errc(1, ENOTDIR, "%s", target);
246
247 /*
248 * Need to detect the case:
249 * cp -R dir foo
250 * Where dir is a directory and foo does not exist, where
251 * we want pathname concatenations turned on but not for
252 * the initial mkdir().
253 */
254 if (r == -1) {
255 if (Rflag && (Lflag || Hflag))
256 stat(*argv, &tmp_stat);
257 else
258 lstat(*argv, &tmp_stat);
259
260 if (S_ISDIR(tmp_stat.st_mode) && Rflag)
261 type = DIR_TO_DNE;
262 else
263 type = FILE_TO_FILE;
264 } else
265 type = FILE_TO_FILE;
266
267 if (have_trailing_slash && type == FILE_TO_FILE) {
268 if (r == -1)
269 errc(1, ENOENT, "%s", target);
270 else
271 errc(1, ENOTDIR, "%s", target);
272 }
273 } else {
274 /*
275 * Case (2). Target is a directory.
276 */
277 type = FILE_TO_DIR;
278 }
279
280 /*
281 * For DIR_TO_DNE, we could provide copy() with the to_stat we've
282 * already allocated on the stack here that isn't being used for
283 * anything. Not doing so, though, simplifies later logic a little bit
284 * as we need to skip checking root_stat on the first iteration and
285 * ensure that we set it with the first mkdir().
286 */
287 exit (copy(argv, type, fts_options, (type == DIR_TO_DNE ? NULL :
288 &to_stat)));
289 }
290
291 static int
ftscmp(const FTSENT * const * a,const FTSENT * const * b)292 ftscmp(const FTSENT * const *a, const FTSENT * const *b)
293 {
294 return (strcmp((*a)->fts_name, (*b)->fts_name));
295 }
296
297 static int
copy(char * argv[],enum op type,int fts_options,struct stat * root_stat)298 copy(char *argv[], enum op type, int fts_options, struct stat *root_stat)
299 {
300 char rootname[NAME_MAX];
301 struct stat created_root_stat, to_stat, *curr_stat;
302 FTS *ftsp;
303 FTSENT *curr;
304 char *recpath = NULL, *sep;
305 int atflags, dne, badcp, len, level, rval;
306 mode_t mask, mode;
307 bool beneath = Rflag && type != FILE_TO_FILE;
308
309 /*
310 * Keep an inverted copy of the umask, for use in correcting
311 * permissions on created directories when not using -p.
312 */
313 mask = ~umask(0777);
314 umask(~mask);
315
316 if (type == FILE_TO_FILE) {
317 to.dir = AT_FDCWD;
318 to.end = to.path + strlcpy(to.path, to.base, sizeof(to.path));
319 to.base[0] = '\0';
320 } else if (type == FILE_TO_DIR) {
321 to.dir = open(to.base, O_DIRECTORY | O_SEARCH);
322 if (to.dir < 0)
323 err(1, "%s", to.base);
324 /*
325 * We have previously made sure there is room for this.
326 */
327 if (strcmp(to.base, "/") != 0) {
328 sep = strchr(to.base, '\0');
329 sep[0] = '/';
330 sep[1] = '\0';
331 }
332 } else {
333 /*
334 * We will create the destination directory imminently.
335 */
336 to.dir = -1;
337 }
338
339 level = FTS_ROOTLEVEL;
340 if ((ftsp = fts_open(argv, fts_options, Sflag ? ftscmp : NULL)) == NULL)
341 err(1, "fts_open");
342 for (badcp = rval = 0;
343 (curr = fts_read(ftsp)) != NULL;
344 badcp = 0, *to.end = '\0') {
345 curr_stat = curr->fts_statp;
346 switch (curr->fts_info) {
347 case FTS_NS:
348 case FTS_DNR:
349 case FTS_ERR:
350 if (level > curr->fts_level) {
351 /* leaving a directory; remove its name from to.path */
352 if (type == DIR_TO_DNE &&
353 curr->fts_level == FTS_ROOTLEVEL) {
354 /* this is actually our created root */
355 } else {
356 while (to.end > to.path && *to.end != '/')
357 to.end--;
358 assert(strcmp(to.end + (*to.end == '/'),
359 curr->fts_name) == 0);
360 *to.end = '\0';
361 }
362 level--;
363 }
364 warnc(curr->fts_errno, "%s", curr->fts_path);
365 badcp = rval = 1;
366 continue;
367 case FTS_DC: /* Warn, continue. */
368 warnx("%s: directory causes a cycle", curr->fts_path);
369 badcp = rval = 1;
370 continue;
371 case FTS_D:
372 /*
373 * Stash the root basename off for detecting
374 * recursion later.
375 *
376 * This will be essential if the root is a symlink
377 * and we're rolling with -L or -H. The later
378 * bits will need this bit in particular.
379 */
380 if (curr->fts_level == FTS_ROOTLEVEL) {
381 strlcpy(rootname, curr->fts_name,
382 sizeof(rootname));
383 }
384 /* we must have a destination! */
385 if (type == DIR_TO_DNE &&
386 curr->fts_level == FTS_ROOTLEVEL) {
387 assert(to.dir < 0);
388 assert(root_stat == NULL);
389 mode = curr_stat->st_mode | S_IRWXU;
390 /*
391 * Will our umask prevent us from entering
392 * the directory after we create it?
393 */
394 if (~mask & S_IRWXU)
395 umask(~mask & ~S_IRWXU);
396 if (mkdir(to.base, mode) != 0) {
397 warn("%s", to.base);
398 fts_set(ftsp, curr, FTS_SKIP);
399 badcp = rval = 1;
400 if (~mask & S_IRWXU)
401 umask(~mask);
402 continue;
403 }
404 to.dir = open(to.base, O_DIRECTORY | O_SEARCH);
405 if (to.dir < 0) {
406 warn("%s", to.base);
407 (void)rmdir(to.base);
408 fts_set(ftsp, curr, FTS_SKIP);
409 badcp = rval = 1;
410 if (~mask & S_IRWXU)
411 umask(~mask);
412 continue;
413 }
414 if (fstat(to.dir, &created_root_stat) != 0) {
415 warn("%s", to.base);
416 (void)close(to.dir);
417 (void)rmdir(to.base);
418 fts_set(ftsp, curr, FTS_SKIP);
419 to.dir = -1;
420 badcp = rval = 1;
421 if (~mask & S_IRWXU)
422 umask(~mask);
423 continue;
424 }
425 if (~mask & S_IRWXU)
426 umask(~mask);
427 root_stat = &created_root_stat;
428 curr->fts_number = 1;
429 /*
430 * We have previously made sure there is
431 * room for this.
432 */
433 sep = strchr(to.base, '\0');
434 sep[0] = '/';
435 sep[1] = '\0';
436 } else if (strcmp(curr->fts_name, "/") == 0) {
437 /* special case when source is the root directory */
438 } else {
439 /* entering a directory; append its name to to.path */
440 len = snprintf(to.end, END(to.path) - to.end, "%s%s",
441 to.end > to.path ? "/" : "", curr->fts_name);
442 if (to.end + len >= END(to.path)) {
443 *to.end = '\0';
444 warnc(ENAMETOOLONG, "%s%s%s%s", to.base,
445 to.path, to.end > to.path ? "/" : "",
446 curr->fts_name);
447 fts_set(ftsp, curr, FTS_SKIP);
448 badcp = rval = 1;
449 continue;
450 }
451 to.end += len;
452 }
453 level++;
454 /*
455 * We're on the verge of recursing on ourselves.
456 * Either we need to stop right here (we knowingly
457 * just created it), or we will in an immediate
458 * descendant. Record the path of the immediate
459 * descendant to make our lives a little less
460 * complicated looking.
461 */
462 if (type != FILE_TO_FILE &&
463 root_stat->st_dev == curr_stat->st_dev &&
464 root_stat->st_ino == curr_stat->st_ino) {
465 assert(recpath == NULL);
466 if (root_stat == &created_root_stat) {
467 /*
468 * This directory didn't exist
469 * when we started, we created it
470 * as part of traversal. Stop
471 * right here before we do
472 * something silly.
473 */
474 fts_set(ftsp, curr, FTS_SKIP);
475 continue;
476 }
477 if (asprintf(&recpath, "%s/%s", to.path,
478 rootname) < 0) {
479 warnc(ENOMEM, NULL);
480 fts_set(ftsp, curr, FTS_SKIP);
481 badcp = rval = 1;
482 continue;
483 }
484 }
485 if (recpath != NULL &&
486 strcmp(recpath, to.path) == 0) {
487 fts_set(ftsp, curr, FTS_SKIP);
488 continue;
489 }
490 break;
491 case FTS_DP:
492 /*
493 * We are nearly finished with this directory. If we
494 * didn't actually copy it, or otherwise don't need to
495 * change its attributes, then we are done.
496 *
497 * If -p is in effect, set all the attributes.
498 * Otherwise, set the correct permissions, limited
499 * by the umask. Optimise by avoiding a chmod()
500 * if possible (which is usually the case if we
501 * made the directory). Note that mkdir() does not
502 * honour setuid, setgid and sticky bits, but we
503 * normally want to preserve them on directories.
504 */
505 if (curr->fts_number && pflag) {
506 int fd = *to.path ? -1 : to.dir;
507 if (setfile(curr_stat, fd, true))
508 rval = 1;
509 if (preserve_dir_acls(curr->fts_accpath,
510 to.path) != 0)
511 rval = 1;
512 } else if (curr->fts_number) {
513 const char *path = *to.path ? to.path : dot;
514 mode = curr_stat->st_mode;
515 if (fchmodat(to.dir, path, mode & mask, 0) != 0) {
516 warn("chmod: %s%s", to.base, to.path);
517 rval = 1;
518 }
519 }
520 if (level > curr->fts_level) {
521 /* leaving a directory; remove its name from to.path */
522 if (type == DIR_TO_DNE &&
523 curr->fts_level == FTS_ROOTLEVEL) {
524 /* this is actually our created root */
525 } else if (strcmp(curr->fts_name, "/") == 0) {
526 /* special case when source is the root directory */
527 } else {
528 while (to.end > to.path && *to.end != '/')
529 to.end--;
530 assert(strcmp(to.end + (*to.end == '/'),
531 curr->fts_name) == 0);
532 *to.end = '\0';
533 }
534 level--;
535 }
536 continue;
537 default:
538 /* something else: append its name to to.path */
539 if (type == FILE_TO_FILE)
540 break;
541 len = snprintf(to.end, END(to.path) - to.end, "%s%s",
542 to.end > to.path ? "/" : "", curr->fts_name);
543 if (to.end + len >= END(to.path)) {
544 *to.end = '\0';
545 warnc(ENAMETOOLONG, "%s%s%s%s", to.base,
546 to.path, to.end > to.path ? "/" : "",
547 curr->fts_name);
548 badcp = rval = 1;
549 continue;
550 }
551 /* intentionally do not update to.end */
552 break;
553 }
554
555 /* Not an error but need to remember it happened. */
556 if (to.path[0] == '\0') {
557 /*
558 * This can happen in three cases:
559 * - The source path is the root directory.
560 * - DIR_TO_DNE; we created the directory and
561 * populated root_stat earlier.
562 * - FILE_TO_DIR if a source has a trailing slash;
563 * the caller populated root_stat.
564 */
565 dne = false;
566 to_stat = *root_stat;
567 } else {
568 atflags = beneath ? AT_RESOLVE_BENEATH : 0;
569 if (curr->fts_info == FTS_D || curr->fts_info == FTS_SL)
570 atflags |= AT_SYMLINK_NOFOLLOW;
571 dne = fstatat(to.dir, to.path, &to_stat, atflags) != 0;
572 }
573
574 /* Check if source and destination are identical. */
575 if (!dne &&
576 to_stat.st_dev == curr_stat->st_dev &&
577 to_stat.st_ino == curr_stat->st_ino) {
578 warnx("%s%s and %s are identical (not copied).",
579 to.base, to.path, curr->fts_path);
580 badcp = rval = 1;
581 if (S_ISDIR(curr_stat->st_mode))
582 fts_set(ftsp, curr, FTS_SKIP);
583 continue;
584 }
585
586 switch (curr_stat->st_mode & S_IFMT) {
587 case S_IFLNK:
588 if ((fts_options & FTS_LOGICAL) ||
589 ((fts_options & FTS_COMFOLLOW) &&
590 curr->fts_level == 0)) {
591 /*
592 * We asked FTS to follow links but got
593 * here anyway, which means the target is
594 * nonexistent or inaccessible. Let
595 * copy_file() deal with the error.
596 */
597 if (copy_file(curr, dne, beneath))
598 badcp = rval = 1;
599 } else {
600 /* Copy the link. */
601 if (copy_link(curr, dne, beneath))
602 badcp = rval = 1;
603 }
604 break;
605 case S_IFDIR:
606 if (!Rflag) {
607 warnx("%s is a directory (not copied).",
608 curr->fts_path);
609 fts_set(ftsp, curr, FTS_SKIP);
610 badcp = rval = 1;
611 break;
612 }
613 /*
614 * If the directory doesn't exist, create the new
615 * one with the from file mode plus owner RWX bits,
616 * modified by the umask. Trade-off between being
617 * able to write the directory (if from directory is
618 * 555) and not causing a permissions race. If the
619 * umask blocks owner writes, we fail.
620 */
621 if (dne) {
622 mode = curr_stat->st_mode | S_IRWXU;
623 /*
624 * Will our umask prevent us from entering
625 * the directory after we create it?
626 */
627 if (~mask & S_IRWXU)
628 umask(~mask & ~S_IRWXU);
629 if (mkdirat(to.dir, to.path, mode) != 0) {
630 warn("%s%s", to.base, to.path);
631 fts_set(ftsp, curr, FTS_SKIP);
632 badcp = rval = 1;
633 if (~mask & S_IRWXU)
634 umask(~mask);
635 break;
636 }
637 if (~mask & S_IRWXU)
638 umask(~mask);
639 } else if (!S_ISDIR(to_stat.st_mode)) {
640 warnc(ENOTDIR, "%s%s", to.base, to.path);
641 fts_set(ftsp, curr, FTS_SKIP);
642 badcp = rval = 1;
643 break;
644 }
645 /*
646 * Arrange to correct directory attributes later
647 * (in the post-order phase) if this is a new
648 * directory, or if the -p flag is in effect.
649 * Note that fts_number may already be set if this
650 * is the newly created destination directory.
651 */
652 curr->fts_number |= pflag || dne;
653 break;
654 case S_IFBLK:
655 case S_IFCHR:
656 if (Rflag && !sflag) {
657 if (copy_special(curr_stat, dne, beneath))
658 badcp = rval = 1;
659 } else {
660 if (copy_file(curr, dne, beneath))
661 badcp = rval = 1;
662 }
663 break;
664 case S_IFSOCK:
665 warnx("%s is a socket (not copied).",
666 curr->fts_path);
667 break;
668 case S_IFIFO:
669 if (Rflag && !sflag) {
670 if (copy_fifo(curr_stat, dne, beneath))
671 badcp = rval = 1;
672 } else {
673 if (copy_file(curr, dne, beneath))
674 badcp = rval = 1;
675 }
676 break;
677 default:
678 if (copy_file(curr, dne, beneath))
679 badcp = rval = 1;
680 break;
681 }
682 if (vflag && !badcp)
683 (void)printf("%s -> %s%s\n", curr->fts_path, to.base, to.path);
684 }
685 assert(level == FTS_ROOTLEVEL);
686 if (errno)
687 err(1, "fts_read");
688 (void)fts_close(ftsp);
689 if (to.dir != AT_FDCWD && to.dir >= 0)
690 (void)close(to.dir);
691 free(recpath);
692 return (rval);
693 }
694
695 static void
siginfo(int sig __unused)696 siginfo(int sig __unused)
697 {
698
699 info = 1;
700 }
701