summaryrefslogtreecommitdiffstats
path: root/bin/rm
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>1995-04-13 13:35:09 +0000
committerache <ache@FreeBSD.org>1995-04-13 13:35:09 +0000
commitbf4c9aa1486ca02ef393fd8a263baba6ac629ef2 (patch)
tree7d222f9d4e2fa1d037ac87ef6e35c9ee85f34198 /bin/rm
parentfdacac9026b1aa66b01fab9a5394fe2f9f49aa65 (diff)
downloadFreeBSD-src-bf4c9aa1486ca02ef393fd8a263baba6ac629ef2.zip
FreeBSD-src-bf4c9aa1486ca02ef393fd8a263baba6ac629ef2.tar.gz
Allow root to delete uchg/uappnd files
Diffstat (limited to 'bin/rm')
-rw-r--r--bin/rm/Makefile5
-rw-r--r--bin/rm/rm.c93
2 files changed, 68 insertions, 30 deletions
diff --git a/bin/rm/Makefile b/bin/rm/Makefile
index 97f68e2..b7e1d58 100644
--- a/bin/rm/Makefile
+++ b/bin/rm/Makefile
@@ -1,6 +1,9 @@
# @(#)Makefile 8.1 (Berkeley) 5/31/93
-# $Id$
+# $Id: Makefile,v 1.2 1994/09/24 02:56:59 davidg Exp $
PROG= rm
+SRCS= rm.c stat_flags.c
+
+.PATH: ${.CURDIR}/../ls
.include <bsd.prog.mk>
diff --git a/bin/rm/rm.c b/bin/rm/rm.c
index ce148ab..1a74378 100644
--- a/bin/rm/rm.c
+++ b/bin/rm/rm.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: rm.c,v 1.5 1994/09/24 02:57:02 davidg Exp $
*/
#ifndef lint
@@ -55,7 +55,10 @@ static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94";
#include <string.h>
#include <unistd.h>
+extern char *flags_to_string __P((u_long, char *));
+
int dflag, eval, fflag, iflag, Pflag, stdin_ok;
+uid_t uid;
int check __P((char *, char *, struct stat *));
void checkdot __P((char **));
@@ -114,6 +117,7 @@ main(argc, argv)
exit (eval);
stdin_ok = isatty(STDIN_FILENO);
+ uid = geteuid();
if (rflag)
rm_tree(argv);
@@ -129,12 +133,13 @@ rm_tree(argv)
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 = !fflag && !iflag && stdin_ok;
+ needstat = !uid || !fflag && !iflag && stdin_ok;
/*
* If the -i option is specified, the user can skip on the pre-order
@@ -177,6 +182,12 @@ rm_tree(argv)
(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)) &&
+ chflags(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. */
@@ -188,25 +199,34 @@ rm_tree(argv)
!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.
- */
- if (p->fts_info == FTS_DP || p->fts_info == FTS_DNR) {
- if (!rmdir(p->fts_accpath))
- continue;
- if (errno == ENOENT) {
- if (fflag)
+ rval = 0;
+ 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));
+ 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;
- } 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;
+ 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;
}
@@ -243,12 +263,19 @@ rm_file(argv)
}
if (!fflag && !check(f, f, &sb))
continue;
- if (S_ISDIR(sb.st_mode))
- rval = rmdir(f);
- else {
- if (Pflag)
- rm_overwrite(f, &sb);
- rval = unlink(f);
+ rval = 0;
+ 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));
+ if (!rval) {
+ 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);
@@ -318,7 +345,7 @@ check(path, name, sp)
struct stat *sp;
{
int ch, first;
- char modep[15];
+ char modep[15], flagsp[128];
/* Check -i first. */
if (iflag)
@@ -330,13 +357,21 @@ check(path, name, sp)
* because their permissions are meaningless. Check stdin_ok
* first because we may not have stat'ed the file.
*/
- if (!stdin_ok || S_ISLNK(sp->st_mode) || !access(name, W_OK))
+ if (!stdin_ok || S_ISLNK(sp->st_mode) ||
+ !access(name, W_OK) &&
+ !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
+ (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid))
return (1);
strmode(sp->st_mode, modep);
- (void)fprintf(stderr, "override %s%s%s/%s for %s? ",
+ strcpy(flagsp, flags_to_string(sp->st_flags, NULL));
+ if (*flagsp)
+ strcat(flagsp, " ");
+ (void)fprintf(stderr, "override %s%s%s/%s %sfor %s? ",
modep + 1, modep[9] == ' ' ? "" : " ",
user_from_uid(sp->st_uid, 0),
- group_from_gid(sp->st_gid, 0), path);
+ group_from_gid(sp->st_gid, 0),
+ *flagsp ? flagsp : "",
+ path);
}
(void)fflush(stderr);
OpenPOWER on IntegriCloud