VirtualBox

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

最後變更 在這個檔案從2464是 2464,由 bird 提交於 14 年 前

rm.c: debug for solaris

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

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