Subject: Larger rm Change
To: None <tech-userlevel@netbsd.org>
From: Jason R. Fink <jrf@adresearch.com>
List: tech-userlevel
Date: 01/07/2003 11:58:56
--/04w6evG8XlLl3ft
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hello,

THe first rm change I sent out was not quite right. In
this one I have pulled in all of the FreeBSD code.
The only part I do not like about this *version*
is the IMMUTABLE tests. They seem a bit on the long
side.

	j

-- 
J Fink http://pyxis.homeunix.net/~jrf/
NetBSD Developer http://www.netbsd.org/
Senior Sysadmin/Programmer http://www.ipsos.com/

--/04w6evG8XlLl3ft
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="rm.diff"

Index: rm.1
===================================================================
RCS file: /cvsroot/src/bin/rm/rm.1,v
retrieving revision 1.14
diff -u -r1.14 rm.1
--- rm.1	2002/05/02 13:14:23	1.14
+++ rm.1	2003/01/06 19:15:31
@@ -37,6 +37,7 @@
 .\"	@(#)rm.1	8.5 (Berkeley) 12/5/94
 .\"
 .Dd December 5, 1994
+.Dd January 6, 2003
 .Dt RM 1
 .Os
 .Sh NAME
@@ -45,7 +46,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl f | Fl i
-.Op Fl dPRrW
+.Op Fl dPRrvW
 .Ar
 .Sh DESCRIPTION
 The
@@ -101,6 +102,10 @@
 .It Fl r
 Equivalent to
 .Fl R .
+.It Fl v
+Cause
+.Nm
+to be verbose, showing files as they are processed.
 .It Fl W
 Attempts to undelete the named files.
 Currently, this option can only be used to recover
@@ -155,3 +160,8 @@
 utility is expected to be
 .St -p1003.2
 compatible.
+.Pp
+The
+.Fl v
+option is an extension to
+.St -p1003.2
Index: rm.c
===================================================================
RCS file: /cvsroot/src/bin/rm/rm.c,v
retrieving revision 1.31
diff -u -r1.31 rm.c
--- rm.c	2002/11/05 04:49:05	1.31
+++ rm.c	2003/01/06 19:15:31
@@ -62,7 +62,8 @@
 #include <string.h>
 #include <unistd.h>
 
-int dflag, eval, fflag, iflag, Pflag ,stdin_ok, Wflag;
+int dflag, eval, fflag, iflag, Pflag ,stdin_ok, vflag, Wflag;
+uid_t uid;
 
 int	check(char *, char *, struct stat *);
 void	checkdot(char **);
@@ -96,7 +97,7 @@
 	(void)setlocale(LC_ALL, "");
 
 	Pflag = rflag = 0;
-	while ((ch = getopt(argc, argv, "dfiPRrW")) != -1)
+	while ((ch = getopt(argc, argv, "dfiPRrvW")) != -1)
 		switch (ch) {
 		case 'd':
 			dflag = 1;
@@ -116,6 +117,9 @@
 		case 'r':			/* Compatibility. */
 			rflag = 1;
 			break;
+		case 'v':
+			vflag = 1;
+			break;
 		case 'W':
 			Wflag = 1;
 			break;
@@ -149,13 +153,13 @@
 {
 	FTS *fts;
 	FTSENT *p;
-	int flags, needstat;
+	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;
+	needstat = !uid || (!fflag && !iflag && stdin_ok);
 
 	/*
 	 * If the -i option is specified, the user can skip on the pre-order
@@ -216,34 +220,56 @@
 				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;
+		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));
 
-		case FTS_W:
-			if (!undelete(p->fts_accpath) ||
-			    (fflag && errno == ENOENT))
-				continue;
-			break;
+		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;
+				}
+				break;
 
-		default:
-			if (Pflag)
-				rm_overwrite(p->fts_accpath, NULL);
-			if (!unlink(p->fts_accpath) ||
-			    (fflag && NONEXISTENT(errno)))
-				continue;
+			case FTS_W:
+				rval = undelete(p->fts_accpath);
+				if (rval == 0 && (fflag && errno == ENOENT)) {
+					if (vflag)
+						(void)printf("%s\n",
+							p->fts_path);
+					continue;
+				}
+				break;
+
+			default:
+				if (Pflag)
+					rm_overwrite(p->fts_accpath, NULL);
+				rval = unlink(p->fts_accpath);
+				if (rval == 0 || (fflag && NONEXISTENT(errno))) {
+					if (rval == 0 && vflag)
+						(void)printf("%s\n",
+							p->fts_path);
+					continue;
+				}
+			}
+			warn("%s", p->fts_path);
+			eval = 1;
 		}
-		warn("%s", p->fts_path);
-		eval = 1;
 	}
 	if (errno)
 		err(1, "fts_read");
@@ -285,19 +311,28 @@
 		}
 		if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
 			continue;
-		if (S_ISWHT(sb.st_mode))
-			rval = undelete(f);
-		else 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 == 0) {
+			if (S_ISWHT(sb.st_mode))
+				rval = undelete(f);
+			else if (S_ISDIR(sb.st_mode))
+				rval = rmdir(f);
+			else {
+				if (Pflag)
+					rm_overwrite(f, &sb);
+				rval = unlink(f);
+			}
 		}
 		if (rval && (!fflag || !NONEXISTENT(errno))) {
 			warn("%s", f);
 			eval = 1;
 		}
+		if(vflag && rval == 0) 
+			(void)printf("%s\n", f);
 	}
 }
 

--/04w6evG8XlLl3ft--