17bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* $NetBSD: rm.c,v 1.53 2013/04/26 18:43:22 christos Exp $ */ 27bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 37bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/*- 47bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Copyright (c) 1990, 1993, 1994, 2003 57bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * The Regents of the University of California. All rights reserved. 67bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 77bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Redistribution and use in source and binary forms, with or without 87bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * modification, are permitted provided that the following conditions 97bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * are met: 107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 1. Redistributions of source code must retain the above copyright 117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * notice, this list of conditions and the following disclaimer. 127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 2. Redistributions in binary form must reproduce the above copyright 137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * notice, this list of conditions and the following disclaimer in the 147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * documentation and/or other materials provided with the distribution. 157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3. Neither the name of the University nor the names of its contributors 167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * may be used to endorse or promote products derived from this software 177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * without specific prior written permission. 187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * SUCH DAMAGE. 307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/cdefs.h> 337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef lint 347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\ 357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes The Regents of the University of California. All rights reserved."); 367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif /* not lint */ 377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef lint 397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#if 0 407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic char sccsid[] = "@(#)rm.c 8.8 (Berkeley) 4/27/95"; 417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#else 427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes__RCSID("$NetBSD: rm.c,v 1.53 2013/04/26 18:43:22 christos Exp $"); 437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif /* not lint */ 457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/param.h> 477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/stat.h> 487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <sys/types.h> 497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <err.h> 517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <errno.h> 527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <fcntl.h> 537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <fts.h> 547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <grp.h> 557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <locale.h> 567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <pwd.h> 577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <signal.h> 587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <stdio.h> 597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <stdlib.h> 607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <string.h> 617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#include <unistd.h> 627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic int dflag, eval, fflag, iflag, Pflag, stdin_ok, vflag, Wflag; 647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic int xflag; 657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic sig_atomic_t pinfo; 667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic int check(char *, char *, struct stat *); 687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void checkdot(char **); 697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void progress(int); 707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void rm_file(char **); 717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic int rm_overwrite(char *, struct stat *); 727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void rm_tree(char **); 737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes__dead static void usage(void); 747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * For the sake of the `-f' flag, check whether an error number indicates the 777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * failure of an operation due to an non-existent file, either per se (ENOENT) 787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * or because its filename argument was illegal (ENAMETOOLONG, ENOTDIR). 797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define NONEXISTENT(x) \ 817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ((x) == ENOENT || (x) == ENAMETOOLONG || (x) == ENOTDIR) 827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * rm -- 857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * This rm is different from historic rm's, but is expected to match 867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * POSIX 1003.2 behavior. The most visible difference is that -f 877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * has two specific effects now, ignore non-existent files and force 887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * file removal. 897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesint 917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesmain(int argc, char *argv[]) 927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int ch, rflag; 947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes setprogname(argv[0]); 967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)setlocale(LC_ALL, ""); 977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes Pflag = rflag = xflag = 0; 997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes while ((ch = getopt(argc, argv, "dfiPRrvWx")) != -1) 1007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes switch (ch) { 1017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'd': 1027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes dflag = 1; 1037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'f': 1057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes fflag = 1; 1067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes iflag = 0; 1077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'i': 1097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes fflag = 0; 1107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes iflag = 1; 1117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'P': 1137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes Pflag = 1; 1147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'R': 1167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'r': /* Compatibility. */ 1177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rflag = 1; 1187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'v': 1207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes vflag = 1; 1217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'x': 1237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes xflag = 1; 1247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef __ANDROID__ 1267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case 'W': 1277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes Wflag = 1; 1287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 1297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 1307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case '?': 1317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes default: 1327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes usage(); 1337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes argc -= optind; 1357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes argv += optind; 1367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (argc < 1) { 1387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (fflag) 1397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return 0; 1407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes usage(); 1417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)signal(SIGINFO, progress); 1447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes checkdot(argv); 1467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (*argv) { 1487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes stdin_ok = isatty(STDIN_FILENO); 1497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rflag) 1517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rm_tree(argv); 1527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else 1537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rm_file(argv); 1547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes exit(eval); 1577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 1587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 1597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 1617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesrm_tree(char **argv) 1627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 1637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes FTS *fts; 1647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes FTSENT *p; 1657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int flags, needstat, rval; 1667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 1687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Remove a file hierarchy. If forcing removal (-f), or interactive 1697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * (-i) or can't ask anyway (stdin_ok), don't stat the file. 1707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 1717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes needstat = !fflag && !iflag && stdin_ok; 1727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 1747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * If the -i option is specified, the user can skip on the pre-order 1757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * visit. The fts_number field flags skipped directories. 1767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 1777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define SKIPPED 1 1787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes flags = FTS_PHYSICAL; 1807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!needstat) 1817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes flags |= FTS_NOSTAT; 1827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef __ANDROID__ 1837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (Wflag) 1847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes flags |= FTS_WHITEOUT; 1857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 1867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (xflag) 1877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes flags |= FTS_XDEV; 1887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((fts = fts_open(argv, flags, NULL)) == NULL) 1897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(1, "fts_open failed"); 1907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes while ((p = fts_read(fts)) != NULL) { 1917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 1927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes switch (p->fts_info) { 1937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_DNR: 1947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!fflag || p->fts_errno != ENOENT) { 1957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warnx("%s: %s", p->fts_path, 1967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes strerror(p->fts_errno)); 1977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 1987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 1997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_ERR: 2017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errx(EXIT_FAILURE, "%s: %s", p->fts_path, 2027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes strerror(p->fts_errno)); 2037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 2047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_NS: 2057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 2067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * FTS_NS: assume that if can't stat the file, it 2077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * can't be unlinked. 2087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 2097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (fflag && NONEXISTENT(p->fts_errno)) 2107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (needstat) { 2127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warnx("%s: %s", p->fts_path, 2137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes strerror(p->fts_errno)); 2147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 2157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 2187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_D: 2197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Pre-order: give user chance to skip. */ 2207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!fflag && !check(p->fts_path, p->fts_accpath, 2217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes p->fts_statp)) { 2227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)fts_set(fts, p, FTS_SKIP); 2237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes p->fts_number = SKIPPED; 2247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_DP: 2277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Post-order: see if user skipped. */ 2287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (p->fts_number == SKIPPED) 2297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 2317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes default: 2327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!fflag && 2337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes !check(p->fts_path, p->fts_accpath, p->fts_statp)) 2347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rval = 0; 2387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 2397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * If we can't read or search the directory, may still be 2407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * able to remove it. Don't print out the un{read,search}able 2417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * message unless the remove fails. 2427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 2437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes switch (p->fts_info) { 2447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_DP: 2457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_DNR: 2467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rval = rmdir(p->fts_accpath); 2477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rval != 0 && fflag && errno == ENOENT) 2487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 2507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef __ANDROID__ 2527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes case FTS_W: 2537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rval = undelete(p->fts_accpath); 2547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rval != 0 && fflag && errno == ENOENT) 2557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 2577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 2587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes default: 2607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (Pflag) { 2617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rm_overwrite(p->fts_accpath, NULL)) 2627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rval = unlink(p->fts_accpath); 2657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rval != 0 && fflag && NONEXISTENT(errno)) 2667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 2677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes break; 2687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rval != 0) { 2707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warn("%s", p->fts_path); 2717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 2727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else if (vflag || pinfo) { 2737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes pinfo = 0; 2747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)printf("%s\n", p->fts_path); 2757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 2777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (errno) 2787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes err(1, "fts_read"); 2797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes fts_close(fts); 2807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 2817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 2837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesrm_file(char **argv) 2847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 2857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes struct stat sb; 2867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int rval; 2877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes char *f; 2887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 2897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 2907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Remove a file. POSIX 1003.2 states that, by default, attempting 2917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * to remove a directory is an error, so must always stat the file. 2927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 2937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes while ((f = *argv++) != NULL) { 2947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Assume if can't stat the file, can't unlink it. */ 2957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (lstat(f, &sb)) { 2967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef __ANDROID__ 2977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (Wflag) { 2987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR; 2997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else { 3007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 3017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!fflag || !NONEXISTENT(errno)) { 3027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warn("%s", f); 3037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 3047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 3067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef __ANDROID__ 3077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else if (Wflag) { 3097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warnx("%s: %s", f, strerror(EEXIST)); 3107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 3117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 3127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 3137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (S_ISDIR(sb.st_mode) && !dflag) { 3167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warnx("%s: is a directory", f); 3177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 3187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 3197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb)) 3217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 3227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#ifndef __ANDROID__ 3237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (S_ISWHT(sb.st_mode)) 3247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rval = undelete(f); 3257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else if (S_ISDIR(sb.st_mode)) 3267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#else 3277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (S_ISDIR(sb.st_mode)) 3287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#endif 3297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rval = rmdir(f); 3307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else { 3317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (Pflag) { 3327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rm_overwrite(f, &sb)) 3337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 3347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rval = unlink(f); 3367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (rval && (!fflag || !NONEXISTENT(errno))) { 3387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warn("%s", f); 3397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 3407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (vflag && rval == 0) 3427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)printf("%s\n", f); 3437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 3447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 3457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 3467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 3477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * rm_overwrite -- 3487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Overwrite the file 3 times with varying bit patterns. 3497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * This is an expensive way to keep people from recovering files from your 3517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * non-snapshotted FFS filesystems using fsdb(8). Really. No more. Only 3527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * regular files are deleted, directories (and therefore names) will remain. 3537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Also, this assumes a fixed-block file system (like FFS, or a V7 or a 3547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * System V file system). In a logging file system, you'll have to have 3557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * kernel support. 3567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * A note on standards: U.S. DoD 5220.22-M "National Industrial Security 3587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Program Operating Manual" ("NISPOM") is often cited as a reference 3597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * for clearing and sanitizing magnetic media. In fact, a matrix of 3607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * "clearing" and "sanitization" methods for various media was given in 3617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Chapter 8 of the original 1995 version of NISPOM. However, that 3627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * matrix was *removed from the document* when Chapter 8 was rewritten 3637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * in Change 2 to the document in 2001. Recently, the Defense Security 3647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Service has made a revised clearing and sanitization matrix available 3657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * in Microsoft Word format on the DSS web site. The standardization 3667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * status of this matrix is unclear. Furthermore, one must be very 3677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * careful when referring to this matrix: it is intended for the "clearing" 3687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * prior to reuse or "sanitization" prior to disposal of *entire media*, 3697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * not individual files and the only non-physically-destructive method of 3707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * "sanitization" that is permitted for magnetic disks of any kind is 3717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * specifically noted to be prohibited for media that have contained 3727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Top Secret data. 3737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * It is impossible to actually conform to the exact procedure given in 3757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * the matrix if one is overwriting a file, not an entire disk, because 3767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * the procedure requires examination and comparison of the disk's defect 3777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * lists. Any program that claims to securely erase *files* while 3787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * conforming to the standard, then, is not correct. We do as much of 3797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * what the standard requires as can actually be done when erasing a 3807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * file, rather than an entire disk; but that does not make us conformant. 3817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Furthermore, the presence of track caches, disk and controller write 3837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * caches, and so forth make it extremely difficult to ensure that data 3847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * have actually been written to the disk, particularly when one tries 3857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * to repeatedly overwrite the same sectors in quick succession. We call 3867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * fsync(), but controllers with nonvolatile cache, as well as IDE disks 3877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * that just plain lie about the stable storage of data, will defeat this. 3887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Finally, widely respected research suggests that the given procedure 3907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * is nowhere near sufficient to prevent the recovery of data using special 3917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * forensic equipment and techniques that are well-known. This is 3927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * presumably one reason that the matrix requires physical media destruction, 3937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * rather than any technique of the sort attempted here, for secret data. 3947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Caveat Emptor. 3967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 3977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * rm_overwrite will return 0 on success. 3987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 3997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic int 4017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesrm_overwrite(char *file, struct stat *sbp) 4027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 4037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes struct stat sb, sb2; 4047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int fd, randint; 4057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes char randchar; 4067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes fd = -1; 4087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (sbp == NULL) { 4097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (lstat(file, &sb)) 4107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; 4117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes sbp = &sb; 4127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!S_ISREG(sbp->st_mode)) 4147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return 0; 4157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* flags to try to defeat hidden caching by forcing seeks */ 4177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((fd = open(file, O_RDWR|O_SYNC|O_RSYNC|O_NOFOLLOW, 0)) == -1) 4187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; 4197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (fstat(fd, &sb2)) { 4217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; 4227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (sb2.st_dev != sbp->st_dev || sb2.st_ino != sbp->st_ino || 4257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes !S_ISREG(sb2.st_mode)) { 4267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes errno = EPERM; 4277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; 4287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 4297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define RAND_BYTES 1 4317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define THIS_BYTE 0 4327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define WRITE_PASS(mode, byte) do { \ 4347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes off_t len; \ 4357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes size_t wlen, i; \ 4367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes char buf[8 * 1024]; \ 4377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes \ 4387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \ 4397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; \ 4407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes \ 4417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (mode == THIS_BYTE) \ 4427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes memset(buf, byte, sizeof(buf)); \ 4437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (len = sbp->st_size; len > 0; len -= wlen) { \ 4447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (mode == RAND_BYTES) { \ 4457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (i = 0; i < sizeof(buf); \ 4467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes i+= sizeof(u_int32_t)) \ 4477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes *(int *)(buf + i) = arc4random(); \ 4487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } \ 4497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes wlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \ 4507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((size_t)write(fd, buf, wlen) != wlen) \ 4517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; \ 4527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } \ 4537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes sync(); /* another poke at hidden caches */ \ 4547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} while (/* CONSTCOND */ 0) 4557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define READ_PASS(byte) do { \ 4577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes off_t len; \ 4587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes size_t rlen; \ 4597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes char pattern[8 * 1024]; \ 4607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes char buf[8 * 1024]; \ 4617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes \ 4627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \ 4637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; \ 4647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes \ 4657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes memset(pattern, byte, sizeof(pattern)); \ 4667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for(len = sbp->st_size; len > 0; len -= rlen) { \ 4677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes rlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \ 4687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if((size_t)read(fd, buf, rlen) != rlen) \ 4697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; \ 4707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if(memcmp(buf, pattern, rlen)) \ 4717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; \ 4727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } \ 4737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes sync(); /* another poke at hidden caches */ \ 4747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} while (/* CONSTCOND */ 0) 4757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 4777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * DSS sanitization matrix "clear" for magnetic disks: 4787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * option 'c' "Overwrite all addressable locations with a single 4797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * character." 4807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 4817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes randint = arc4random(); 4827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes randchar = *(char *)&randint; 4837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes WRITE_PASS(THIS_BYTE, randchar); 4847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 4867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * DSS sanitization matrix "sanitize" for magnetic disks: 4877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * option 'd', sub 2 "Overwrite all addressable locations with a 4887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * character, then its complement. Verify "complement" character 4897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * was written successfully to all addressable locations, then 4907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * overwrite all addressable locations with random characters; or 4917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * verify third overwrite of random characters." The rest of the 4927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * text in d-sub-2 specifies requirements for overwriting spared 4937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * sectors; we cannot conform to it when erasing only a file, thus 4947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * we do not conform to the standard. 4957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 4967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 4977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 1. "a character" */ 4987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes WRITE_PASS(THIS_BYTE, 0xff); 4997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 2. "its complement" */ 5017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes WRITE_PASS(THIS_BYTE, 0x00); 5027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 3. "Verify 'complement' character" */ 5047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes READ_PASS(0x00); 5057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 4. "overwrite all addressable locations with random characters" */ 5077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes WRITE_PASS(RAND_BYTES, 0x00); 5097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 5117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * As the file might be huge, and we note that this revision of 5127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * the matrix says "random characters", not "a random character" 5137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * as the original did, we do not verify the random-character 5147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * write; the "or" in the standard allows this. 5157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 5167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (close(fd) == -1) { 5187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes fd = -1; 5197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes goto err; 5207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return 0; 5237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5247bb5660647d0106f96b000c25f5690a45734c38cElliott Hugheserr: eval = 1; 5257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warn("%s", file); 5267bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (fd != -1) 5277bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes close(fd); 5287bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return 1; 5297bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 5307bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5317bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic int 5327bb5660647d0106f96b000c25f5690a45734c38cElliott Hughescheck(char *path, char *name, struct stat *sp) 5337bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 5347bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int ch, first; 5357bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes char modep[15]; 5367bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5377bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* Check -i first. */ 5387bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (iflag) 5397bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)fprintf(stderr, "remove '%s'? ", path); 5407bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else { 5417bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* 5427bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * If it's not a symbolic link and it's unwritable and we're 5437bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * talking to a terminal, ask. Symbolic links are excluded 5447bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * because their permissions are meaningless. Check stdin_ok 5457bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * first because we may not have stat'ed the file. 5467bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 5477bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!stdin_ok || S_ISLNK(sp->st_mode) || 5487bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes !(access(name, W_OK) && (errno != ETXTBSY))) 5497bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return (1); 5507bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes strmode(sp->st_mode, modep); 5517bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (Pflag) { 5527bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warnx( 5537bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes "%s: -P was specified but file could not" 5547bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes " be overwritten", path); 5557bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return 0; 5567bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5577bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)fprintf(stderr, "override %s%s%s:%s for '%s'? ", 5587bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes modep + 1, modep[9] == ' ' ? "" : " ", 5597bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes user_from_uid(sp->st_uid, 0), 5607bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes group_from_gid(sp->st_gid, 0), path); 5617bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 5627bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)fflush(stderr); 5637bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5647bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes first = ch = getchar(); 5657bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes while (ch != '\n' && ch != EOF) 5667bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ch = getchar(); 5677bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes return (first == 'y' || first == 'Y'); 5687bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 5697bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5707bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes/* 5717bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * POSIX.2 requires that if "." or ".." are specified as the basename 5727bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * portion of an operand, a diagnostic message be written to standard 5737bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * error and nothing more be done with such operands. 5747bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * 5757bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * Since POSIX.2 defines basename as the final portion of a path after 5767bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes * trailing slashes have been removed, we'll remove them here. 5777bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes */ 5787bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2]))) 5797bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 5807bb5660647d0106f96b000c25f5690a45734c38cElliott Hughescheckdot(char **argv) 5817bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 5827bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes char *p, **save, **t; 5837bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes int complained; 5847bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5857bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes complained = 0; 5867bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (t = argv; *t;) { 5877bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* strip trailing slashes */ 5887bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes p = strrchr(*t, '\0'); 5897bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes while (--p > *t && *p == '/') 5907bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes *p = '\0'; 5917bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5927bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* extract basename */ 5937bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if ((p = strrchr(*t, '/')) != NULL) 5947bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++p; 5957bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes else 5967bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes p = *t; 5977bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 5987bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (ISDOT(p)) { 5997bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes if (!complained++) 6007bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes warnx("\".\" and \"..\" may not be removed"); 6017bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes eval = 1; 6027bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes for (save = t; (t[0] = t[1]) != NULL; ++t) 6037bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes continue; 6047bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes t = save; 6057bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } else 6067bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes ++t; 6077bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes } 6087bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 6097bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 6107bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 6117bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesusage(void) 6127bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 6137bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 6147bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes (void)fprintf(stderr, "usage: %s [-f|-i] [-dPRrvWx] file ...\n", 6157bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes getprogname()); 6167bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes exit(1); 6177bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes /* NOTREACHED */ 6187bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 6197bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 6207bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesstatic void 6217bb5660647d0106f96b000c25f5690a45734c38cElliott Hughesprogress(int sig __unused) 6227bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes{ 6237bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes 6247bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes pinfo++; 6257bb5660647d0106f96b000c25f5690a45734c38cElliott Hughes} 626