VirtualBox

source: kBuild/trunk/src/kmk/kmkbuiltin/cp.c@ 3140

Last change on this file since 3140 was 2996, checked in by bird, 9 years ago

cp.c: -r differs from -R, document -v.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.3 KB
Line 
1/*
2 * Copyright (c) 1988, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * David Hitz of Auspex Systems Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if 0
34#ifndef lint
35static char const copyright[] =
36"@(#) Copyright (c) 1988, 1993, 1994\n\
37 The Regents of the University of California. All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)cp.c 8.2 (Berkeley) 4/1/94";
42#endif /* not lint */
43#include <sys/cdefs.h>
44__FBSDID("$FreeBSD: src/bin/cp/cp.c,v 1.50 2004/04/06 20:06:44 markm Exp $");
45#endif
46
47/*
48 * Cp copies source files to target files.
49 *
50 * The global PATH_T structure "to" always contains the path to the
51 * current target file. Since fts(3) does not change directories,
52 * this path can be either absolute or dot-relative.
53 *
54 * The basic algorithm is to initialize "to" and use fts(3) to traverse
55 * the file hierarchy rooted in the argument list. A trivial case is the
56 * case of 'cp file1 file2'. The more interesting case is the case of
57 * 'cp file1 file2 ... fileN dir' where the hierarchy is traversed and the
58 * path (relative to the root of the traversal) is appended to dir (stored
59 * in "to") to form the final target path.
60 */
61
62#include "config.h"
63#include <sys/types.h>
64#include <sys/stat.h>
65
66#include "err.h"
67#include <errno.h>
68#include <fts.h>
69#include <limits.h>
70#include <signal.h>
71#include <stdio.h>
72#include <stdlib.h>
73#include <string.h>
74#include <unistd.h>
75#include "getopt.h"
76#include "k/kDefs.h"
77#ifdef _MSC_VER
78# include "mscfakes.h"
79#endif
80#include "cp_extern.h"
81#include "kmkbuiltin.h"
82#include "kbuild_protection.h"
83
84#if defined(_MSC_VER) || defined(__gnu_linux__) || defined(__linux__)
85extern size_t strlcpy(char *, const char *, size_t);
86#endif
87
88
89#ifndef S_IFWHT
90#define S_IFWHT 0
91#define S_ISWHT(s) 0
92#define undelete(s) (-1)
93#endif
94
95#ifndef S_ISTXT
96#ifdef S_ISVTX
97#define S_ISTXT S_ISVTX
98#else
99#define S_ISTXT 0
100#endif
101#endif /* !S_ISTXT */
102
103#ifndef __unused
104# define __unused
105#endif
106
107#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
108# define IS_SLASH(ch) ((ch) == '/' || (ch) == '\\')
109#else
110# define IS_SLASH(ch) ((ch) == '/')
111#endif
112
113#define STRIP_TRAILING_SLASH(p) { \
114 while ((p).p_end > (p).p_path + 1 && IS_SLASH((p).p_end[-1])) \
115 *--(p).p_end = 0; \
116}
117
118/* have wrappers for globals in cp_extern! */
119
120static KBUILDPROTECTION g_ProtData;
121const char *cp_argv0;
122static char emptystring[] = "";
123
124PATH_T to = { to.p_path, emptystring, "" };
125
126int fflag, iflag, nflag, pflag, vflag;
127static int Rflag, rflag;
128volatile sig_atomic_t info;
129static int cp_ignore_non_existing, cp_changed_only;
130
131enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
132
133enum cp_arg {
134 CP_OPT_HELP = 261,
135 CP_OPT_VERSION,
136 CP_OPT_IGNORE_NON_EXISTING,
137 CP_OPT_CHANGED,
138 CP_OPT_DISABLE_PROTECTION,
139 CP_OPT_ENABLE_PROTECTION,
140 CP_OPT_ENABLE_FULL_PROTECTION,
141 CP_OPT_DISABLE_FULL_PROTECTION,
142 CP_OPT_PROTECTION_DEPTH
143};
144static struct option long_options[] =
145{
146 { "help", no_argument, 0, CP_OPT_HELP },
147 { "version", no_argument, 0, CP_OPT_VERSION },
148 { "ignore-non-existing", no_argument, 0, CP_OPT_IGNORE_NON_EXISTING },
149 { "changed", no_argument, 0, CP_OPT_CHANGED },
150 { "disable-protection", no_argument, 0, CP_OPT_DISABLE_PROTECTION },
151 { "enable-protection", no_argument, 0, CP_OPT_ENABLE_PROTECTION },
152 { "enable-full-protection", no_argument, 0, CP_OPT_ENABLE_FULL_PROTECTION },
153 { "disable-full-protection", no_argument, 0, CP_OPT_DISABLE_FULL_PROTECTION },
154 { "protection-depth", required_argument, 0, CP_OPT_PROTECTION_DEPTH },
155 { 0, 0, 0, 0 },
156};
157
158
159static int copy(char *[], enum op, int);
160static int mastercmp(const FTSENT **, const FTSENT **);
161#ifdef SIGINFO
162static void siginfo(int __unused);
163#endif
164static int usage(FILE *);
165
166int
167kmk_builtin_cp(int argc, char *argv[], char **envp)
168{
169 struct stat to_stat, tmp_stat;
170 enum op type;
171 int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash, rc;
172 char *target;
173
174 /* init globals */
175 cp_argv0 = argv[0];
176 to.p_end = to.p_path;
177 to.target_end = emptystring;
178 memset(to.p_path, 0, sizeof(to.p_path));
179 fflag = iflag = nflag = pflag = vflag = Rflag = rflag = 0;
180 info = 0;
181 cp_ignore_non_existing = cp_changed_only = 0;
182 kBuildProtectionInit(&g_ProtData);
183
184 /* reset getopt and set progname. */
185 g_progname = argv[0];
186 opterr = 1;
187 optarg = NULL;
188 optopt = 0;
189 optind = 0; /* init */
190
191 Hflag = Lflag = Pflag = 0;
192 while ((ch = getopt_long(argc, argv, "HLPRfinprv", long_options, NULL)) != -1)
193 switch (ch) {
194 case 'H':
195 Hflag = 1;
196 Lflag = Pflag = 0;
197 break;
198 case 'L':
199 Lflag = 1;
200 Hflag = Pflag = 0;
201 break;
202 case 'P':
203 Pflag = 1;
204 Hflag = Lflag = 0;
205 break;
206 case 'R':
207 Rflag = 1;
208 break;
209 case 'f':
210 fflag = 1;
211 iflag = nflag = 0;
212 break;
213 case 'i':
214 iflag = 1;
215 fflag = nflag = 0;
216 break;
217 case 'n':
218 nflag = 1;
219 fflag = iflag = 0;
220 break;
221 case 'p':
222 pflag = 1;
223 break;
224 case 'r':
225 rflag = 1;
226 break;
227 case 'v':
228 vflag = 1;
229 break;
230 case CP_OPT_HELP:
231 usage(stdout);
232 kBuildProtectionTerm(&g_ProtData);
233 return 0;
234 case CP_OPT_VERSION:
235 kBuildProtectionTerm(&g_ProtData);
236 return kbuild_version(argv[0]);
237 case CP_OPT_IGNORE_NON_EXISTING:
238 cp_ignore_non_existing = 1;
239 break;
240 case CP_OPT_CHANGED:
241 cp_changed_only = 1;
242 break;
243 case CP_OPT_DISABLE_PROTECTION:
244 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
245 break;
246 case CP_OPT_ENABLE_PROTECTION:
247 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
248 break;
249 case CP_OPT_ENABLE_FULL_PROTECTION:
250 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
251 break;
252 case CP_OPT_DISABLE_FULL_PROTECTION:
253 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
254 break;
255 case CP_OPT_PROTECTION_DEPTH:
256 if (kBuildProtectionSetDepth(&g_ProtData, optarg)) {
257 kBuildProtectionTerm(&g_ProtData);
258 return 1;
259 }
260 break;
261 default:
262 kBuildProtectionTerm(&g_ProtData);
263 return usage(stderr);
264 }
265 argc -= optind;
266 argv += optind;
267
268 if (argc < 2) {
269 kBuildProtectionTerm(&g_ProtData);
270 return usage(stderr);
271 }
272
273 fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
274 if (rflag) {
275 if (Rflag) {
276 kBuildProtectionTerm(&g_ProtData);
277 return errx(1,
278 "the -R and -r options may not be specified together.");
279 }
280 if (Hflag || Lflag || Pflag)
281 errx(1,
282 "the -H, -L, and -P options may not be specified with the -r option.");
283 fts_options &= ~FTS_PHYSICAL;
284 fts_options |= FTS_LOGICAL;
285 }
286 if (Rflag) {
287 if (Hflag)
288 fts_options |= FTS_COMFOLLOW;
289 if (Lflag) {
290 fts_options &= ~FTS_PHYSICAL;
291 fts_options |= FTS_LOGICAL;
292 }
293 } else {
294 fts_options &= ~FTS_PHYSICAL;
295 fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
296 }
297#ifdef SIGINFO
298 (void)signal(SIGINFO, siginfo);
299#endif
300
301 /* Save the target base in "to". */
302 target = argv[--argc];
303 if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) {
304 kBuildProtectionTerm(&g_ProtData);
305 return errx(1, "%s: name too long", target);
306 }
307 to.p_end = to.p_path + strlen(to.p_path);
308 if (to.p_path == to.p_end) {
309 *to.p_end++ = '.';
310 *to.p_end = 0;
311 }
312 have_trailing_slash = IS_SLASH(to.p_end[-1]);
313 if (have_trailing_slash)
314 STRIP_TRAILING_SLASH(to);
315 to.target_end = to.p_end;
316
317 /* Set end of argument list for fts(3). */
318 argv[argc] = NULL;
319
320 /*
321 * Cp has two distinct cases:
322 *
323 * cp [-R] source target
324 * cp [-R] source1 ... sourceN directory
325 *
326 * In both cases, source can be either a file or a directory.
327 *
328 * In (1), the target becomes a copy of the source. That is, if the
329 * source is a file, the target will be a file, and likewise for
330 * directories.
331 *
332 * In (2), the real target is not directory, but "directory/source".
333 */
334 r = stat(to.p_path, &to_stat);
335 if (r == -1 && errno != ENOENT) {
336 kBuildProtectionTerm(&g_ProtData);
337 return err(1, "stat: %s", to.p_path);
338 }
339 if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
340 /*
341 * Case (1). Target is not a directory.
342 */
343 if (argc > 1) {
344 kBuildProtectionTerm(&g_ProtData);
345 return usage(stderr);
346 }
347 /*
348 * Need to detect the case:
349 * cp -R dir foo
350 * Where dir is a directory and foo does not exist, where
351 * we want pathname concatenations turned on but not for
352 * the initial mkdir().
353 */
354 if (r == -1) {
355 if (rflag || (Rflag && (Lflag || Hflag)))
356 stat(*argv, &tmp_stat);
357 else
358 lstat(*argv, &tmp_stat);
359
360 if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag))
361 type = DIR_TO_DNE;
362 else
363 type = FILE_TO_FILE;
364 } else
365 type = FILE_TO_FILE;
366
367 if (have_trailing_slash && type == FILE_TO_FILE) {
368 kBuildProtectionTerm(&g_ProtData);
369 if (r == -1)
370 return errx(1, "directory %s does not exist",
371 to.p_path);
372 else
373 return errx(1, "%s is not a directory", to.p_path);
374 }
375 } else
376 /*
377 * Case (2). Target is a directory.
378 */
379 type = FILE_TO_DIR;
380
381 /* Finally, check that the "to" directory isn't protected. */
382 rc = 1;
383 if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_CP_")
384 && !kBuildProtectionEnforce(&g_ProtData,
385 Rflag || rflag
386 ? KBUILDPROTECTIONTYPE_RECURSIVE
387 : KBUILDPROTECTIONTYPE_FULL,
388 to.p_path)) {
389 rc = copy(argv, type, fts_options);
390 }
391
392 kBuildProtectionTerm(&g_ProtData);
393 return rc;
394}
395
396static int
397copy(char *argv[], enum op type, int fts_options)
398{
399 struct stat to_stat;
400 FTS *ftsp;
401 FTSENT *curr;
402 int base = 0, dne, badcp, rval;
403 size_t nlen;
404 char *p, *target_mid;
405 mode_t mask, mode;
406
407 /*
408 * Keep an inverted copy of the umask, for use in correcting
409 * permissions on created directories when not using -p.
410 */
411 mask = ~umask(0777);
412 umask(~mask);
413
414 if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
415 return err(1, "fts_open");
416 for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
417 int copied = 0;
418
419 switch (curr->fts_info) {
420 case FTS_NS:
421 if ( cp_ignore_non_existing
422 && curr->fts_errno == ENOENT) {
423 if (vflag) {
424 warnx("fts: %s: %s", curr->fts_path,
425 strerror(curr->fts_errno));
426 }
427 continue;
428 }
429 case FTS_DNR:
430 case FTS_ERR:
431 warnx("fts: %s: %s",
432 curr->fts_path, strerror(curr->fts_errno));
433 badcp = rval = 1;
434 continue;
435 case FTS_DC: /* Warn, continue. */
436 warnx("%s: directory causes a cycle", curr->fts_path);
437 badcp = rval = 1;
438 continue;
439 default:
440 ;
441 }
442
443 /*
444 * If we are in case (2) or (3) above, we need to append the
445 * source name to the target name.
446 */
447 if (type != FILE_TO_FILE) {
448 /*
449 * Need to remember the roots of traversals to create
450 * correct pathnames. If there's a directory being
451 * copied to a non-existent directory, e.g.
452 * cp -R a/dir noexist
453 * the resulting path name should be noexist/foo, not
454 * noexist/dir/foo (where foo is a file in dir), which
455 * is the case where the target exists.
456 *
457 * Also, check for "..". This is for correct path
458 * concatenation for paths ending in "..", e.g.
459 * cp -R .. /tmp
460 * Paths ending in ".." are changed to ".". This is
461 * tricky, but seems the easiest way to fix the problem.
462 *
463 * XXX
464 * Since the first level MUST be FTS_ROOTLEVEL, base
465 * is always initialized.
466 */
467 if (curr->fts_level == FTS_ROOTLEVEL) {
468 if (type != DIR_TO_DNE) {
469 p = strrchr(curr->fts_path, '/');
470#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
471 if (strrchr(curr->fts_path, '\\') > p)
472 p = strrchr(curr->fts_path, '\\');
473#endif
474 base = (p == NULL) ? 0 :
475 (int)(p - curr->fts_path + 1);
476
477 if (!strcmp(&curr->fts_path[base],
478 ".."))
479 base += 1;
480 } else
481 base = curr->fts_pathlen;
482 }
483
484 p = &curr->fts_path[base];
485 nlen = curr->fts_pathlen - base;
486 target_mid = to.target_end;
487 if (!IS_SLASH(*p) && !IS_SLASH(target_mid[-1]))
488 *target_mid++ = '/';
489 *target_mid = 0;
490 if (target_mid - to.p_path + nlen >= PATH_MAX) {
491 warnx("%s%s: name too long (not copied)",
492 to.p_path, p);
493 badcp = rval = 1;
494 continue;
495 }
496 (void)strncat(target_mid, p, nlen);
497 to.p_end = target_mid + nlen;
498 *to.p_end = 0;
499 STRIP_TRAILING_SLASH(to);
500 }
501
502 if (curr->fts_info == FTS_DP) {
503 /*
504 * We are nearly finished with this directory. If we
505 * didn't actually copy it, or otherwise don't need to
506 * change its attributes, then we are done.
507 */
508 if (!curr->fts_number)
509 continue;
510 /*
511 * If -p is in effect, set all the attributes.
512 * Otherwise, set the correct permissions, limited
513 * by the umask. Optimise by avoiding a chmod()
514 * if possible (which is usually the case if we
515 * made the directory). Note that mkdir() does not
516 * honour setuid, setgid and sticky bits, but we
517 * normally want to preserve them on directories.
518 */
519 if (pflag) {
520 if (setfile(curr->fts_statp, -1))
521 rval = 1;
522 } else {
523 mode = curr->fts_statp->st_mode;
524 if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
525 ((mode | S_IRWXU) & mask) != (mode & mask))
526 if (chmod(to.p_path, mode & mask) != 0){
527 warn("chmod: %s", to.p_path);
528 rval = 1;
529 }
530 }
531 continue;
532 }
533
534 /* Not an error but need to remember it happened */
535 if (stat(to.p_path, &to_stat) == -1)
536 dne = 1;
537 else {
538 if (to_stat.st_dev == curr->fts_statp->st_dev &&
539 to_stat.st_dev != 0 &&
540 to_stat.st_ino == curr->fts_statp->st_ino &&
541 to_stat.st_ino != 0) {
542 warnx("%s and %s are identical (not copied).",
543 to.p_path, curr->fts_path);
544 badcp = rval = 1;
545 if (S_ISDIR(curr->fts_statp->st_mode))
546 (void)fts_set(ftsp, curr, FTS_SKIP);
547 continue;
548 }
549 if (!S_ISDIR(curr->fts_statp->st_mode) &&
550 S_ISDIR(to_stat.st_mode)) {
551 warnx("cannot overwrite directory %s with "
552 "non-directory %s",
553 to.p_path, curr->fts_path);
554 badcp = rval = 1;
555 continue;
556 }
557 dne = 0;
558 }
559
560 switch (curr->fts_statp->st_mode & S_IFMT) {
561#ifdef S_IFLNK
562 case S_IFLNK:
563 /* Catch special case of a non-dangling symlink */
564 if ((fts_options & FTS_LOGICAL) ||
565 ((fts_options & FTS_COMFOLLOW) &&
566 curr->fts_level == 0)) {
567 if (copy_file(curr, dne, cp_changed_only, &copied))
568 badcp = rval = 1;
569 } else {
570 if (copy_link(curr, !dne))
571 badcp = rval = 1;
572 }
573 break;
574#endif
575 case S_IFDIR:
576 if (!Rflag && !rflag) {
577 warnx("%s is a directory (not copied).",
578 curr->fts_path);
579 (void)fts_set(ftsp, curr, FTS_SKIP);
580 badcp = rval = 1;
581 break;
582 }
583 /*
584 * If the directory doesn't exist, create the new
585 * one with the from file mode plus owner RWX bits,
586 * modified by the umask. Trade-off between being
587 * able to write the directory (if from directory is
588 * 555) and not causing a permissions race. If the
589 * umask blocks owner writes, we fail..
590 */
591 if (dne) {
592 if (mkdir(to.p_path,
593 curr->fts_statp->st_mode | S_IRWXU) < 0)
594 return err(1, "mkdir: %s", to.p_path);
595 } else if (!S_ISDIR(to_stat.st_mode)) {
596 errno = ENOTDIR;
597 return err(1, "to-mode: %s", to.p_path);
598 }
599 /*
600 * Arrange to correct directory attributes later
601 * (in the post-order phase) if this is a new
602 * directory, or if the -p flag is in effect.
603 */
604 curr->fts_number = pflag || dne;
605 break;
606#ifdef S_IFBLK
607 case S_IFBLK:
608#endif
609 case S_IFCHR:
610 if (Rflag) {
611 if (copy_special(curr->fts_statp, !dne))
612 badcp = rval = 1;
613 } else {
614 if (copy_file(curr, dne, cp_changed_only, &copied))
615 badcp = rval = 1;
616 }
617 break;
618#ifdef S_IFIFO
619 case S_IFIFO:
620#endif
621 if (Rflag) {
622 if (copy_fifo(curr->fts_statp, !dne))
623 badcp = rval = 1;
624 } else {
625 if (copy_file(curr, dne, cp_changed_only, &copied))
626 badcp = rval = 1;
627 }
628 break;
629 default:
630 if (copy_file(curr, dne, cp_changed_only, &copied))
631 badcp = rval = 1;
632 break;
633 }
634 if (vflag && !badcp)
635 (void)printf(copied ? "%s -> %s\n" : "%s matches %s - not copied\n",
636 curr->fts_path, to.p_path);
637 }
638 if (errno)
639 return err(1, "fts_read");
640 return (rval);
641}
642
643/*
644 * mastercmp --
645 * The comparison function for the copy order. The order is to copy
646 * non-directory files before directory files. The reason for this
647 * is because files tend to be in the same cylinder group as their
648 * parent directory, whereas directories tend not to be. Copying the
649 * files first reduces seeking.
650 */
651static int
652mastercmp(const FTSENT **a, const FTSENT **b)
653{
654 int a_info, b_info;
655
656 a_info = (*a)->fts_info;
657 if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR)
658 return (0);
659 b_info = (*b)->fts_info;
660 if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR)
661 return (0);
662 if (a_info == FTS_D)
663 return (-1);
664 if (b_info == FTS_D)
665 return (1);
666 return (0);
667}
668
669#ifdef SIGINFO
670static void
671siginfo(int sig __unused)
672{
673
674 info = 1;
675}
676#endif
677
678
679static int
680usage(FILE *fp)
681{
682 fprintf(fp,
683"usage: %s [options] src target\n"
684" or: %s [options] src1 ... srcN directory\n"
685" or: %s --help\n"
686" or: %s --version\n"
687"\n"
688"Options:\n"
689" -R Recursive copy.\n"
690" -H Follow symbolic links on the commandline. Only valid with -R.\n"
691" -L Follow all symbolic links. Only valid with -R.\n"
692" -P Do not follow symbolic links. Default. Only valid with -R\n"
693" -f Force. Overrides -i and -n.\n"
694" -i Iteractive. Overrides -n and -f.\n"
695" -n Don't overwrite any files. Overrides -i and -f.\n"
696" -v Verbose.\n"
697" --ignore-non-existing\n"
698" Don't fail if the specified source file doesn't exist.\n"
699" --changed\n"
700" Only copy if changed (i.e. compare first).\n"
701" --disable-protection\n"
702" Will disable the protection file protection applied with -R.\n"
703" --enable-protection\n"
704" Will enable the protection file protection applied with -R.\n"
705" --enable-full-protection\n"
706" Will enable the protection file protection for all operations.\n"
707" --disable-full-protection\n"
708" Will disable the protection file protection for all operations.\n"
709" --protection-depth\n"
710" Number or path indicating the file protection depth. Default: %d\n"
711"\n"
712"Environment:\n"
713" KMK_CP_DISABLE_PROTECTION\n"
714" Same as --disable-protection. Overrides command line.\n"
715" KMK_CP_ENABLE_PROTECTION\n"
716" Same as --enable-protection. Overrides everyone else.\n"
717" KMK_CP_ENABLE_FULL_PROTECTION\n"
718" Same as --enable-full-protection. Overrides everyone else.\n"
719" KMK_CP_DISABLE_FULL_PROTECTION\n"
720" Same as --disable-full-protection. Overrides command line.\n"
721" KMK_CP_PROTECTION_DEPTH\n"
722" Same as --protection-depth. Overrides command line.\n"
723"\n"
724"The file protection of the top %d layers of the file hierarchy is there\n"
725"to try prevent makefiles from doing bad things to your system. This\n"
726"protection is not bulletproof, but should help prevent you from shooting\n"
727"yourself in the foot.\n"
728 ,
729 g_progname, g_progname, g_progname, g_progname,
730 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
731 return 1;
732}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette