VirtualBox

source: kBuild/branches/kBuild-0.1.5/src/kmk/kmkbuiltin/cp.c@ 2368

Last change on this file since 2368 was 2206, checked in by bird, 16 years ago

cp.c: solaris build fix (strlcpy).

  • 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 char *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#if 0 /* only one -R */
225 case 'r':
226 rflag = 1;
227 break;
228#endif
229 case 'v':
230 vflag = 1;
231 break;
232 case CP_OPT_HELP:
233 usage(stdout);
234 kBuildProtectionTerm(&g_ProtData);
235 return 0;
236 case CP_OPT_VERSION:
237 kBuildProtectionTerm(&g_ProtData);
238 return kbuild_version(argv[0]);
239 case CP_OPT_IGNORE_NON_EXISTING:
240 cp_ignore_non_existing = 1;
241 break;
242 case CP_OPT_CHANGED:
243 cp_changed_only = 1;
244 break;
245 case CP_OPT_DISABLE_PROTECTION:
246 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
247 break;
248 case CP_OPT_ENABLE_PROTECTION:
249 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
250 break;
251 case CP_OPT_ENABLE_FULL_PROTECTION:
252 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
253 break;
254 case CP_OPT_DISABLE_FULL_PROTECTION:
255 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
256 break;
257 case CP_OPT_PROTECTION_DEPTH:
258 if (kBuildProtectionSetDepth(&g_ProtData, optarg)) {
259 kBuildProtectionTerm(&g_ProtData);
260 return 1;
261 }
262 break;
263 default:
264 kBuildProtectionTerm(&g_ProtData);
265 return usage(stderr);
266 }
267 argc -= optind;
268 argv += optind;
269
270 if (argc < 2) {
271 kBuildProtectionTerm(&g_ProtData);
272 return usage(stderr);
273 }
274
275 fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
276 if (rflag) {
277 if (Rflag) {
278 kBuildProtectionTerm(&g_ProtData);
279 return errx(1,
280 "the -R and -r options may not be specified together.");
281 }
282 if (Hflag || Lflag || Pflag)
283 errx(1,
284 "the -H, -L, and -P options may not be specified with the -r option.");
285 fts_options &= ~FTS_PHYSICAL;
286 fts_options |= FTS_LOGICAL;
287 }
288 if (Rflag) {
289 if (Hflag)
290 fts_options |= FTS_COMFOLLOW;
291 if (Lflag) {
292 fts_options &= ~FTS_PHYSICAL;
293 fts_options |= FTS_LOGICAL;
294 }
295 } else {
296 fts_options &= ~FTS_PHYSICAL;
297 fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
298 }
299#ifdef SIGINFO
300 (void)signal(SIGINFO, siginfo);
301#endif
302
303 /* Save the target base in "to". */
304 target = argv[--argc];
305 if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path)) {
306 kBuildProtectionTerm(&g_ProtData);
307 return errx(1, "%s: name too long", target);
308 }
309 to.p_end = to.p_path + strlen(to.p_path);
310 if (to.p_path == to.p_end) {
311 *to.p_end++ = '.';
312 *to.p_end = 0;
313 }
314 have_trailing_slash = IS_SLASH(to.p_end[-1]);
315 if (have_trailing_slash)
316 STRIP_TRAILING_SLASH(to);
317 to.target_end = to.p_end;
318
319 /* Set end of argument list for fts(3). */
320 argv[argc] = NULL;
321
322 /*
323 * Cp has two distinct cases:
324 *
325 * cp [-R] source target
326 * cp [-R] source1 ... sourceN directory
327 *
328 * In both cases, source can be either a file or a directory.
329 *
330 * In (1), the target becomes a copy of the source. That is, if the
331 * source is a file, the target will be a file, and likewise for
332 * directories.
333 *
334 * In (2), the real target is not directory, but "directory/source".
335 */
336 r = stat(to.p_path, &to_stat);
337 if (r == -1 && errno != ENOENT) {
338 kBuildProtectionTerm(&g_ProtData);
339 return err(1, "%s", to.p_path);
340 }
341 if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
342 /*
343 * Case (1). Target is not a directory.
344 */
345 if (argc > 1) {
346 kBuildProtectionTerm(&g_ProtData);
347 return usage(stderr);
348 }
349 /*
350 * Need to detect the case:
351 * cp -R dir foo
352 * Where dir is a directory and foo does not exist, where
353 * we want pathname concatenations turned on but not for
354 * the initial mkdir().
355 */
356 if (r == -1) {
357 if (rflag || (Rflag && (Lflag || Hflag)))
358 stat(*argv, &tmp_stat);
359 else
360 lstat(*argv, &tmp_stat);
361
362 if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag))
363 type = DIR_TO_DNE;
364 else
365 type = FILE_TO_FILE;
366 } else
367 type = FILE_TO_FILE;
368
369 if (have_trailing_slash && type == FILE_TO_FILE) {
370 kBuildProtectionTerm(&g_ProtData);
371 if (r == -1)
372 return errx(1, "directory %s does not exist",
373 to.p_path);
374 else
375 return errx(1, "%s is not a directory", to.p_path);
376 }
377 } else
378 /*
379 * Case (2). Target is a directory.
380 */
381 type = FILE_TO_DIR;
382
383 /* Finally, check that the "to" directory isn't protected. */
384 rc = 1;
385 if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_CP_")
386 && !kBuildProtectionEnforce(&g_ProtData,
387 Rflag || rflag
388 ? KBUILDPROTECTIONTYPE_RECURSIVE
389 : KBUILDPROTECTIONTYPE_FULL,
390 to.p_path)) {
391 rc = copy(argv, type, fts_options);
392 }
393
394 kBuildProtectionTerm(&g_ProtData);
395 return rc;
396}
397
398static int
399copy(char *argv[], enum op type, int fts_options)
400{
401 struct stat to_stat;
402 FTS *ftsp;
403 FTSENT *curr;
404 int base = 0, dne, badcp, rval;
405 size_t nlen;
406 char *p, *target_mid;
407 mode_t mask, mode;
408
409 /*
410 * Keep an inverted copy of the umask, for use in correcting
411 * permissions on created directories when not using -p.
412 */
413 mask = ~umask(0777);
414 umask(~mask);
415
416 if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
417 return err(1, "fts_open");
418 for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
419 int copied = 0;
420
421 switch (curr->fts_info) {
422 case FTS_NS:
423 if ( cp_ignore_non_existing
424 && curr->fts_errno == ENOENT) {
425 if (vflag) {
426 warnx("%s: %s", curr->fts_path,
427 strerror(curr->fts_errno));
428 }
429 continue;
430 }
431 case FTS_DNR:
432 case FTS_ERR:
433 warnx("%s: %s",
434 curr->fts_path, strerror(curr->fts_errno));
435 badcp = rval = 1;
436 continue;
437 case FTS_DC: /* Warn, continue. */
438 warnx("%s: directory causes a cycle", curr->fts_path);
439 badcp = rval = 1;
440 continue;
441 default:
442 ;
443 }
444
445 /*
446 * If we are in case (2) or (3) above, we need to append the
447 * source name to the target name.
448 */
449 if (type != FILE_TO_FILE) {
450 /*
451 * Need to remember the roots of traversals to create
452 * correct pathnames. If there's a directory being
453 * copied to a non-existent directory, e.g.
454 * cp -R a/dir noexist
455 * the resulting path name should be noexist/foo, not
456 * noexist/dir/foo (where foo is a file in dir), which
457 * is the case where the target exists.
458 *
459 * Also, check for "..". This is for correct path
460 * concatenation for paths ending in "..", e.g.
461 * cp -R .. /tmp
462 * Paths ending in ".." are changed to ".". This is
463 * tricky, but seems the easiest way to fix the problem.
464 *
465 * XXX
466 * Since the first level MUST be FTS_ROOTLEVEL, base
467 * is always initialized.
468 */
469 if (curr->fts_level == FTS_ROOTLEVEL) {
470 if (type != DIR_TO_DNE) {
471 p = strrchr(curr->fts_path, '/');
472#if K_OS == K_OS_WINDOWS || K_OS == K_OS_OS2
473 if (strrchr(curr->fts_path, '\\') > p)
474 p = strrchr(curr->fts_path, '\\');
475#endif
476 base = (p == NULL) ? 0 :
477 (int)(p - curr->fts_path + 1);
478
479 if (!strcmp(&curr->fts_path[base],
480 ".."))
481 base += 1;
482 } else
483 base = curr->fts_pathlen;
484 }
485
486 p = &curr->fts_path[base];
487 nlen = curr->fts_pathlen - base;
488 target_mid = to.target_end;
489 if (!IS_SLASH(*p) && !IS_SLASH(target_mid[-1]))
490 *target_mid++ = '/';
491 *target_mid = 0;
492 if (target_mid - to.p_path + nlen >= PATH_MAX) {
493 warnx("%s%s: name too long (not copied)",
494 to.p_path, p);
495 badcp = rval = 1;
496 continue;
497 }
498 (void)strncat(target_mid, p, nlen);
499 to.p_end = target_mid + nlen;
500 *to.p_end = 0;
501 STRIP_TRAILING_SLASH(to);
502 }
503
504 if (curr->fts_info == FTS_DP) {
505 /*
506 * We are nearly finished with this directory. If we
507 * didn't actually copy it, or otherwise don't need to
508 * change its attributes, then we are done.
509 */
510 if (!curr->fts_number)
511 continue;
512 /*
513 * If -p is in effect, set all the attributes.
514 * Otherwise, set the correct permissions, limited
515 * by the umask. Optimise by avoiding a chmod()
516 * if possible (which is usually the case if we
517 * made the directory). Note that mkdir() does not
518 * honour setuid, setgid and sticky bits, but we
519 * normally want to preserve them on directories.
520 */
521 if (pflag) {
522 if (setfile(curr->fts_statp, -1))
523 rval = 1;
524 } else {
525 mode = curr->fts_statp->st_mode;
526 if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
527 ((mode | S_IRWXU) & mask) != (mode & mask))
528 if (chmod(to.p_path, mode & mask) != 0){
529 warn("chmod: %s", to.p_path);
530 rval = 1;
531 }
532 }
533 continue;
534 }
535
536 /* Not an error but need to remember it happened */
537 if (stat(to.p_path, &to_stat) == -1)
538 dne = 1;
539 else {
540 if (to_stat.st_dev == curr->fts_statp->st_dev &&
541 to_stat.st_dev != 0 &&
542 to_stat.st_ino == curr->fts_statp->st_ino &&
543 to_stat.st_ino != 0) {
544 warnx("%s and %s are identical (not copied).",
545 to.p_path, curr->fts_path);
546 badcp = rval = 1;
547 if (S_ISDIR(curr->fts_statp->st_mode))
548 (void)fts_set(ftsp, curr, FTS_SKIP);
549 continue;
550 }
551 if (!S_ISDIR(curr->fts_statp->st_mode) &&
552 S_ISDIR(to_stat.st_mode)) {
553 warnx("cannot overwrite directory %s with "
554 "non-directory %s",
555 to.p_path, curr->fts_path);
556 badcp = rval = 1;
557 continue;
558 }
559 dne = 0;
560 }
561
562 switch (curr->fts_statp->st_mode & S_IFMT) {
563#ifdef S_IFLNK
564 case S_IFLNK:
565 /* Catch special case of a non-dangling symlink */
566 if ((fts_options & FTS_LOGICAL) ||
567 ((fts_options & FTS_COMFOLLOW) &&
568 curr->fts_level == 0)) {
569 if (copy_file(curr, dne, cp_changed_only, &copied))
570 badcp = rval = 1;
571 } else {
572 if (copy_link(curr, !dne))
573 badcp = rval = 1;
574 }
575 break;
576#endif
577 case S_IFDIR:
578 if (!Rflag && !rflag) {
579 warnx("%s is a directory (not copied).",
580 curr->fts_path);
581 (void)fts_set(ftsp, curr, FTS_SKIP);
582 badcp = rval = 1;
583 break;
584 }
585 /*
586 * If the directory doesn't exist, create the new
587 * one with the from file mode plus owner RWX bits,
588 * modified by the umask. Trade-off between being
589 * able to write the directory (if from directory is
590 * 555) and not causing a permissions race. If the
591 * umask blocks owner writes, we fail..
592 */
593 if (dne) {
594 if (mkdir(to.p_path,
595 curr->fts_statp->st_mode | S_IRWXU) < 0)
596 return err(1, "%s", to.p_path);
597 } else if (!S_ISDIR(to_stat.st_mode)) {
598 errno = ENOTDIR;
599 return err(1, "%s", to.p_path);
600 }
601 /*
602 * Arrange to correct directory attributes later
603 * (in the post-order phase) if this is a new
604 * directory, or if the -p flag is in effect.
605 */
606 curr->fts_number = pflag || dne;
607 break;
608#ifdef S_IFBLK
609 case S_IFBLK:
610#endif
611 case S_IFCHR:
612 if (Rflag) {
613 if (copy_special(curr->fts_statp, !dne))
614 badcp = rval = 1;
615 } else {
616 if (copy_file(curr, dne, cp_changed_only, &copied))
617 badcp = rval = 1;
618 }
619 break;
620#ifdef S_IFIFO
621 case S_IFIFO:
622#endif
623 if (Rflag) {
624 if (copy_fifo(curr->fts_statp, !dne))
625 badcp = rval = 1;
626 } else {
627 if (copy_file(curr, dne, cp_changed_only, &copied))
628 badcp = rval = 1;
629 }
630 break;
631 default:
632 if (copy_file(curr, dne, cp_changed_only, &copied))
633 badcp = rval = 1;
634 break;
635 }
636 if (vflag && !badcp)
637 (void)printf(copied ? "%s -> %s\n" : "%s matches %s - not copied\n",
638 curr->fts_path, to.p_path);
639 }
640 if (errno)
641 return err(1, "fts_read");
642 return (rval);
643}
644
645/*
646 * mastercmp --
647 * The comparison function for the copy order. The order is to copy
648 * non-directory files before directory files. The reason for this
649 * is because files tend to be in the same cylinder group as their
650 * parent directory, whereas directories tend not to be. Copying the
651 * files first reduces seeking.
652 */
653static int
654mastercmp(const FTSENT **a, const FTSENT **b)
655{
656 int a_info, b_info;
657
658 a_info = (*a)->fts_info;
659 if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR)
660 return (0);
661 b_info = (*b)->fts_info;
662 if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR)
663 return (0);
664 if (a_info == FTS_D)
665 return (-1);
666 if (b_info == FTS_D)
667 return (1);
668 return (0);
669}
670
671#ifdef SIGINFO
672static void
673siginfo(int sig __unused)
674{
675
676 info = 1;
677}
678#endif
679
680
681static int
682usage(FILE *fp)
683{
684 fprintf(fp,
685"usage: %s [options] src target\n"
686" or: %s [options] src1 ... srcN directory\n"
687" or: %s --help\n"
688" or: %s --version\n"
689"\n"
690"Options:\n"
691" -R Recursive copy.\n"
692" -H Follow symbolic links on the commandline. Only valid with -R.\n"
693" -L Follow all symbolic links. Only valid with -R.\n"
694" -P Do not follow symbolic links. Default. Only valid with -R\n"
695" -f Force. Overrides -i and -n.\n"
696" -i Iteractive. Overrides -n and -f.\n"
697" -n Don't overwrite any files. Overrides -i and -f.\n"
698" --ignore-non-existing\n"
699" Don't fail if the specified source file doesn't exist.\n"
700" --changed\n"
701" Only copy if changed (i.e. compare first).\n"
702" --disable-protection\n"
703" Will disable the protection file protection applied with -R.\n"
704" --enable-protection\n"
705" Will enable the protection file protection applied with -R.\n"
706" --enable-full-protection\n"
707" Will enable the protection file protection for all operations.\n"
708" --disable-full-protection\n"
709" Will disable the protection file protection for all operations.\n"
710" --protection-depth\n"
711" Number or path indicating the file protection depth. Default: %d\n"
712"\n"
713"Environment:\n"
714" KMK_CP_DISABLE_PROTECTION\n"
715" Same as --disable-protection. Overrides command line.\n"
716" KMK_CP_ENABLE_PROTECTION\n"
717" Same as --enable-protection. Overrides everyone else.\n"
718" KMK_CP_ENABLE_FULL_PROTECTION\n"
719" Same as --enable-full-protection. Overrides everyone else.\n"
720" KMK_CP_DISABLE_FULL_PROTECTION\n"
721" Same as --disable-full-protection. Overrides command line.\n"
722" KMK_CP_PROTECTION_DEPTH\n"
723" Same as --protection-depth. Overrides command line.\n"
724"\n"
725"The file protection of the top %d layers of the file hierarchy is there\n"
726"to try prevent makefiles from doing bad things to your system. This\n"
727"protection is not bulletproof, but should help prevent you from shooting\n"
728"yourself in the foot.\n"
729 ,
730 g_progname, g_progname, g_progname, g_progname,
731 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
732 return 1;
733}
Note: See TracBrowser for help on using the repository browser.

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