VirtualBox

source: kBuild/trunk/src/kmk/kmkbuiltin/rm.c@ 2546

Last change on this file since 2546 was 2546, checked in by bird, 13 years ago

Applied modified patches for Haiku support from Mike Smith.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.9 KB
Line 
1/*-
2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if 0
31#ifndef lint
32static const char copyright[] =
33"@(#) Copyright (c) 1990, 1993, 1994\n\
34 The Regents of the University of California. All rights reserved.\n";
35#endif /* not lint */
36
37#ifndef lint
38static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94";
39#endif /* not lint */
40#include <sys/cdefs.h>
41/*__FBSDID("$FreeBSD: src/bin/rm/rm.c,v 1.47 2004/04/06 20:06:50 markm Exp $");*/
42#endif
43
44#include "config.h"
45#include <sys/stat.h>
46#if !defined(_MSC_VER) && !defined(__HAIKU__)
47# include <sys/param.h>
48# include <sys/mount.h>
49#endif
50
51#include "err.h"
52#include <errno.h>
53#include <fcntl.h>
54#include <fts.h>
55#include <grp.h>
56#include <pwd.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#ifndef __HAIKU__
61# include <sysexits.h>
62#endif
63#include <unistd.h>
64#include <ctype.h>
65#include "getopt.h"
66#ifdef __HAIKU__
67# include "haikufakes.h"
68#endif
69#ifdef _MSC_VER
70# include "mscfakes.h"
71#endif
72#if defined(__OS2__) || defined(_MSC_VER)
73# include <direct.h>
74# include <limits.h>
75#endif
76#include "kmkbuiltin.h"
77#include "kbuild_protection.h"
78
79#if defined(__EMX__) || defined(_MSC_VER)
80# define IS_SLASH(ch) ( (ch) == '/' || (ch) == '\\' )
81# define HAVE_DOS_PATHS 1
82# define DEFAULT_PROTECTION_DEPTH 1
83#else
84# define IS_SLASH(ch) ( (ch) == '/' )
85# undef HAVE_DOS_PATHS
86# define DEFAULT_PROTECTION_DEPTH 2
87#endif
88
89#ifdef __EMX__
90#undef S_IFWHT
91#undef S_ISWHT
92#endif
93#ifndef S_IFWHT
94#define S_IFWHT 0
95#define S_ISWHT(s) 0
96#define undelete(s) (-1)
97#endif
98
99extern void bsd_strmode(mode_t mode, char *p);
100
101static int dflag, eval, fflag, iflag, Pflag, vflag, Wflag, stdin_ok;
102static uid_t uid;
103
104static char *argv0;
105static KBUILDPROTECTION g_ProtData;
106
107static struct option long_options[] =
108{
109 { "help", no_argument, 0, 261 },
110 { "version", no_argument, 0, 262 },
111 { "disable-protection", no_argument, 0, 263 },
112 { "enable-protection", no_argument, 0, 264 },
113 { "enable-full-protection", no_argument, 0, 265 },
114 { "disable-full-protection", no_argument, 0, 266 },
115 { "protection-depth", required_argument, 0, 267 },
116 { 0, 0, 0, 0 },
117};
118
119
120static int check(char *, char *, struct stat *);
121static void checkdot(char **);
122static int rm_file(char **);
123static int rm_overwrite(char *, struct stat *);
124static int rm_tree(char **);
125static int usage(FILE *);
126
127#if 1
128#define CUR_LINE_H2(x) "[line " #x "]"
129#define CUR_LINE_H1(x) CUR_LINE_H2(x)
130#define CUR_LINE() CUR_LINE_H1(__LINE__)
131#else
132# define CUR_LINE()
133#endif
134
135
136/*
137 * rm --
138 * This rm is different from historic rm's, but is expected to match
139 * POSIX 1003.2 behavior. The most visible difference is that -f
140 * has two specific effects now, ignore non-existent files and force
141 * file removal.
142 */
143int
144kmk_builtin_rm(int argc, char *argv[], char **envp)
145{
146 int ch, rflag;
147
148 /* reinitialize globals */
149 argv0 = argv[0];
150 dflag = eval = fflag = iflag = Pflag = vflag = Wflag = stdin_ok = 0;
151 uid = 0;
152 kBuildProtectionInit(&g_ProtData);
153
154 /* kmk: reset getopt and set program name. */
155 g_progname = argv[0];
156 opterr = 1;
157 optarg = NULL;
158 optopt = 0;
159 optind = 0; /* init */
160
161 Pflag = rflag = 0;
162 while ((ch = getopt_long(argc, argv, "dfiPRvW", long_options, NULL)) != -1)
163 switch(ch) {
164 case 'd':
165 dflag = 1;
166 break;
167 case 'f':
168 fflag = 1;
169 iflag = 0;
170 break;
171 case 'i':
172 fflag = 0;
173 iflag = 1;
174 break;
175 case 'P':
176 Pflag = 1;
177 break;
178 case 'R':
179#if 0
180 case 'r': /* Compatibility. */
181#endif
182 rflag = 1;
183 break;
184 case 'v':
185 vflag = 1;
186 break;
187#ifdef FTS_WHITEOUT
188 case 'W':
189 Wflag = 1;
190 break;
191#endif
192 case 261:
193 kBuildProtectionTerm(&g_ProtData);
194 usage(stdout);
195 return 0;
196 case 262:
197 kBuildProtectionTerm(&g_ProtData);
198 return kbuild_version(argv[0]);
199 case 263:
200 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
201 break;
202 case 264:
203 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE);
204 break;
205 case 265:
206 kBuildProtectionEnable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
207 break;
208 case 266:
209 kBuildProtectionDisable(&g_ProtData, KBUILDPROTECTIONTYPE_FULL);
210 break;
211 case 267:
212 if (kBuildProtectionSetDepth(&g_ProtData, optarg)) {
213 kBuildProtectionTerm(&g_ProtData);
214 return 1;
215 }
216 break;
217 case '?':
218 default:
219 kBuildProtectionTerm(&g_ProtData);
220 return usage(stderr);
221 }
222 argc -= optind;
223 argv += optind;
224
225 if (argc < 1) {
226 kBuildProtectionTerm(&g_ProtData);
227 if (fflag)
228 return (0);
229 return usage(stderr);
230 }
231
232 if (!kBuildProtectionScanEnv(&g_ProtData, envp, "KMK_RM_")) {
233 checkdot(argv);
234 uid = geteuid();
235
236 if (*argv) {
237 stdin_ok = isatty(STDIN_FILENO);
238 if (rflag)
239 eval |= rm_tree(argv);
240 else
241 eval |= rm_file(argv);
242 }
243 } else {
244 eval = 1;
245 }
246
247 kBuildProtectionTerm(&g_ProtData);
248 return eval;
249}
250
251static int
252rm_tree(char **argv)
253{
254 FTS *fts;
255 FTSENT *p;
256 int needstat;
257 int flags;
258 int rval;
259
260 /*
261 * Check up front before anything is deleted. This will not catch
262 * everything, but we'll check the individual items later.
263 */
264 int i;
265 for (i = 0; argv[i]; i++) {
266 if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) {
267 return 1;
268 }
269 }
270
271 /*
272 * Remove a file hierarchy. If forcing removal (-f), or interactive
273 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
274 */
275 needstat = !uid || (!fflag && !iflag && stdin_ok);
276
277 /*
278 * If the -i option is specified, the user can skip on the pre-order
279 * visit. The fts_number field flags skipped directories.
280 */
281#define SKIPPED 1
282
283 flags = FTS_PHYSICAL;
284 if (!needstat)
285 flags |= FTS_NOSTAT;
286#ifdef FTS_WHITEOUT
287 if (Wflag)
288 flags |= FTS_WHITEOUT;
289#endif
290 if (!(fts = fts_open(argv, flags, NULL))) {
291 return err(1, "fts_open");
292 }
293 while ((p = fts_read(fts)) != NULL) {
294 const char *operation = "chflags";
295 switch (p->fts_info) {
296 case FTS_DNR:
297 if (!fflag || p->fts_errno != ENOENT) {
298 fprintf(stderr, "fts: %s: %s: %s" CUR_LINE() "\n",
299 argv0, p->fts_path, strerror(p->fts_errno));
300 eval = 1;
301 }
302 continue;
303 case FTS_ERR:
304 fts_close(fts);
305 return errx(1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno));
306 case FTS_NS:
307 /*
308 * Assume that since fts_read() couldn't stat the
309 * file, it can't be unlinked.
310 */
311 if (!needstat)
312 break;
313 if (!fflag || p->fts_errno != ENOENT) {
314 fprintf(stderr, "fts: %s: %s: %s " CUR_LINE() "\n",
315 argv0, p->fts_path, strerror(p->fts_errno));
316 eval = 1;
317 }
318 continue;
319 case FTS_D:
320 /* Pre-order: give user chance to skip. */
321 if (!fflag && !check(p->fts_path, p->fts_accpath,
322 p->fts_statp)) {
323 (void)fts_set(fts, p, FTS_SKIP);
324 p->fts_number = SKIPPED;
325 }
326#ifdef UF_APPEND
327 else if (!uid &&
328 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
329 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
330 chflags(p->fts_accpath,
331 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
332 goto err;
333#endif
334 continue;
335 case FTS_DP:
336 /* Post-order: see if user skipped. */
337 if (p->fts_number == SKIPPED)
338 continue;
339 break;
340 default:
341 if (!fflag &&
342 !check(p->fts_path, p->fts_accpath, p->fts_statp))
343 continue;
344 }
345
346 /*
347 * Protect against deleting root files and directories.
348 */
349 if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) {
350 fts_close(fts);
351 return 1;
352 }
353
354 rval = 0;
355#ifdef UF_APPEND
356 if (!uid &&
357 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
358 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
359 rval = chflags(p->fts_accpath,
360 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
361#endif
362 if (rval == 0) {
363 /*
364 * If we can't read or search the directory, may still be
365 * able to remove it. Don't print out the un{read,search}able
366 * message unless the remove fails.
367 */
368 switch (p->fts_info) {
369 case FTS_DP:
370 case FTS_DNR:
371 rval = rmdir(p->fts_accpath);
372 if (rval == 0 || (fflag && errno == ENOENT)) {
373 if (rval == 0 && vflag)
374 (void)printf("%s\n",
375 p->fts_path);
376 continue;
377 }
378 operation = "mkdir";
379 break;
380
381#ifdef FTS_W
382 case FTS_W:
383 rval = undelete(p->fts_accpath);
384 if (rval == 0 && (fflag && errno == ENOENT)) {
385 if (vflag)
386 (void)printf("%s\n",
387 p->fts_path);
388 continue;
389 }
390 operation = "undelete";
391 break;
392#endif
393
394 case FTS_NS:
395 /*
396 * Assume that since fts_read() couldn't stat
397 * the file, it can't be unlinked.
398 */
399 if (fflag)
400 continue;
401 /* FALLTHROUGH */
402 default:
403 if (Pflag)
404 if (!rm_overwrite(p->fts_accpath, NULL))
405 continue;
406 rval = unlink(p->fts_accpath);
407#ifdef _MSC_VER
408 if (rval != 0) {
409 chmod(p->fts_accpath, 0777);
410 rval = unlink(p->fts_accpath);
411 }
412#endif
413
414 if (rval == 0 || (fflag && errno == ENOENT)) {
415 if (rval == 0 && vflag)
416 (void)printf("%s\n",
417 p->fts_path);
418 continue;
419 }
420 operation = "unlink";
421 break;
422 }
423 }
424#ifdef UF_APPEND
425err:
426#endif
427 fprintf(stderr, "%s: %s: %s: %s " CUR_LINE() "\n", operation, argv0, p->fts_path, strerror(errno));
428 eval = 1;
429 }
430 if (errno) {
431 fprintf(stderr, "%s: fts_read: %s " CUR_LINE() "\n", argv0, strerror(errno));
432 eval = 1;
433 }
434 fts_close(fts);
435 return eval;
436}
437
438static int
439rm_file(char **argv)
440{
441 struct stat sb;
442 int rval;
443 char *f;
444
445 /*
446 * Check up front before anything is deleted.
447 */
448 int i;
449 for (i = 0; argv[i]; i++) {
450 if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i]))
451 return 1;
452 }
453
454 /*
455 * Remove a file. POSIX 1003.2 states that, by default, attempting
456 * to remove a directory is an error, so must always stat the file.
457 */
458 while ((f = *argv++) != NULL) {
459 const char *operation = "?";
460 /* Assume if can't stat the file, can't unlink it. */
461 if (lstat(f, &sb)) {
462#ifdef FTS_WHITEOUT
463 if (Wflag) {
464 sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
465 } else {
466#else
467 {
468#endif
469 if (!fflag || errno != ENOENT) {
470 fprintf(stderr, "lstat: %s: %s: %s " CUR_LINE() "\n", argv0, f, strerror(errno));
471 eval = 1;
472 }
473 continue;
474 }
475#ifdef FTS_WHITEOUT
476 } else if (Wflag) {
477 fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(EEXIST));
478 eval = 1;
479 continue;
480#endif
481 }
482
483 if (S_ISDIR(sb.st_mode) && !dflag) {
484 fprintf(stderr, "%s: %s: is a directory\n", argv0, f);
485 eval = 1;
486 continue;
487 }
488 if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
489 continue;
490 rval = 0;
491#ifdef UF_APPEND
492 if (!uid &&
493 (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
494 !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
495 rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
496#endif
497 if (rval == 0) {
498 if (S_ISWHT(sb.st_mode)) {
499 rval = undelete(f);
500 operation = "undelete";
501 } else if (S_ISDIR(sb.st_mode)) {
502 rval = rmdir(f);
503 operation = "rmdir";
504 } else {
505 if (Pflag)
506 if (!rm_overwrite(f, &sb))
507 continue;
508 rval = unlink(f);
509#ifdef _MSC_VER
510 if (rval != 0) {
511 chmod(f, 0777);
512 rval = unlink(f);
513 }
514#endif
515 operation = "unlink";
516 }
517 }
518 if (rval && (!fflag || errno != ENOENT)) {
519 fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, f, strerror(errno));
520 eval = 1;
521 }
522 if (vflag && rval == 0)
523 (void)printf("%s\n", f);
524 }
525 return eval;
526}
527
528/*
529 * rm_overwrite --
530 * Overwrite the file 3 times with varying bit patterns.
531 *
532 * XXX
533 * This is a cheap way to *really* delete files. Note that only regular
534 * files are deleted, directories (and therefore names) will remain.
535 * Also, this assumes a fixed-block file system (like FFS, or a V7 or a
536 * System V file system). In a logging file system, you'll have to have
537 * kernel support.
538 */
539static int
540rm_overwrite(char *file, struct stat *sbp)
541{
542 struct stat sb;
543#ifdef HAVE_FSTATFS
544 struct statfs fsb;
545#endif
546 off_t len;
547 int bsize, fd, wlen;
548 char *buf = NULL;
549 const char *operation = "lstat";
550
551 fd = -1;
552 if (sbp == NULL) {
553 if (lstat(file, &sb))
554 goto err;
555 sbp = &sb;
556 }
557 if (!S_ISREG(sbp->st_mode))
558 return (1);
559 operation = "open";
560 if ((fd = open(file, O_WRONLY, 0)) == -1)
561 goto err;
562#ifdef HAVE_FSTATFS
563 if (fstatfs(fd, &fsb) == -1)
564 goto err;
565 bsize = MAX(fsb.f_iosize, 1024);
566#elif defined(HAVE_ST_BLKSIZE)
567 bsize = MAX(sb.st_blksize, 1024);
568#else
569 bsize = 1024;
570#endif
571 if ((buf = malloc(bsize)) == NULL)
572 exit(err(1, "%s: malloc", file));
573
574#define PASS(byte) { \
575 operation = "write"; \
576 memset(buf, byte, bsize); \
577 for (len = sbp->st_size; len > 0; len -= wlen) { \
578 wlen = len < bsize ? len : bsize; \
579 if (write(fd, buf, wlen) != wlen) \
580 goto err; \
581 } \
582}
583 PASS(0xff);
584 operation = "fsync/lseek";
585 if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
586 goto err;
587 PASS(0x00);
588 operation = "fsync/lseek";
589 if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
590 goto err;
591 PASS(0xff);
592 if (!fsync(fd) && !close(fd)) {
593 free(buf);
594 return (1);
595 }
596 operation = "fsync/close";
597
598err: eval = 1;
599 if (buf)
600 free(buf);
601 if (fd != -1)
602 close(fd);
603 fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, file, strerror(errno));
604 return (0);
605}
606
607
608static int
609check(char *path, char *name, struct stat *sp)
610{
611 int ch, first;
612 char modep[15], *flagsp;
613
614 /* Check -i first. */
615 if (iflag)
616 (void)fprintf(stderr, "remove %s? ", path);
617 else {
618 /*
619 * If it's not a symbolic link and it's unwritable and we're
620 * talking to a terminal, ask. Symbolic links are excluded
621 * because their permissions are meaningless. Check stdin_ok
622 * first because we may not have stat'ed the file.
623 * Also skip this check if the -P option was specified because
624 * we will not be able to overwrite file contents and will
625 * barf later.
626 */
627 if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag ||
628 (!access(name, W_OK) &&
629#ifdef SF_APPEND
630 !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
631 (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid))
632#else
633 1)
634#endif
635 )
636 return (1);
637 bsd_strmode(sp->st_mode, modep);
638#ifdef SF_APPEND
639 if ((flagsp = fflagstostr(sp->st_flags)) == NULL)
640 exit(err(1, "fflagstostr"));
641 (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
642 modep + 1, modep[9] == ' ' ? "" : " ",
643 user_from_uid(sp->st_uid, 0),
644 group_from_gid(sp->st_gid, 0),
645 *flagsp ? flagsp : "", *flagsp ? " " : "",
646 path);
647 free(flagsp);
648#else
649 (void)flagsp;
650 (void)fprintf(stderr, "override %s%s %d/%d for %s? ",
651 modep + 1, modep[9] == ' ' ? "" : " ",
652 sp->st_uid, sp->st_gid, path);
653#endif
654 }
655 (void)fflush(stderr);
656
657 first = ch = getchar();
658 while (ch != '\n' && ch != EOF)
659 ch = getchar();
660 return (first == 'y' || first == 'Y');
661}
662
663#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
664static void
665checkdot(char **argv)
666{
667 char *p, **save, **t;
668 int complained;
669
670 complained = 0;
671 for (t = argv; *t;) {
672#ifdef HAVE_DOS_PATHS
673 const char *tmp = p = *t;
674 while (*tmp) {
675 switch (*tmp) {
676 case '/':
677 case '\\':
678 case ':':
679 p = (char *)tmp + 1;
680 break;
681 }
682 tmp++;
683 }
684#else
685 if ((p = strrchr(*t, '/')) != NULL)
686 ++p;
687 else
688 p = *t;
689#endif
690 if (ISDOT(p)) {
691 if (!complained++)
692 fprintf(stderr, "%s: \".\" and \"..\" may not be removed\n", argv0);
693 eval = 1;
694 for (save = t; (t[0] = t[1]) != NULL; ++t)
695 continue;
696 t = save;
697 } else
698 ++t;
699 }
700}
701
702static int
703usage(FILE *pf)
704{
705 fprintf(pf,
706 "usage: %s [options] file ...\n"
707 " or: %s --help\n"
708 " or: %s --version\n"
709 "\n"
710 "Options:\n"
711 " -f\n"
712 " Attempt to remove files without prompting, regardless of the file\n"
713 " permission. Ignore non-existing files. Overrides previous -i's.\n"
714 " -i\n"
715 " Prompt for each file. Always.\n"
716 " -d\n"
717 " Attempt to remove directories as well as other kinds of files.\n"
718 " -P\n"
719 " Overwrite regular files before deleting; three passes: ff,0,ff\n"
720 " -R\n"
721 " Attempt to remove the file hierachy rooted in each file argument.\n"
722 " This option implies -d and file protection.\n"
723 " -v\n"
724 " Be verbose, show files as they are removed.\n"
725 " -W\n"
726 " Undelete without files.\n"
727 " --disable-protection\n"
728 " Will disable the protection file protection applied with -R.\n"
729 " --enable-protection\n"
730 " Will enable the protection file protection applied with -R.\n"
731 " --enable-full-protection\n"
732 " Will enable the protection file protection for all operations.\n"
733 " --disable-full-protection\n"
734 " Will disable the protection file protection for all operations.\n"
735 " --protection-depth\n"
736 " Number or path indicating the file protection depth. Default: %d\n"
737 "\n"
738 "Environment:\n"
739 " KMK_RM_DISABLE_PROTECTION\n"
740 " Same as --disable-protection. Overrides command line.\n"
741 " KMK_RM_ENABLE_PROTECTION\n"
742 " Same as --enable-protection. Overrides everyone else.\n"
743 " KMK_RM_ENABLE_FULL_PROTECTION\n"
744 " Same as --enable-full-protection. Overrides everyone else.\n"
745 " KMK_RM_DISABLE_FULL_PROTECTION\n"
746 " Same as --disable-full-protection. Overrides command line.\n"
747 " KMK_RM_PROTECTION_DEPTH\n"
748 " Same as --protection-depth. Overrides command line.\n"
749 "\n"
750 "The file protection of the top %d layers of the file hierarchy is there\n"
751 "to try prevent makefiles from doing bad things to your system. This\n"
752 "protection is not bulletproof, but should help prevent you from shooting\n"
753 "yourself in the foot.\n"
754 ,
755 g_progname, g_progname, g_progname,
756 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
757 return EX_USAGE;
758}
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