rm.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1992-2012 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* rm [-fir] [file ...]
*/
static const char usage[] =
"[-?\n@(#)$Id: rm (AT&T Research) 2012-02-14 $\n]"
"[+NAME?rm - remove files]"
"[+DESCRIPTION?\brm\b removes the named \afile\a arguments. By default it"
" does not remove directories. If a file is unwritable, the"
" standard input is a terminal, and the \b--force\b option is not"
" given, \brm\b prompts the user for whether to remove the file."
" An affirmative response (\by\b or \bY\b) removes the file, a quit"
" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and"
" all other responses skip the current file.]"
"[c|F:clear|clobber?Clear the contents of each file before removing by"
" writing a 0 filled buffer the same size as the file, executing"
" \bfsync\b(2) and closing before attempting to remove. Implemented"
" only on systems that support \bfsync\b(2).]"
"[d:directory?\bremove\b(3) (or \bunlink\b(2)) directories rather than"
" \brmdir\b(2), and don't require that they be empty before removal."
" The caller requires sufficient privilege, not to mention a strong"
" constitution, to use this option. Even though the directory must"
" not be empty, \brm\b still attempts to empty it before removal.]"
"[f:force?Ignore nonexistent files, ignore no file operands specified,"
" and never prompt the user.]"
"[i:interactive|prompt?Prompt whether to remove each file."
" An affirmative response (\by\b or \bY\b) removes the file, a quit"
" response (\bq\b or \bQ\b) causes \brm\b to exit immediately, and"
" all other responses skip the current file.]"
"[r|R:recursive?Remove the contents of directories recursively.]"
"[u:unconditional?If \b--recursive\b and \b--force\b are also enabled then"
" the owner read, write and execute modes are enabled (if not already"
" enabled) for each directory before attempting to remove directory"
" contents.]"
"[v:verbose?Print the name of each file before removing it.]"
"\n"
"\nfile ...\n"
"\n"
"[+SEE ALSO?\bmv\b(1), \brmdir\b(2), \bunlink\b(2), \bremove\b(3)]"
;
#include <cmd.h>
#include <ls.h>
#include <fts_fix.h>
#include <fs3d.h>
#define RM_ENTRY 1
typedef struct State_s /* program state */
{
int clobber; /* clear out file data first */
int directory; /* remove(dir) not rmdir(dir) */
int force; /* force actions */
int fs3d; /* 3d enabled */
int interactive; /* prompt for approval */
int recursive; /* remove subtrees too */
int terminal; /* attached to terminal */
int uid; /* caller uid */
int unconditional; /* enable dir rwx on preorder */
int verbose; /* display each file */
#if _lib_fsync
#endif
} State_t;
/*
* remove a single file
*/
static int
{
register char* path;
register int n;
int v;
{
}
{
case FTS_DNR:
case FTS_DNX:
if (state->unconditional)
{
break;
{
break;
}
error_info.errors++;
}
else
error_info.errors++;
break;
case FTS_D:
case FTS_DC:
{
else
error_info.errors++;
break;
}
{
break;
}
{
{
char* s;
else
{
*s = 0;
*s = '/';
}
if (v)
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');
}
else
v = 1;
if (v)
{
if (state->interactive)
{
return -1;
if (v > 0)
{
}
}
break;
}
else
{
}
}
break;
/*FALLTHROUGH*/
case FTS_DP:
{
{
switch (errno)
{
case ENOENT:
break;
case EEXIST:
case ENOTEMPTY:
#endif
{
break;
}
/*FALLTHROUGH*/
default:
else
error_info.errors++;
break;
}
}
else
error_info.errors++;
}
else
{
else
error_info.errors++;
}
break;
default:
if (state->interactive)
{
return -1;
if (v > 0)
{
break;
}
}
{
#ifdef ETXTBSY
#endif
return -1;
if (v > 0)
{
break;
}
}
#if _lib_fsync
{
else
{
for (;;)
{
{
break;
}
break;
}
fsync(n);
close(n);
}
}
#endif
{
switch (errno)
{
case ENOENT:
break;
default:
else
error_info.errors++;
break;
}
}
break;
}
return 0;
}
int
{
int set3d;
for (;;)
{
{
case 'd':
continue;
case 'f':
state.interactive = 0;
continue;
case 'i':
continue;
case 'r':
case 'R':
continue;
case 'F':
#if _lib_fsync
#else
#endif
continue;
case 'u':
continue;
case 'v':
continue;
case '?':
break;
case ':':
break;
}
break;
}
argv++;
if (!*argv)
return 0;
/*
* do it
*/
if (state.interactive)
{
fs3d(0);
}
else
set3d = 0;
{
}
if (set3d)
return error_info.errors != 0;
}