VirtualBox

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

Last change on this file since 2702 was 2702, checked in by bird, 11 years ago

kmk/WindowsNT: Avoiding unnecessary stat() calls. Reimplemented stat(), lstat(), fstat(), opendir(), readdir(), and closedir() using native NT APIs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.0 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#ifndef _MSC_VER
502 } else if (S_ISDIR(sb.st_mode)) {
503#else
504 } else if (S_ISDIR(sb.st_mode) || sb.st_dirsymlink) {
505#endif
506 rval = rmdir(f);
507 operation = "rmdir";
508 } else {
509 if (Pflag)
510 if (!rm_overwrite(f, &sb))
511 continue;
512 rval = unlink(f);
513#ifdef _MSC_VER
514 if (rval != 0) {
515 chmod(f, 0777);
516 rval = unlink(f);
517 }
518#endif
519 operation = "unlink";
520 }
521 }
522 if (rval && (!fflag || errno != ENOENT)) {
523 fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, f, strerror(errno));
524 eval = 1;
525 }
526 if (vflag && rval == 0)
527 (void)printf("%s\n", f);
528 }
529 return eval;
530}
531
532/*
533 * rm_overwrite --
534 * Overwrite the file 3 times with varying bit patterns.
535 *
536 * XXX
537 * This is a cheap way to *really* delete files. Note that only regular
538 * files are deleted, directories (and therefore names) will remain.
539 * Also, this assumes a fixed-block file system (like FFS, or a V7 or a
540 * System V file system). In a logging file system, you'll have to have
541 * kernel support.
542 */
543static int
544rm_overwrite(char *file, struct stat *sbp)
545{
546 struct stat sb;
547#ifdef HAVE_FSTATFS
548 struct statfs fsb;
549#endif
550 off_t len;
551 int bsize, fd, wlen;
552 char *buf = NULL;
553 const char *operation = "lstat";
554
555 fd = -1;
556 if (sbp == NULL) {
557 if (lstat(file, &sb))
558 goto err;
559 sbp = &sb;
560 }
561 if (!S_ISREG(sbp->st_mode))
562 return (1);
563 operation = "open";
564 if ((fd = open(file, O_WRONLY, 0)) == -1)
565 goto err;
566#ifdef HAVE_FSTATFS
567 if (fstatfs(fd, &fsb) == -1)
568 goto err;
569 bsize = MAX(fsb.f_iosize, 1024);
570#elif defined(HAVE_ST_BLKSIZE)
571 bsize = MAX(sb.st_blksize, 1024);
572#else
573 bsize = 1024;
574#endif
575 if ((buf = malloc(bsize)) == NULL)
576 exit(err(1, "%s: malloc", file));
577
578#define PASS(byte) { \
579 operation = "write"; \
580 memset(buf, byte, bsize); \
581 for (len = sbp->st_size; len > 0; len -= wlen) { \
582 wlen = len < bsize ? len : bsize; \
583 if (write(fd, buf, wlen) != wlen) \
584 goto err; \
585 } \
586}
587 PASS(0xff);
588 operation = "fsync/lseek";
589 if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
590 goto err;
591 PASS(0x00);
592 operation = "fsync/lseek";
593 if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
594 goto err;
595 PASS(0xff);
596 if (!fsync(fd) && !close(fd)) {
597 free(buf);
598 return (1);
599 }
600 operation = "fsync/close";
601
602err: eval = 1;
603 if (buf)
604 free(buf);
605 if (fd != -1)
606 close(fd);
607 fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, file, strerror(errno));
608 return (0);
609}
610
611
612static int
613check(char *path, char *name, struct stat *sp)
614{
615 int ch, first;
616 char modep[15], *flagsp;
617
618 /* Check -i first. */
619 if (iflag)
620 (void)fprintf(stderr, "remove %s? ", path);
621 else {
622 /*
623 * If it's not a symbolic link and it's unwritable and we're
624 * talking to a terminal, ask. Symbolic links are excluded
625 * because their permissions are meaningless. Check stdin_ok
626 * first because we may not have stat'ed the file.
627 * Also skip this check if the -P option was specified because
628 * we will not be able to overwrite file contents and will
629 * barf later.
630 */
631 if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag ||
632 (!access(name, W_OK) &&
633#ifdef SF_APPEND
634 !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
635 (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid))
636#else
637 1)
638#endif
639 )
640 return (1);
641 bsd_strmode(sp->st_mode, modep);
642#ifdef SF_APPEND
643 if ((flagsp = fflagstostr(sp->st_flags)) == NULL)
644 exit(err(1, "fflagstostr"));
645 (void)fprintf(stderr, "override %s%s%s/%s %s%sfor %s? ",
646 modep + 1, modep[9] == ' ' ? "" : " ",
647 user_from_uid(sp->st_uid, 0),
648 group_from_gid(sp->st_gid, 0),
649 *flagsp ? flagsp : "", *flagsp ? " " : "",
650 path);
651 free(flagsp);
652#else
653 (void)flagsp;
654 (void)fprintf(stderr, "override %s%s %d/%d for %s? ",
655 modep + 1, modep[9] == ' ' ? "" : " ",
656 sp->st_uid, sp->st_gid, path);
657#endif
658 }
659 (void)fflush(stderr);
660
661 first = ch = getchar();
662 while (ch != '\n' && ch != EOF)
663 ch = getchar();
664 return (first == 'y' || first == 'Y');
665}
666
667#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
668static void
669checkdot(char **argv)
670{
671 char *p, **save, **t;
672 int complained;
673
674 complained = 0;
675 for (t = argv; *t;) {
676#ifdef HAVE_DOS_PATHS
677 const char *tmp = p = *t;
678 while (*tmp) {
679 switch (*tmp) {
680 case '/':
681 case '\\':
682 case ':':
683 p = (char *)tmp + 1;
684 break;
685 }
686 tmp++;
687 }
688#else
689 if ((p = strrchr(*t, '/')) != NULL)
690 ++p;
691 else
692 p = *t;
693#endif
694 if (ISDOT(p)) {
695 if (!complained++)
696 fprintf(stderr, "%s: \".\" and \"..\" may not be removed\n", argv0);
697 eval = 1;
698 for (save = t; (t[0] = t[1]) != NULL; ++t)
699 continue;
700 t = save;
701 } else
702 ++t;
703 }
704}
705
706static int
707usage(FILE *pf)
708{
709 fprintf(pf,
710 "usage: %s [options] file ...\n"
711 " or: %s --help\n"
712 " or: %s --version\n"
713 "\n"
714 "Options:\n"
715 " -f\n"
716 " Attempt to remove files without prompting, regardless of the file\n"
717 " permission. Ignore non-existing files. Overrides previous -i's.\n"
718 " -i\n"
719 " Prompt for each file. Always.\n"
720 " -d\n"
721 " Attempt to remove directories as well as other kinds of files.\n"
722 " -P\n"
723 " Overwrite regular files before deleting; three passes: ff,0,ff\n"
724 " -R\n"
725 " Attempt to remove the file hierachy rooted in each file argument.\n"
726 " This option implies -d and file protection.\n"
727 " -v\n"
728 " Be verbose, show files as they are removed.\n"
729 " -W\n"
730 " Undelete without files.\n"
731 " --disable-protection\n"
732 " Will disable the protection file protection applied with -R.\n"
733 " --enable-protection\n"
734 " Will enable the protection file protection applied with -R.\n"
735 " --enable-full-protection\n"
736 " Will enable the protection file protection for all operations.\n"
737 " --disable-full-protection\n"
738 " Will disable the protection file protection for all operations.\n"
739 " --protection-depth\n"
740 " Number or path indicating the file protection depth. Default: %d\n"
741 "\n"
742 "Environment:\n"
743 " KMK_RM_DISABLE_PROTECTION\n"
744 " Same as --disable-protection. Overrides command line.\n"
745 " KMK_RM_ENABLE_PROTECTION\n"
746 " Same as --enable-protection. Overrides everyone else.\n"
747 " KMK_RM_ENABLE_FULL_PROTECTION\n"
748 " Same as --enable-full-protection. Overrides everyone else.\n"
749 " KMK_RM_DISABLE_FULL_PROTECTION\n"
750 " Same as --disable-full-protection. Overrides command line.\n"
751 " KMK_RM_PROTECTION_DEPTH\n"
752 " Same as --protection-depth. Overrides command line.\n"
753 "\n"
754 "The file protection of the top %d layers of the file hierarchy is there\n"
755 "to try prevent makefiles from doing bad things to your system. This\n"
756 "protection is not bulletproof, but should help prevent you from shooting\n"
757 "yourself in the foot.\n"
758 ,
759 g_progname, g_progname, g_progname,
760 kBuildProtectionDefaultDepth(), kBuildProtectionDefaultDepth());
761 return EX_USAGE;
762}
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