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.
Old behaviour: rm -P /tmp/foo (foo mode 0444) would NOT overwrite foo,
but still delete it (with a warning: rm: foo: Permission denied)
New behaviour: Just the EPERM warning, but no deletion

Reviewed by:	bde
This commit is contained in:
Guido van Rooij 2003-11-10 09:40:18 +00:00
parent 5597389c40
commit f3761deee3

View File

@ -67,7 +67,7 @@ uid_t uid;
int check(char *, char *, struct stat *); int check(char *, char *, struct stat *);
void checkdot(char **); void checkdot(char **);
void rm_file(char **); void rm_file(char **);
void rm_overwrite(char *, struct stat *); int rm_overwrite(char *, struct stat *);
void rm_tree(char **); void rm_tree(char **);
void usage(void); void usage(void);
@ -139,7 +139,7 @@ main(int argc, char *argv[])
if (argc < 1) { if (argc < 1) {
if (fflag) if (fflag)
return 0; return (0);
usage(); usage();
} }
@ -271,7 +271,8 @@ rm_tree(char **argv)
default: default:
if (Pflag) if (Pflag)
rm_overwrite(p->fts_accpath, NULL); if (!rm_overwrite(p->fts_accpath, NULL))
continue;
rval = unlink(p->fts_accpath); rval = unlink(p->fts_accpath);
if (rval == 0 || (fflag && errno == ENOENT)) { if (rval == 0 || (fflag && errno == ENOENT)) {
if (rval == 0 && vflag) if (rval == 0 && vflag)
@ -337,7 +338,8 @@ rm_file(char **argv)
rval = rmdir(f); rval = rmdir(f);
else { else {
if (Pflag) if (Pflag)
rm_overwrite(f, &sb); if (!rm_overwrite(f, &sb))
continue;
rval = unlink(f); rval = unlink(f);
} }
} }
@ -361,7 +363,7 @@ rm_file(char **argv)
* System V file system). In a logging file system, you'll have to have * System V file system). In a logging file system, you'll have to have
* kernel support. * kernel support.
*/ */
void int
rm_overwrite(char *file, struct stat *sbp) rm_overwrite(char *file, struct stat *sbp)
{ {
struct stat sb; struct stat sb;
@ -377,7 +379,7 @@ rm_overwrite(char *file, struct stat *sbp)
sbp = &sb; sbp = &sb;
} }
if (!S_ISREG(sbp->st_mode)) if (!S_ISREG(sbp->st_mode))
return; return (1);
if ((fd = open(file, O_WRONLY, 0)) == -1) if ((fd = open(file, O_WRONLY, 0)) == -1)
goto err; goto err;
if (fstatfs(fd, &fsb) == -1) if (fstatfs(fd, &fsb) == -1)
@ -403,7 +405,7 @@ rm_overwrite(char *file, struct stat *sbp)
PASS(0xff); PASS(0xff);
if (!fsync(fd) && !close(fd)) { if (!fsync(fd) && !close(fd)) {
free(buf); free(buf);
return; return (1);
} }
err: eval = 1; err: eval = 1;
@ -412,6 +414,7 @@ err: eval = 1;
if (fd != -1) if (fd != -1)
close(fd); close(fd);
warn("%s", file); warn("%s", file);
return (0);
} }
@ -430,8 +433,11 @@ check(char *path, char *name, struct stat *sp)
* talking to a terminal, ask. Symbolic links are excluded * talking to a terminal, ask. Symbolic links are excluded
* because their permissions are meaningless. Check stdin_ok * because their permissions are meaningless. Check stdin_ok
* first because we may not have stat'ed the file. * 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) && (!access(name, W_OK) &&
!(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) && !(sp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
(!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid))) (!(sp->st_flags & (UF_APPEND|UF_IMMUTABLE)) || !uid)))