mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-05 12:56:08 +00:00
Allow root to delete uchg/uappnd files
This commit is contained in:
parent
3cf91c530d
commit
6b4198130e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=7798
@ -1,6 +1,9 @@
|
|||||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||||
# $Id$
|
# $Id: Makefile,v 1.2 1994/09/24 02:56:59 davidg Exp $
|
||||||
|
|
||||||
PROG= rm
|
PROG= rm
|
||||||
|
SRCS= rm.c stat_flags.c
|
||||||
|
|
||||||
|
.PATH: ${.CURDIR}/../ls
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
93
bin/rm/rm.c
93
bin/rm/rm.c
@ -30,7 +30,7 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $Id$
|
* $Id: rm.c,v 1.5 1994/09/24 02:57:02 davidg Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
@ -55,7 +55,10 @@ static char sccsid[] = "@(#)rm.c 8.5 (Berkeley) 4/18/94";
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern char *flags_to_string __P((u_long, char *));
|
||||||
|
|
||||||
int dflag, eval, fflag, iflag, Pflag, stdin_ok;
|
int dflag, eval, fflag, iflag, Pflag, stdin_ok;
|
||||||
|
uid_t uid;
|
||||||
|
|
||||||
int check __P((char *, char *, struct stat *));
|
int check __P((char *, char *, struct stat *));
|
||||||
void checkdot __P((char **));
|
void checkdot __P((char **));
|
||||||
@ -114,6 +117,7 @@ main(argc, argv)
|
|||||||
exit (eval);
|
exit (eval);
|
||||||
|
|
||||||
stdin_ok = isatty(STDIN_FILENO);
|
stdin_ok = isatty(STDIN_FILENO);
|
||||||
|
uid = geteuid();
|
||||||
|
|
||||||
if (rflag)
|
if (rflag)
|
||||||
rm_tree(argv);
|
rm_tree(argv);
|
||||||
@ -129,12 +133,13 @@ rm_tree(argv)
|
|||||||
FTS *fts;
|
FTS *fts;
|
||||||
FTSENT *p;
|
FTSENT *p;
|
||||||
int needstat;
|
int needstat;
|
||||||
|
int rval;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove a file hierarchy. If forcing removal (-f), or interactive
|
* Remove a file hierarchy. If forcing removal (-f), or interactive
|
||||||
* (-i) or can't ask anyway (stdin_ok), don't stat the file.
|
* (-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
|
* 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);
|
(void)fts_set(fts, p, FTS_SKIP);
|
||||||
p->fts_number = SKIPPED;
|
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;
|
continue;
|
||||||
case FTS_DP:
|
case FTS_DP:
|
||||||
/* Post-order: see if user skipped. */
|
/* Post-order: see if user skipped. */
|
||||||
@ -188,25 +199,34 @@ rm_tree(argv)
|
|||||||
!check(p->fts_path, p->fts_accpath, p->fts_statp))
|
!check(p->fts_path, p->fts_accpath, p->fts_statp))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
rval = 0;
|
||||||
* If we can't read or search the directory, may still be
|
if (!uid &&
|
||||||
* able to remove it. Don't print out the un{read,search}able
|
(p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||||
* message unless the remove fails.
|
!(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
|
||||||
*/
|
rval = chflags(p->fts_accpath,
|
||||||
if (p->fts_info == FTS_DP || p->fts_info == FTS_DNR) {
|
p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
|
||||||
if (!rmdir(p->fts_accpath))
|
if (!rval) {
|
||||||
continue;
|
/*
|
||||||
if (errno == ENOENT) {
|
* If we can't read or search the directory, may still be
|
||||||
if (fflag)
|
* 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;
|
continue;
|
||||||
} else if (p->fts_info != FTS_DP)
|
if (errno == ENOENT) {
|
||||||
warnx("%s: unable to read", p->fts_path);
|
if (fflag)
|
||||||
} else {
|
continue;
|
||||||
if (Pflag)
|
} else if (p->fts_info != FTS_DP)
|
||||||
rm_overwrite(p->fts_accpath, NULL);
|
warnx("%s: unable to read", p->fts_path);
|
||||||
if (!unlink(p->fts_accpath) || (fflag && errno == ENOENT))
|
} else {
|
||||||
continue;
|
if (Pflag)
|
||||||
|
rm_overwrite(p->fts_accpath, NULL);
|
||||||
|
if (!unlink(p->fts_accpath) || (fflag && errno == ENOENT))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
err:
|
||||||
warn("%s", p->fts_path);
|
warn("%s", p->fts_path);
|
||||||
eval = 1;
|
eval = 1;
|
||||||
}
|
}
|
||||||
@ -243,12 +263,19 @@ rm_file(argv)
|
|||||||
}
|
}
|
||||||
if (!fflag && !check(f, f, &sb))
|
if (!fflag && !check(f, f, &sb))
|
||||||
continue;
|
continue;
|
||||||
if (S_ISDIR(sb.st_mode))
|
rval = 0;
|
||||||
rval = rmdir(f);
|
if (!uid &&
|
||||||
else {
|
(sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||||
if (Pflag)
|
!(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
|
||||||
rm_overwrite(f, &sb);
|
rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
|
||||||
rval = unlink(f);
|
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)) {
|
if (rval && (!fflag || errno != ENOENT)) {
|
||||||
warn("%s", f);
|
warn("%s", f);
|
||||||
@ -318,7 +345,7 @@ check(path, name, sp)
|
|||||||
struct stat *sp;
|
struct stat *sp;
|
||||||
{
|
{
|
||||||
int ch, first;
|
int ch, first;
|
||||||
char modep[15];
|
char modep[15], flagsp[128];
|
||||||
|
|
||||||
/* Check -i first. */
|
/* Check -i first. */
|
||||||
if (iflag)
|
if (iflag)
|
||||||
@ -330,13 +357,21 @@ check(path, name, sp)
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
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);
|
return (1);
|
||||||
strmode(sp->st_mode, modep);
|
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] == ' ' ? "" : " ",
|
modep + 1, modep[9] == ' ' ? "" : " ",
|
||||||
user_from_uid(sp->st_uid, 0),
|
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);
|
(void)fflush(stderr);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user