Esempio n. 1
0
File: rm.c Progetto: aalm/obsd-src
void
rm_file(char **argv)
{
	struct stat sb;
	int rval;
	char *f;

	/*
	 * Remove a file.  POSIX 1003.2 states that, by default, attempting
	 * to remove a directory is an error, so must always stat the file.
	 */
	while ((f = *argv++) != NULL) {
		/* Assume if can't stat the file, can't unlink it. */
		if (lstat(f, &sb)) {
			if (!fflag || errno != ENOENT) {
				warn("%s", f);
				eval = 1;
			}
			continue;
		}

		if (S_ISDIR(sb.st_mode) && !dflag) {
			warnx("%s: is a directory", f);
			eval = 1;
			continue;
		}
		if (!fflag && !check(f, f, &sb))
			continue;
		else if (S_ISDIR(sb.st_mode))
			rval = rmdir(f);
		else {
			if (Pflag)
				rm_overwrite(f, &sb);
			rval = unlink(f);
		}
		if (rval && (!fflag || errno != ENOENT)) {
			warn("%s", f);
			eval = 1;
		}
	}
}
Esempio n. 2
0
static void
rm_file(char **argv)
{
	struct stat sb;
	int rval;
	char *f;

	/*
	 * Remove a file.  POSIX 1003.2 states that, by default, attempting
	 * to remove a directory is an error, so must always stat the file.
	 */
	while ((f = *argv++) != NULL) {
		/* Assume if can't stat the file, can't unlink it. */
		if (lstat(f, &sb)) {
#ifndef __ANDROID__
			if (Wflag) {
				sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
			} else {
#endif
				if (!fflag || !NONEXISTENT(errno)) {
					warn("%s", f);
					eval = 1;
				}
				continue;
#ifndef __ANDROID__
			}
		} else if (Wflag) {
			warnx("%s: %s", f, strerror(EEXIST));
			eval = 1;
			continue;
#endif
		}

		if (S_ISDIR(sb.st_mode) && !dflag) {
			warnx("%s: is a directory", f);
			eval = 1;
			continue;
		}
		if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
			continue;
#ifndef __ANDROID__
		if (S_ISWHT(sb.st_mode))
			rval = undelete(f);
		else if (S_ISDIR(sb.st_mode))
#else
		if (S_ISDIR(sb.st_mode))
#endif
			rval = rmdir(f);
		else {
			if (Pflag) {
				if (rm_overwrite(f, &sb))
					continue;
			}
			rval = unlink(f);
		}
		if (rval && (!fflag || !NONEXISTENT(errno))) {
			warn("%s", f);
			eval = 1;
		}
		if (vflag && rval == 0)
			(void)printf("%s\n", f);
	}
}
Esempio n. 3
0
static void
rm_tree(char **argv)
{
	FTS *fts;
	FTSENT *p;
	int flags, needstat, rval;
			
	/*
	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
	 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
	 */
	needstat = !fflag && !iflag && stdin_ok;

	/*
	 * If the -i option is specified, the user can skip on the pre-order
	 * visit.  The fts_number field flags skipped directories.
	 */
#define	SKIPPED	1

	flags = FTS_PHYSICAL;
	if (!needstat)
		flags |= FTS_NOSTAT;
#ifndef __ANDROID__
	if (Wflag)
		flags |= FTS_WHITEOUT;
#endif
	if (xflag)
		flags |= FTS_XDEV;
	if ((fts = fts_open(argv, flags, NULL)) == NULL)
		err(1, "fts_open failed");
	while ((p = fts_read(fts)) != NULL) {
	
		switch (p->fts_info) {
		case FTS_DNR:
			if (!fflag || p->fts_errno != ENOENT) {
				warnx("%s: %s", p->fts_path,
						strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_ERR:
			errx(EXIT_FAILURE, "%s: %s", p->fts_path,
					strerror(p->fts_errno));
			/* NOTREACHED */
		case FTS_NS:
			/*
			 * FTS_NS: assume that if can't stat the file, it
			 * can't be unlinked.
			 */
			if (fflag && NONEXISTENT(p->fts_errno))
				continue;
			if (needstat) {
				warnx("%s: %s", p->fts_path,
						strerror(p->fts_errno));
				eval = 1;
				continue;
			}
			break;
		case FTS_D:
			/* Pre-order: give user chance to skip. */
			if (!fflag && !check(p->fts_path, p->fts_accpath,
			    p->fts_statp)) {
				(void)fts_set(fts, p, FTS_SKIP);
				p->fts_number = SKIPPED;
			}
			continue;
		case FTS_DP:
			/* Post-order: see if user skipped. */
			if (p->fts_number == SKIPPED)
				continue;
			break;
		default:
			if (!fflag &&
			    !check(p->fts_path, p->fts_accpath, p->fts_statp))
				continue;
		}

		rval = 0;
		/*
		 * If we can't read or search the directory, may still be
		 * able to remove it.  Don't print out the un{read,search}able
		 * message unless the remove fails.
		 */
		switch (p->fts_info) {
		case FTS_DP:
		case FTS_DNR:
			rval = rmdir(p->fts_accpath);
			if (rval != 0 && fflag && errno == ENOENT)
				continue;
			break;

#ifndef __ANDROID__
		case FTS_W:
			rval = undelete(p->fts_accpath);
			if (rval != 0 && fflag && errno == ENOENT)
				continue;
			break;
#endif

		default:
			if (Pflag) {
				if (rm_overwrite(p->fts_accpath, NULL))
					continue;
			}
			rval = unlink(p->fts_accpath);
			if (rval != 0 && fflag && NONEXISTENT(errno))
				continue;
			break;
		}
		if (rval != 0) {
			warn("%s", p->fts_path);
			eval = 1;
		} else if (vflag || pinfo) {
			pinfo = 0;
			(void)printf("%s\n", p->fts_path);
		}
	}
	if (errno)
		err(1, "fts_read");
	fts_close(fts);
}
Esempio n. 4
0
static void
rm_file(char **argv)
{
    struct stat sb;
    int rval;
    char *f;

    /*
     * Remove a file.  POSIX 1003.2 states that, by default, attempting
     * to remove a directory is an error, so must always stat the file.
     */
    while ((f = *argv++) != NULL) {
        /* Assume if can't stat the file, can't unlink it. */
        if (lstat(f, &sb)) {
            if (Wflag) {
                sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
            } else {
                if (!fflag || errno != ENOENT) {
                    warn("%s", f);
                    eval = 1;
                }
                continue;
            }
        } else if (Wflag) {
            warnx("%s: %s", f, strerror(EEXIST));
            eval = 1;
            continue;
        }

        if (S_ISDIR(sb.st_mode) && !dflag) {
            warnx("%s: is a directory", f);
            eval = 1;
            continue;
        }
        if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
            continue;
        rval = 0;
        if (!uid && !S_ISWHT(sb.st_mode) &&
                (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
            rval = lchflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
        if (rval == 0) {
            if (S_ISWHT(sb.st_mode))
                rval = undelete(f);
            else if (S_ISDIR(sb.st_mode))
                rval = rmdir(f);
            else {
                if (Pflag)
                    if (!rm_overwrite(f, &sb))
                        continue;
                rval = unlink(f);
            }
        }
        if (rval && (!fflag || errno != ENOENT)) {
            warn("%s", f);
            eval = 1;
        }
        if (vflag && rval == 0)
            (void)printf("%s\n", f);
        if (info && rval == 0) {
            info = 0;
            (void)printf("%s\n", f);
        }
    }
}
Esempio n. 5
0
static void
rm_tree(char **argv)
{
    FTS *fts;
    FTSENT *p;
    int needstat;
    int flags;
    int rval;

    /*
     * Remove a file hierarchy.  If forcing removal (-f), or interactive
     * (-i) or can't ask anyway (stdin_ok), don't stat the file.
     */
    needstat = !uid || (!fflag && !iflag && stdin_ok);

    /*
     * If the -i option is specified, the user can skip on the pre-order
     * visit.  The fts_number field flags skipped directories.
     */
#define	SKIPPED	1

    flags = FTS_PHYSICAL;
    if (!needstat)
        flags |= FTS_NOSTAT;
    if (Wflag)
        flags |= FTS_WHITEOUT;
    if (xflag)
        flags |= FTS_XDEV;
    if (!(fts = fts_open(argv, flags, NULL))) {
        if (fflag && errno == ENOENT)
            return;
        err(1, "fts_open");
    }
    while ((p = fts_read(fts)) != NULL) {
        switch (p->fts_info) {
        case FTS_DNR:
            if (!fflag || p->fts_errno != ENOENT) {
                warnx("%s: %s",
                      p->fts_path, strerror(p->fts_errno));
                eval = 1;
            }
            continue;
        case FTS_ERR:
            errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
        case FTS_NS:
            /*
             * Assume that since fts_read() couldn't stat the
             * file, it can't be unlinked.
             */
            if (!needstat)
                break;
            if (!fflag || p->fts_errno != ENOENT) {
                warnx("%s: %s",
                      p->fts_path, strerror(p->fts_errno));
                eval = 1;
            }
            continue;
        case FTS_D:
            /* Pre-order: give user chance to skip. */
            if (!fflag && !check(p->fts_path, p->fts_accpath,
                                 p->fts_statp)) {
                (void)fts_set(fts, p, FTS_SKIP);
                p->fts_number = SKIPPED;
            }
            else if (!uid &&
                     (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                     !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
                     lchflags(p->fts_accpath,
                              p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
                goto err;
            continue;
        case FTS_DP:
            /* Post-order: see if user skipped. */
            if (p->fts_number == SKIPPED)
                continue;
            break;
        default:
            if (!fflag &&
                    !check(p->fts_path, p->fts_accpath, p->fts_statp))
                continue;
        }

        rval = 0;
        if (!uid &&
                (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
                !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
            rval = lchflags(p->fts_accpath,
                            p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
        if (rval == 0) {
            /*
             * If we can't read or search the directory, may still be
             * able to remove it.  Don't print out the un{read,search}able
             * message unless the remove fails.
             */
            switch (p->fts_info) {
            case FTS_DP:
            case FTS_DNR:
                rval = rmdir(p->fts_accpath);
                if (rval == 0 || (fflag && errno == ENOENT)) {
                    if (rval == 0 && vflag)
                        (void)printf("%s\n",
                                     p->fts_path);
                    if (rval == 0 && info) {
                        info = 0;
                        (void)printf("%s\n",
                                     p->fts_path);
                    }
                    continue;
                }
                break;

            case FTS_W:
                rval = undelete(p->fts_accpath);
                if (rval == 0 && (fflag && errno == ENOENT)) {
                    if (vflag)
                        (void)printf("%s\n",
                                     p->fts_path);
                    if (info) {
                        info = 0;
                        (void)printf("%s\n",
                                     p->fts_path);
                    }
                    continue;
                }
                break;

            case FTS_NS:
                /*
                 * Assume that since fts_read() couldn't stat
                 * the file, it can't be unlinked.
                 */
                if (fflag)
                    continue;
            /* FALLTHROUGH */

            case FTS_F:
            case FTS_NSOK:
                if (Pflag)
                    if (!rm_overwrite(p->fts_accpath, p->fts_info ==
                                      FTS_NSOK ? NULL : p->fts_statp))
                        continue;
            /* FALLTHROUGH */

            default:
                rval = unlink(p->fts_accpath);
                if (rval == 0 || (fflag && errno == ENOENT)) {
                    if (rval == 0 && vflag)
                        (void)printf("%s\n",
                                     p->fts_path);
                    if (rval == 0 && info) {
                        info = 0;
                        (void)printf("%s\n",
                                     p->fts_path);
                    }
                    continue;
                }
            }
        }
err:
        warn("%s", p->fts_path);
        eval = 1;
    }
    if (!fflag && errno)
        err(1, "fts_read");
    fts_close(fts);
}
Esempio n. 6
0
File: rm.c Progetto: Bluerise/bitrig
void
rm_tree(char **argv)
{
	FTS *fts;
	FTSENT *p;
	int needstat;
	int flags;

	/*
	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
	 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
	 */
	needstat = !fflag && !iflag && stdin_ok;

	/*
	 * If the -i option is specified, the user can skip on the pre-order
	 * visit.  The fts_number field flags skipped directories.
	 */
#define	SKIPPED	1

	flags = FTS_PHYSICAL;
	if (!needstat)
		flags |= FTS_NOSTAT;
	if (xflag)
		flags |= FTS_XDEV;
	if (!(fts = fts_open(argv, flags, NULL)))
		err(1, NULL);
	while ((p = fts_read(fts)) != NULL) {
		switch (p->fts_info) {
		case FTS_DNR:
			if (!fflag || p->fts_errno != ENOENT) {
				warnx("%s: %s",
				    p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_ERR:
			errc(1, p->fts_errno, "%s", p->fts_path);
		case FTS_NS:
			/*
			 * FTS_NS: assume that if can't stat the file, it
			 * can't be unlinked.
			 */
			if (!needstat)
				break;
			if (!fflag || p->fts_errno != ENOENT) {
				warnx("%s: %s",
				    p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_D:
			/* Pre-order: give user chance to skip. */
			if (!fflag && !check(p->fts_path, p->fts_accpath,
			    p->fts_statp)) {
				(void)fts_set(fts, p, FTS_SKIP);
				p->fts_number = SKIPPED;
			}
			continue;
		case FTS_DP:
			/* Post-order: see if user skipped. */
			if (p->fts_number == SKIPPED)
				continue;
			break;
		default:
			if (!fflag &&
			    !check(p->fts_path, p->fts_accpath, p->fts_statp))
				continue;
		}

		/*
		 * If we can't read or search the directory, may still be
		 * able to remove it.  Don't print out the un{read,search}able
		 * message unless the remove fails.
		 */
		switch (p->fts_info) {
		case FTS_DP:
		case FTS_DNR:
			if (!rmdir(p->fts_accpath) ||
			    (fflag && errno == ENOENT))
				continue;
			break;

		case FTS_F:
		case FTS_NSOK:
			if (Pflag)
				rm_overwrite(p->fts_accpath, p->fts_info ==
				    FTS_NSOK ? NULL : p->fts_statp);
			/* FALLTHROUGH */
		default:
			if (!unlink(p->fts_accpath) ||
			    (fflag && errno == ENOENT))
				continue;
		}
		warn("%s", p->fts_path);
		eval = 1;
	}
	if (errno)
		err(1, "fts_read");
	fts_close(fts);
}
Esempio n. 7
0
rm_tree(char **argv)
#endif
{
	FTS *fts;
	FTSENT *p;
	int needstat;
	int rval;

	/*
	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
	 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
	 */
	needstat = !uid || !fflag && !iflag && stdin_ok;

	/*
	 * If the -i option is specified, the user can skip on the pre-order
	 * visit.  The fts_number field flags skipped directories.
	 */
#define	SKIPPED	1

	if (!(fts = fts_open(argv,
	    needstat ? FTS_PHYSICAL|FTS_NOCHDIR :
		FTS_PHYSICAL|FTS_NOSTAT|FTS_NOCHDIR, (int (*)())NULL)))
		err(1, NULL);
	while ((p = fts_read(fts)) != NULL) {
		switch (p->fts_info) {
		case FTS_DNR:
			if (!fflag || p->fts_errno != ENOENT) {
				warnx("%s: %s",
				    p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_ERR:
			errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
		case FTS_NS:
			/*
			 * FTS_NS: assume that if can't stat the file, it
			 * can't be unlinked.
			 */
			if (!needstat)
				break;
			if (!fflag || p->fts_errno != ENOENT) {
				warnx("%s: %s",
				    p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_D:
			/* Pre-order: give user chance to skip. */
			if (iflag && !check(p->fts_path, p->fts_accpath,
			    p->fts_statp)) {
				(void)fts_set(fts, p, FTS_SKIP);
				p->fts_number = SKIPPED;
			}
#ifndef __GNO__
			else if (!uid &&
				 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
				 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
				 chflags(p->fts_accpath,
					 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
				goto err;
#endif
			continue;
		case FTS_DP:
			/* Post-order: see if user skipped. */
			if (p->fts_number == SKIPPED)
				continue;
			break;
		}
		if (!fflag &&
		    !check(p->fts_path, p->fts_accpath, p->fts_statp))
			continue;

		rval = 0;
#ifndef __GNO__
		if (!uid &&
		    (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
		    !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
			rval = chflags(p->fts_accpath,
				       p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
#endif
		if (!rval) {
			/*
			 * If we can't read or search the directory, may still be
			 * able to remove it.  Don't print out the un{read,search}able
			 * message unless the remove fails.
			 */
			if (p->fts_info == FTS_DP || p->fts_info == FTS_DNR) {
				if (!rmdir(p->fts_accpath))
					continue;
				if (errno == ENOENT) {
					if (fflag)
						continue;
				} else if (p->fts_info != FTS_DP)
					warnx("%s: unable to read", p->fts_path);
			} else {
				if (Pflag)
					rm_overwrite(p->fts_accpath, NULL);
				if (!unlink(p->fts_accpath) || (fflag && errno == ENOENT))
					continue;
			}
		}
err:
		warn("%s", p->fts_path);
		eval = 1;
	}
	if (errno)
		err(1, "fts_read");
}
Esempio n. 8
0
File: rm.c Progetto: dezelin/kBuild
static int
rm_file(char **argv)
{
	struct stat sb;
	int rval;
	char *f;

	/*
	 * Check up front before anything is deleted.
	 */
	int i;
	for (i = 0; argv[i]; i++) {
		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_FULL, argv[i]))
			return 1;
	}

	/*
	 * Remove a file.  POSIX 1003.2 states that, by default, attempting
	 * to remove a directory is an error, so must always stat the file.
	 */
	while ((f = *argv++) != NULL) {
		const char *operation = "?";
		/* Assume if can't stat the file, can't unlink it. */
		if (lstat(f, &sb)) {
#ifdef FTS_WHITEOUT
			if (Wflag) {
				sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
			} else {
#else
			{
#endif
				if (!fflag || errno != ENOENT) {
					fprintf(stderr, "lstat: %s: %s: %s " CUR_LINE() "\n", argv0, f, strerror(errno));
					eval = 1;
				}
				continue;
			}
#ifdef FTS_WHITEOUT
		} else if (Wflag) {
			fprintf(stderr, "%s: %s: %s\n", argv0, f, strerror(EEXIST));
			eval = 1;
			continue;
#endif
		}

		if (S_ISDIR(sb.st_mode) && !dflag) {
			fprintf(stderr, "%s: %s: is a directory\n", argv0, f);
			eval = 1;
			continue;
		}
		if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
			continue;
		rval = 0;
#ifdef UF_APPEND
		if (!uid &&
		    (sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
		    !(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
			rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
#endif
		if (rval == 0) {
			if (S_ISWHT(sb.st_mode)) {
				rval = undelete(f);
				operation = "undelete";
			} else if (S_ISDIR(sb.st_mode)) {
				rval = rmdir(f);
				operation = "rmdir";
			} else {
				if (Pflag)
					if (!rm_overwrite(f, &sb))
						continue;
				rval = unlink(f);
#ifdef _MSC_VER
				if (rval != 0) {
					chmod(f, 0777);
					rval = unlink(f);
				}
#endif
				operation = "unlink";
			}
		}
		if (rval && (!fflag || errno != ENOENT)) {
			fprintf(stderr, "%s: %s: %s: %s" CUR_LINE() "\n", operation, argv0, f, strerror(errno));
			eval = 1;
		}
		if (vflag && rval == 0)
			(void)printf("%s\n", f);
	}
	return eval;
}
Esempio n. 9
0
File: rm.c Progetto: dezelin/kBuild
static int
rm_tree(char **argv)
{
	FTS *fts;
	FTSENT *p;
	int needstat;
	int flags;
	int rval;

	/*
	 * Check up front before anything is deleted. This will not catch
	 * everything, but we'll check the individual items later.
	 */
	int i;
	for (i = 0; argv[i]; i++) {
		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, argv[i])) {
			return 1;
		}
	}

	/*
	 * Remove a file hierarchy.  If forcing removal (-f), or interactive
	 * (-i) or can't ask anyway (stdin_ok), don't stat the file.
	 */
	needstat = !uid || (!fflag && !iflag && stdin_ok);

	/*
	 * If the -i option is specified, the user can skip on the pre-order
	 * visit.  The fts_number field flags skipped directories.
	 */
#define	SKIPPED	1

	flags = FTS_PHYSICAL;
	if (!needstat)
		flags |= FTS_NOSTAT;
#ifdef FTS_WHITEOUT
	if (Wflag)
		flags |= FTS_WHITEOUT;
#endif
	if (!(fts = fts_open(argv, flags, NULL))) {
		return err(1, "fts_open");
	}
	while ((p = fts_read(fts)) != NULL) {
		const char *operation = "chflags";
		switch (p->fts_info) {
		case FTS_DNR:
			if (!fflag || p->fts_errno != ENOENT) {
				fprintf(stderr, "fts: %s: %s: %s" CUR_LINE() "\n",
				        argv0, p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_ERR:
			fts_close(fts);
			return errx(1, "fts: %s: %s " CUR_LINE(), p->fts_path, strerror(p->fts_errno));
		case FTS_NS:
			/*
			 * Assume that since fts_read() couldn't stat the
			 * file, it can't be unlinked.
			 */
			if (!needstat)
				break;
			if (!fflag || p->fts_errno != ENOENT) {
				fprintf(stderr, "fts: %s: %s: %s " CUR_LINE() "\n",
				        argv0, p->fts_path, strerror(p->fts_errno));
				eval = 1;
			}
			continue;
		case FTS_D:
			/* Pre-order: give user chance to skip. */
			if (!fflag && !check(p->fts_path, p->fts_accpath,
			    p->fts_statp)) {
				(void)fts_set(fts, p, FTS_SKIP);
				p->fts_number = SKIPPED;
			}
#ifdef UF_APPEND
			else if (!uid &&
				 (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
				 !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
				 chflags(p->fts_accpath,
					 p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
				goto err;
#endif
			continue;
		case FTS_DP:
			/* Post-order: see if user skipped. */
			if (p->fts_number == SKIPPED)
				continue;
			break;
		default:
			if (!fflag &&
			    !check(p->fts_path, p->fts_accpath, p->fts_statp))
				continue;
		}

		/*
		 * Protect against deleting root files and directories.
		 */
		if (kBuildProtectionEnforce(&g_ProtData, KBUILDPROTECTIONTYPE_RECURSIVE, p->fts_accpath)) {
			fts_close(fts);
			return 1;
		}

		rval = 0;
#ifdef UF_APPEND
		if (!uid &&
		    (p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
		    !(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
			rval = chflags(p->fts_accpath,
				       p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
#endif
		if (rval == 0) {
			/*
			 * If we can't read or search the directory, may still be
			 * able to remove it.  Don't print out the un{read,search}able
			 * message unless the remove fails.
			 */
			switch (p->fts_info) {
			case FTS_DP:
			case FTS_DNR:
				rval = rmdir(p->fts_accpath);
				if (rval == 0 || (fflag && errno == ENOENT)) {
					if (rval == 0 && vflag)
						(void)printf("%s\n",
						    p->fts_path);
					continue;
				}
				operation = "mkdir";
				break;

#ifdef FTS_W
			case FTS_W:
				rval = undelete(p->fts_accpath);
				if (rval == 0 && (fflag && errno == ENOENT)) {
					if (vflag)
						(void)printf("%s\n",
						    p->fts_path);
					continue;
				}
				operation = "undelete";
				break;
#endif

			case FTS_NS:
				/*
				 * Assume that since fts_read() couldn't stat
				 * the file, it can't be unlinked.
				 */
				if (fflag)
					continue;
				/* FALLTHROUGH */
			default:
				if (Pflag)
					if (!rm_overwrite(p->fts_accpath, NULL))
						continue;
				rval = unlink(p->fts_accpath);
#ifdef _MSC_VER
				if (rval != 0) {
    					chmod(p->fts_accpath, 0777);
					rval = unlink(p->fts_accpath);
				}
#endif

				if (rval == 0 || (fflag && errno == ENOENT)) {
					if (rval == 0 && vflag)
						(void)printf("%s\n",
						    p->fts_path);
					continue;
				}
				operation = "unlink";
				break;
			}
		}
#ifdef UF_APPEND
err:
#endif
		fprintf(stderr, "%s: %s: %s: %s " CUR_LINE() "\n", operation, argv0, p->fts_path, strerror(errno));
		eval = 1;
	}
	if (errno) {
		fprintf(stderr, "%s: fts_read: %s " CUR_LINE() "\n", argv0, strerror(errno));
		eval = 1;
	}
	fts_close(fts);
	return eval;
}