da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1992-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * rm [-fir] [file ...]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage[] =
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz"[-?\n@(#)$Id: rm (AT&T Research) 2009-06-18 $\n]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinUSAGE_LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?rm - remove files]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?\brm\b removes the named \afile\a arguments. By default it"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" does not remove directories. If a file is unwritable, the"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" standard input is a terminal, and the \b--force\b option is not"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" given, \brm\b prompts the user for whether to remove the file."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" An affirmative response (\by\b or \bY\b) removes the file, a quit"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" all other responses skip the current file.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[c|F:clear|clobber?Clear the contents of each file before removing by"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" writing a 0 filled buffer the same size as the file, executing"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \bfsync\b(2) and closing before attempting to remove. Implemented"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" only on systems that support \bfsync\b(2).]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[d:directory?\bremove\b(3) (or \bunlink\b(2)) directories rather than"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \brmdir\b(2), and don't require that they be empty before removal."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" The caller requires sufficient privilege, not to mention a strong"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" constitution, to use this option. Even though the directory must"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" not be empty, \brm\b still attempts to empty it before removal.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[f:force?Ignore nonexistent files and never prompt the user.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[i:interactive|prompt?Prompt whether to remove each file."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" An affirmative response (\by\b or \bY\b) removes the file, a quit"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" all other responses skip the current file.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[r|R:recursive?Remove the contents of directories recursively.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[u:unconditional?If \b--recursive\b and \b--force\b are also enabled then"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the owner read, write and execute modes are enabled (if not already"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" enabled) for each directory before attempting to remove directory"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" contents.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[v:verbose?Print the name of each file before removing it.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\nfile ...\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+SEE ALSO?\bmv\b(1), \brmdir\b(2), \bunlink\b(2), \bremove\b(3)]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <cmd.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ls.h>
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner#include <fts_fix.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <fs3d.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define RM_ENTRY 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define beenhere(f) (((f)->fts_number>>1)==(f)->fts_statp->st_nlink)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define isempty(f) (!((f)->fts_number&RM_ENTRY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define nonempty(f) ((f)->fts_parent->fts_number|=RM_ENTRY)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define pathchunk(n) roundof(n,1024)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define retry(f) ((f)->fts_number=((f)->fts_statp->st_nlink<<1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct State_s /* program state */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz void* context; /* builtin context */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int clobber; /* clear out file data first */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int directory; /* remove(dir) not rmdir(dir) */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int force; /* force actions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int fs3d; /* 3d enabled */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int interactive; /* prompt for approval */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int recursive; /* remove subtrees too */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int terminal; /* attached to terminal */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int uid; /* caller uid */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int unconditional; /* enable dir rwx on preorder */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int verbose; /* display each file */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fsync
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char buf[SF_BUFSIZE];/* clobber buffer */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} State_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * remove a single file
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinrm(State_t* state, register FTSENT* ent)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* path;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int v;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct stat st;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_info == FTS_NS || ent->fts_info == FTS_ERR || ent->fts_info == FTS_SLNONE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: not found", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (state->fs3d && iview(ent->fts_statp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else switch (ent->fts_info)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNR:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DNX:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->unconditional)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!chmod(ent->fts_name, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_AGAIN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.errors++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot %s directory", ent->fts_path, (ent->fts_info & FTS_NR) ? "read" : "search");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.errors++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nonempty(ent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_D:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DC:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path = ent->fts_name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (path[0] == '.' && (!path[1] || path[1] == '.' && !path[2]) && (ent->fts_level > 0 || path[1]))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot remove", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.errors++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->recursive)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: directory", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!beenhere(ent))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->unconditional && (ent->fts_statp->st_mode ^ S_IRWXU))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin chmod(path, (ent->fts_statp->st_mode & S_IPERM)|S_IRWXU);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_level > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_accpath == ent->fts_name || !(s = strrchr(ent->fts_accpath, '/')))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = !stat(".", &st);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path = ent->fts_accpath;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = !stat(path, &st);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s = '/';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (v)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = st.st_nlink <= 2 || st.st_ino == ent->fts_parent->fts_statp->st_ino && st.st_dev == ent->fts_parent->fts_statp->st_dev || strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'l');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (v)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->interactive)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((v = astquery(-1, "remove directory %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (v > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_SKIP);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nonempty(ent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_info == FTS_D)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ent->fts_info = FTS_DC;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s: hard link to directory", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (ent->fts_info == FTS_D)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case FTS_DP:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (isempty(ent) || state->directory)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path = ent->fts_name;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (path[0] != '.' || path[1])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path = ent->fts_accpath;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->verbose)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sfstdout, ent->fts_path, '\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((ent->fts_info == FTS_DC || state->directory) ? remove(path) : rmdir(path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (errno)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin case ENOENT:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case EEXIST:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if defined(ENOTEMPTY) && (ENOTEMPTY) != (EEXIST)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ENOTEMPTY:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (ent->fts_info == FTS_DP && !beenhere(ent))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin retry(ent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_set(NiL, ent, FTS_AGAIN);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nonempty(ent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: directory not removed", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.errors++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: cannot remove", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.errors++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nonempty(ent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!state->force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s: directory not removed", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.errors++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin default:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin path = ent->fts_accpath;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->verbose)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputr(sfstdout, ent->fts_path, '\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->interactive)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((v = astquery(-1, "remove %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (v > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nonempty(ent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!state->force && state->terminal && S_ISREG(ent->fts_statp->st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = open(path, O_RDWR)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef ENOENT
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno != ENOENT &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef EROFS
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno != EROFS &&
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (v = astquery(-1, "override protection %s for %s? ",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef ETXTBSY
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin errno == ETXTBSY ? "``running program''" :
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ent->fts_statp->st_uid != state->uid ? "``not owner''" :
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz fmtmode(ent->fts_statp->st_mode & S_IPERM, 0) + 1, ent->fts_path)) < 0 ||
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz sh_checksig(state->context))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (v > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nonempty(ent);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fsync
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state->clobber && S_ISREG(ent->fts_statp->st_mode) && ent->fts_statp->st_size > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((n = open(path, O_WRONLY)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot clear data", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin off_t c = ent->fts_statp->st_size;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (write(n, state->buf, sizeof(state->buf)) != sizeof(state->buf))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: data clear error", ent->fts_path);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c <= sizeof(state->buf))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c -= sizeof(state->buf);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fsync(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (remove(path))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin nonempty(ent);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin switch (errno)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin case ENOENT:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin break;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin default:
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!state->force || state->interactive)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error(ERROR_SYSTEM|2, "%s: not removed", ent->fts_path);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin error_info.errors++;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin break;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinb_rm(int argc, register char** argv, void* context)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin State_t state;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FTS* fts;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FTSENT* ent;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int set3d;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memset(&state, 0, sizeof(state));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz state.context = context;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.fs3d = fs3d(FS3D_TEST);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.terminal = isatty(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (optget(argv, usage))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'd':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.directory = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'f':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.force = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.interactive = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'i':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.interactive = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.force = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'r':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'R':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.recursive = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'F':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_fsync
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.clobber = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "%s not implemented on this system", opt_info.name);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'u':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.unconditional = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'v':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.verbose = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '?':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_USAGE|4, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ':':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv += opt_info.index;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*argv && streq(*argv, "-") && !streq(*(argv - 1), "--"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (error_info.errors || !*argv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_USAGE|4, "%s", optusage(NiL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * do it
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state.interactive)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.verbose = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.uid = geteuid();
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.unconditional = state.unconditional && state.recursive && state.force;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (state.recursive && state.fs3d)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin set3d = state.fs3d;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.fs3d = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fs3d(0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin set3d = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (fts = fts_open(argv, FTS_PHYSICAL, NiL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin while (!sh_checksig(context) && (ent = fts_read(fts)) && !rm(&state, ent));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fts_close(fts);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!state.force)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|2, "%s: cannot remove", argv[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (set3d)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fs3d(set3d);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return error_info.errors != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}