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 {
437 /* entering a directory; append its name to to.path */
438 len = snprintf(to.end, END(to.path) - to.end, "%s%s",
439 to.end > to.path ? "/" : "", curr->fts_name);
440 if (to.end + len >= END(to.path)) {
441 *to.end = '\0';
442 warnc(ENAMETOOLONG, "%s%s%s%s", to.base,
443 to.path, to.end > to.path ? "/" : "",
444 curr->fts_name);
445 fts_set(ftsp, curr, FTS_SKIP);
446 badcp = rval = 1;
447 continue;
448 }
449 to.end += len;
450 }
451 level++;
452 /*
453 * We're on the verge of recursing on ourselves.
454 * Either we need to stop right here (we knowingly
455 * just created it), or we will in an immediate
456 * descendant. Record the path of the immediate
457 * descendant to make our lives a little less
458 * complicated looking.
459 */
460 if (type != FILE_TO_FILE &&
461 root_stat->st_dev == curr_stat->st_dev &&
462 root_stat->st_ino == curr_stat->st_ino) {
463 assert(recpath == NULL);
464 if (root_stat == &created_root_stat) {
465 /*
466 * This directory didn't exist
467 * when we started, we created it
468 * as part of traversal. Stop
469 * right here before we do
470 * something silly.
471 */
472 fts_set(ftsp, curr, FTS_SKIP);
473 continue;
474 }
475 if (asprintf(&recpath, "%s/%s", to.path,
476 rootname) < 0) {
477 warnc(ENOMEM, NULL);
478 fts_set(ftsp, curr, FTS_SKIP);
479 badcp = rval = 1;
480 continue;
481 }
482 }
483 if (recpath != NULL &&
484 strcmp(recpath, to.path) == 0) {
485 fts_set(ftsp, curr, FTS_SKIP);
486 continue;
487 }
488 break;
489 case FTS_DP:
490 /*
491 * We are nearly finished with this directory. If we
492 * didn't actually copy it, or otherwise don't need to
493 * change its attributes, then we are done.
494 *
495 * If -p is in effect, set all the attributes.
496 * Otherwise, set the correct permissions, limited
497 * by the umask. Optimise by avoiding a chmod()
498 * if possible (which is usually the case if we
499 * made the directory). Note that mkdir() does not
500 * honour setuid, setgid and sticky bits, but we
501 * normally want to preserve them on directories.
502 */
503 if (curr->fts_number && pflag) {
504 int fd = *to.path ? -1 : to.dir;
505 if (setfile(curr_stat, fd, true))
506 rval = 1;
507 if (preserve_dir_acls(curr->fts_accpath,
508 to.path) != 0)
509 rval = 1;
510 } else if (curr->fts_number) {
511 const char *path = *to.path ? to.path : dot;
512 mode = curr_stat->st_mode;
513 if (fchmodat(to.dir, path, mode & mask, 0) != 0) {
514 warn("chmod: %s%s", to.base, to.path);
515 rval = 1;
516 }
517 }
518 if (level > curr->fts_level) {
519 /* leaving a directory; remove its name from to.path */
520 if (type == DIR_TO_DNE &&
521 curr->fts_level == FTS_ROOTLEVEL) {
522 /* this is actually our created root */
523 } else {
524 while (to.end > to.path && *to.end != '/')
525 to.end--;
526 assert(strcmp(to.end + (*to.end == '/'),
527 curr->fts_name) == 0);
528 *to.end = '\0';
529 }
530 level--;
531 }
532 continue;
533 default:
534 /* something else: append its name to to.path */
535 if (type == FILE_TO_FILE)
536 break;
537 len = snprintf(to.end, END(to.path) - to.end, "%s%s",
538 to.end > to.path ? "/" : "", curr->fts_name);
539 if (to.end + len >= END(to.path)) {
540 *to.end = '\0';
541 warnc(ENAMETOOLONG, "%s%s%s%s", to.base,
542 to.path, to.end > to.path ? "/" : "",
543 curr->fts_name);
544 badcp = rval = 1;
545 continue;
546 }
547 /* intentionally do not update to.end */
548 break;
549 }
550
551 /* Not an error but need to remember it happened. */
552 if (to.path[0] == '\0') {
553 /*
554 * This can happen in two cases:
555 * - DIR_TO_DNE; we created the directory and
556 * populated root_stat earlier.
557 * - FILE_TO_DIR if a source has a trailing slash;
558 * the caller populated root_stat.
559 */
560 dne = false;
561 to_stat = *root_stat;
562 } else {
563 atflags = beneath ? AT_RESOLVE_BENEATH : 0;
564 if (curr->fts_info == FTS_D || curr->fts_info == FTS_SL)
565 atflags |= AT_SYMLINK_NOFOLLOW;
566 dne = fstatat(to.dir, to.path, &to_stat, atflags) != 0;
567 }
568
569 /* Check if source and destination are identical. */
570 if (!dne &&
571 to_stat.st_dev == curr_stat->st_dev &&
572 to_stat.st_ino == curr_stat->st_ino) {
573 warnx("%s%s and %s are identical (not copied).",
574 to.base, to.path, curr->fts_path);
575 badcp = rval = 1;
576 if (S_ISDIR(curr_stat->st_mode))
577 fts_set(ftsp, curr, FTS_SKIP);
578 continue;
579 }
580
581 switch (curr_stat->st_mode & S_IFMT) {
582 case S_IFLNK:
583 if ((fts_options & FTS_LOGICAL) ||
584 ((fts_options & FTS_COMFOLLOW) &&
585 curr->fts_level == 0)) {
586 /*
587 * We asked FTS to follow links but got
588 * here anyway, which means the target is
589 * nonexistent or inaccessible. Let
590 * copy_file() deal with the error.
591 */
592 if (copy_file(curr, dne, beneath))
593 badcp = rval = 1;
594 } else {
595 /* Copy the link. */
596 if (copy_link(curr, dne, beneath))
597 badcp = rval = 1;
598 }
599 break;
600 case S_IFDIR:
601 if (!Rflag) {
602 warnx("%s is a directory (not copied).",
603 curr->fts_path);
604 fts_set(ftsp, curr, FTS_SKIP);
605 badcp = rval = 1;
606 break;
607 }
608 /*
609 * If the directory doesn't exist, create the new
610 * one with the from file mode plus owner RWX bits,
611 * modified by the umask. Trade-off between being
612 * able to write the directory (if from directory is
613 * 555) and not causing a permissions race. If the
614 * umask blocks owner writes, we fail.
615 */
616 if (dne) {
617 mode = curr_stat->st_mode | S_IRWXU;
618 /*
619 * Will our umask prevent us from entering
620 * the directory after we create it?
621 */
622 if (~mask & S_IRWXU)
623 umask(~mask & ~S_IRWXU);
624 if (mkdirat(to.dir, to.path, mode) != 0) {
625 warn("%s%s", to.base, to.path);
626 fts_set(ftsp, curr, FTS_SKIP);
627 badcp = rval = 1;
628 if (~mask & S_IRWXU)
629 umask(~mask);
630 break;
631 }
632 if (~mask & S_IRWXU)
633 umask(~mask);
634 } else if (!S_ISDIR(to_stat.st_mode)) {
635 warnc(ENOTDIR, "%s%s", to.base, to.path);
636 fts_set(ftsp, curr, FTS_SKIP);
637 badcp = rval = 1;
638 break;
639 }
640 /*
641 * Arrange to correct directory attributes later
642 * (in the post-order phase) if this is a new
643 * directory, or if the -p flag is in effect.
644 * Note that fts_number may already be set if this
645 * is the newly created destination directory.
646 */
647 curr->fts_number |= pflag || dne;
648 break;
649 case S_IFBLK:
650 case S_IFCHR:
651 if (Rflag && !sflag) {
652 if (copy_special(curr_stat, dne, beneath))
653 badcp = rval = 1;
654 } else {
655 if (copy_file(curr, dne, beneath))
656 badcp = rval = 1;
657 }
658 break;
659 case S_IFSOCK:
660 warnx("%s is a socket (not copied).",
661 curr->fts_path);
662 break;
663 case S_IFIFO:
664 if (Rflag && !sflag) {
665 if (copy_fifo(curr_stat, dne, beneath))
666 badcp = rval = 1;
667 } else {
668 if (copy_file(curr, dne, beneath))
669 badcp = rval = 1;
670 }
671 break;
672 default:
673 if (copy_file(curr, dne, beneath))
674 badcp = rval = 1;
675 break;
676 }
677 if (vflag && !badcp)
678 (void)printf("%s -> %s%s\n", curr->fts_path, to.base, to.path);
679 }
680 assert(level == FTS_ROOTLEVEL);
681 if (errno)
682 err(1, "fts_read");
683 (void)fts_close(ftsp);
684 if (to.dir != AT_FDCWD && to.dir >= 0)
685 (void)close(to.dir);
686 free(recpath);
687 return (rval);
688 }
689
690 static void
siginfo(int sig __unused)691 siginfo(int sig __unused)
692 {
693
694 info = 1;
695 }
696