Print this page
4815 Want rm support for -v option
4816 rm does not print error messages when -f is used
@@ -18,19 +18,23 @@
*
* CDDL HEADER END
*/
/*
+ * Copyright 2014 Andrew Stormont.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
- * rm [-fiRr] file ...
+ * rm [-fiRrv] file ...
*/
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
@@ -72,12 +76,17 @@
static int rm(const char *, struct dlist *);
static int confirm(FILE *, const char *, ...);
static void memerror(void);
static int checkdir(struct dlist *, struct dlist *);
-static int errcnt;
-static boolean_t silent, interactive, recursive, ontty;
+static int errcnt = 0;
+
+static boolean_t force = B_FALSE;
+static boolean_t interactive = B_FALSE;
+static boolean_t recursive = B_FALSE;
+static boolean_t ontty = B_FALSE;
+static boolean_t verbose = B_FALSE;
static char *pathbuf;
static size_t pathbuflen = MAXPATHLEN;
static int maxfds = MAXINT;
@@ -93,28 +102,27 @@
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
#endif
(void) textdomain(TEXT_DOMAIN);
- while ((c = getopt(argc, argv, "frRi")) != EOF)
+ while ((c = getopt(argc, argv, "frRiv")) != EOF)
switch (c) {
case 'f':
- silent = B_TRUE;
-#ifdef XPG4
+ force = B_TRUE;
interactive = B_FALSE;
-#endif
break;
case 'i':
interactive = B_TRUE;
-#ifdef XPG4
- silent = B_FALSE;
-#endif
+ force = B_FALSE;
break;
case 'r':
case 'R':
recursive = B_TRUE;
break;
+ case 'v':
+ verbose = B_TRUE;
+ break;
case '?':
errflg = 1;
break;
}
@@ -130,12 +138,13 @@
optind++;
argc -= optind;
argv = &argv[optind];
- if ((argc < 1 && !silent) || errflg) {
- (void) fprintf(stderr, gettext("usage: rm [-fiRr] file ...\n"));
+ if ((argc < 1 && !force) || errflg) {
+ (void) fprintf(stderr,
+ gettext("usage: rm [-fiRrv] file ...\n"));
exit(2);
}
ontty = isatty(STDIN_FILENO) != 0;
@@ -326,15 +335,13 @@
* call, we use the global pathbuf instead of the entry argument.
*/
pushfilename(entry);
if (fstatat(caller->fd, entry, &temp, AT_SYMLINK_NOFOLLOW) != 0) {
- if (!silent) {
(void) fprintf(stderr, "rm: %s: %s\n", pathbuf,
strerror(errno));
errcnt++;
- }
return (0);
}
if (S_ISDIR(temp.st_mode)) {
/*
@@ -373,24 +380,25 @@
frame.dev = temp.st_dev;
frame.ino = temp.st_ino;
frame.flags = 0;
flag = AT_REMOVEDIR;
-#ifdef XPG4
+#ifndef SUS
/*
* XCU4 and POSIX.2: If not interactive, check to see whether
* or not directory is readable or writable and if not,
* prompt user for response.
*/
- if (ontty && !interactive && !silent &&
+ if (ontty && !interactive && !force &&
faccessat(caller->fd, entry, W_OK|X_OK, AT_EACCESS) != 0 &&
!confirm(stderr,
gettext("rm: examine files in directory %s (%s/%s)? "),
pathbuf, yesstr, nostr)) {
return (0);
}
#endif
+
if (opendirat(caller->fd, entry, &frame) == -1) {
err = errno;
if (interactive) {
/*
@@ -423,12 +431,16 @@
errcnt++;
return (0);
}
}
/* If it's empty we may still be able to rm it */
- if (unlinkat(caller->fd, entry, flag) == 0)
+ if (unlinkat(caller->fd, entry, flag) == 0) {
+ if (verbose)
+ (void) printf(gettext("removed "
+ "directory: `%s'\n"), pathbuf);
return (0);
+ }
if (interactive)
err = errno;
(void) fprintf(stderr,
interactive ?
gettext("rm: Unable to remove directory %s: %s\n") :
@@ -496,13 +508,13 @@
if (interactive) {
if (!confirm(stderr, gettext("rm: remove %s (%s/%s)? "),
pathbuf, yesstr, nostr)) {
return (0);
}
- } else if (!silent && flag == 0) {
+ } else if (!force && flag == 0) {
/*
- * If not silent, and stdin is a terminal, and there's
+ * If not force, and stdin is a terminal, and there's
* no write access, and the file isn't a symbolic link,
* ask for permission. If flag is set, then we know it's
* a directory so we skip this test as it was done above.
*
* TRANSLATION_NOTE - The following message will contain the
@@ -521,11 +533,17 @@
pathbuf, temp.st_mode & 0777, yesstr, nostr)) {
return (0);
}
}
- if (unlinkat(caller->fd, entry, flag) != 0) {
+ if (unlinkat(caller->fd, entry, flag) == 0) {
+ if (verbose)
+ (void) printf(S_ISDIR(temp.st_mode) ?
+ gettext("removed directory: `%s'\n") :
+ gettext("removed `%s'\n"), pathbuf);
+ return (0);
+ } else {
err = errno;
if (err == ENOENT)
return (0);
if (flag != 0) {
@@ -539,20 +557,15 @@
err = ENOTEMPTY;
(void) fprintf(stderr,
gettext("rm: Unable to remove directory %s:"
" %s\n"), pathbuf, strerror(err));
}
+#ifndef SUS
} else {
-#ifndef XPG4
- if (!silent || interactive) {
-#endif
-
(void) fprintf(stderr,
gettext("rm: %s not removed: %s\n"),
pathbuf, strerror(err));
-#ifndef XPG4
- }
#endif
}
errcnt++;
}
return (0);