rm(1) sync
Liam J. Foy
liamfoy at sepulcrum.org
Sat Nov 6 04:50:38 PST 2004
Hey Guys,
The following patch syncs our rm(1) with FreeBSD. The commit log on
the patch will describe it. If there are any problems, please post back with
them. Everything looks ok to me, but as you all know things slip. If no
objections are recieved, it will be committed sometime tomorrow or late
tonight.
Sync with FreeBSD rm(1) with my modifications. Some things have been
left out of this sync for time being.
- Fix the leakage of a file descriptor in rm_overwrite for non-fatal
errors(this is for rm -P).
- Fix the fatal malloc() error message.
- When the P flag is set (i.e. Overwrite regular files before deleting them),
do only unlink the file if we could indeed overwrite the file. See
http://www.freebsd.org/cgi/cvsweb.cgi/src/bin/rm/rm.c?rev=1.45&content-type=text/x-cvsweb-markup
for more details.
- Fix poor wording in comment.
- When fts_read() cannot stat the file, it can't be unlinked. At
that case, don't display error message when -f flag is used.
- Kindly let the user know rm(1) could not overwrite non-regular
files and continue to unlink.
- Static functions.
- Constify rw_overwrite() and check().
Index: rm.c
===================================================================
RCS file: /home/dcvs/src/bin/rm/rm.c,v
retrieving revision 1.8
diff -u -r1.8 rm.c
--- rm.c 18 Oct 2004 17:38:52 -0000 1.8
+++ rm.c 6 Nov 2004 10:48:51 -0000
@@ -54,13 +54,13 @@
int rflag, Iflag;
uid_t uid;
-int check(char *, char *, struct stat *);
-int check2(char **);
-void checkdot(char **);
-void rm_file(char **);
-void rm_overwrite(char *, struct stat *);
-void rm_tree(char **);
-void usage(void);
+static int check(const char *, const char *, struct stat *);
+static int check2(char **);
+static void checkdot(char **);
+static void rm_file(char **);
+static int rm_overwrite(const char *, struct stat *);
+static void rm_tree(char **);
+static void usage(void);
/*
* rm --
@@ -156,7 +156,7 @@
exit (eval);
}
-void
+static void
rm_tree(char **argv)
{
FTS *fts;
@@ -196,10 +196,10 @@
case FTS_ERR:
errx(1, "%s: %s", p->fts_path, strerror(p->fts_errno));
case FTS_NS:
- /*
- * FTS_NS: assume that if can't stat the file, it
- * can't be unlinked.
- */
+ /*
+ * Assume that since fts_read() couldn't stat
+ * the file, it can't be unlinked.
+ */
if (!needstat)
break;
if (!fflag || p->fts_errno != ENOENT) {
@@ -267,9 +267,18 @@
}
break;
+ case FTS_NS:
+ /*
+ * Assume that since fts_read() couldn't stat
+ * the file, it can't be unlinked.
+ */
+ if (fflag)
+ continue;
+ /* FALLTHROUGH */
default:
if (Pflag)
- rm_overwrite(p->fts_accpath, NULL);
+ if (!rm_overwrite(p->fts_accpath, NULL))
+ continue;
rval = unlink(p->fts_accpath);
if (rval == 0 || (fflag && errno == ENOENT)) {
if (rval == 0 && vflag)
@@ -287,7 +296,7 @@
err(1, "fts_read");
}
-void
+static void
rm_file(char **argv)
{
struct stat sb;
@@ -335,7 +344,8 @@
rval = rmdir(f);
else {
if (Pflag)
- rm_overwrite(f, &sb);
+ if (!rm_overwrite(f, &sb))
+ continue;
rval = unlink(f);
}
}
@@ -359,7 +369,7 @@
* System V filesystem). In a logging filesystem, you'll have to have
* kernel support.
*/
-void
+static int
rm_overwrite(const char *file, struct stat *sbp)
{
struct stat sb;
@@ -374,15 +384,17 @@
goto err;
sbp = &sb;
}
- if (!S_ISREG(sbp->st_mode))
- return;
+ if (!S_ISREG(sbp->st_mode)) {
+ warnx("%s: cannot overwrite a non-regular file", file);
+ return (1);
+ }
if ((fd = open(file, O_WRONLY, 0)) == -1)
goto err;
if (fstatfs(fd, &fsb) == -1)
goto err;
bsize = MAX(fsb.f_iosize, 1024);
if ((buf = malloc(bsize)) == NULL)
- err(1, "malloc");
+ err(1, "%s malloc failed", file);
#define PASS(byte) { \
memset(buf, byte, bsize); \
@@ -401,18 +413,21 @@
PASS(0xff);
if (!fsync(fd) && !close(fd)) {
free(buf);
- return;
+ return (1);
}
err: eval = 1;
if (buf)
free(buf);
+ if (fd != -1)
+ close(fd);
warn("%s", file);
+ return (0);
}
-int
-check(char *path, char *name, struct stat *sp)
+static int
+check(const char *path, const char *name, struct stat *sp)
{
int ch, first;
char modep[15], *flagsp;
@@ -426,8 +441,11 @@
* talking to a terminal, ask. Symbolic links are excluded
* because their permissions are meaningless. Check stdin_ok
* first because we may not have stat'ed the file.
+ * Also skip this check if the -P option was specified because
+ * we will not be able to overwrite file contents and will
+ * barf later.
*/
- if (!stdin_ok || S_ISLNK(sp->st_mode) ||
+ if (!stdin_ok || S_ISLNK(sp->st_mode) || Pflag ||
(!access(name, W_OK) &&
!(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
(!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid)))
@@ -451,7 +469,7 @@
return (first == 'y' || first == 'Y');
}
-int
+static int
check2(char **argv)
{
struct stat st;
@@ -502,7 +520,7 @@
}
#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
-void
+static void
checkdot(char **argv)
{
char *p, **save, **t;
@@ -526,7 +544,7 @@
}
}
-void
+static void
usage(void)
{
--
- Liam J. Foy
liamfoy at xxxxxxxxxxxxx
More information about the Kernel
mailing list