rm: Add -i and cleanup rm()

POSIX mandates that if the input of rm is a tty and it does not have
write rights over a file/dir then it should ask for confirmation, in
the same way that is done with the -i flag. To accomodate both things
the code has been rearrenged a bit to have only one case instead of
having two. Also, this rework adds the error message when a directory
is removed without a -r flag.
This commit is contained in:
Roberto E. Vargas Caballero 2025-04-23 22:12:52 +02:00
parent 948e516190
commit 0df8cdc12d
5 changed files with 40 additions and 18 deletions

2
README
View File

@ -102,7 +102,7 @@ The following tools are implemented:
0=*|x readlink .
0=*|o renice .
0#* x rev .
0=*|o rm (-i)
0=*|o rm .
0=*|o rmdir .
# sed .
0=*|x seq .

2
fs.h
View File

@ -24,6 +24,8 @@ enum {
SAMEDEV = 1 << 0,
DIRFIRST = 1 << 1,
SILENT = 1 << 2,
CONFIRM = 1 << 3,
IGNORE = 1 << 4,
};
extern int cp_aflag;

View File

@ -14,19 +14,36 @@ int rm_status = 0;
void
rm(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r)
{
if (!r->maxdepth && S_ISDIR(st->st_mode)) {
recurse(dirfd, name, NULL, r);
int quiet, ask, write, flags, ignore;
if (unlinkat(dirfd, name, AT_REMOVEDIR) < 0) {
if (!(r->flags & SILENT))
weprintf("rmdir %s:", r->path);
if (!((r->flags & SILENT) && errno == ENOENT))
rm_status = 1;
}
} else if (unlinkat(dirfd, name, 0) < 0) {
if (!(r->flags & SILENT))
weprintf("unlink %s:", r->path);
if (!((r->flags & SILENT) && errno == ENOENT))
rm_status = 1;
ignore = r->flags & IGNORE;
quiet = r->flags & SILENT;
ask = r->flags & CONFIRM;
write = faccessat(dirfd, name, W_OK, 0) == 0;
flags = 0;
if (S_ISDIR(st->st_mode) && r->maxdepth) {
errno = EISDIR;
goto err;
}
if (!quiet && (!write && isatty(0) || ask)) {
if (!confirm("remove file '%s'", r->path));
return;
}
if (S_ISDIR(st->st_mode)) {
flags = AT_REMOVEDIR;
recurse(dirfd, name, NULL, r);
}
if (unlinkat(dirfd, name, flags) < 0)
goto err;
return;
err:
if (!ignore) {
weprintf("cannot remove '%s':", r->path);
rm_status = 1;
}
}

2
mv.c
View File

@ -13,7 +13,7 @@ static int mv_status = 0;
static int
mv(const char *s1, const char *s2, int depth)
{
struct recursor r = { .fn = rm, .follow = 'P' };
struct recursor r = { .fn = rm, .follow = 'P', .flags = SILENT };
if (!rename(s1, s2))
return 0;

9
rm.c
View File

@ -7,7 +7,7 @@
static void
usage(void)
{
eprintf("usage: %s [-f] [-Rr] file ...\n", argv0);
eprintf("usage: %s [-f] [-iRr] file ...\n", argv0);
}
int
@ -17,7 +17,10 @@ main(int argc, char *argv[])
ARGBEGIN {
case 'f':
r.flags |= SILENT;
r.flags |= SILENT | IGNORE;
break;
case 'i':
r.flags |= CONFIRM;
break;
case 'R':
case 'r':
@ -28,7 +31,7 @@ main(int argc, char *argv[])
} ARGEND
if (!argc) {
if (!(r.flags & SILENT))
if (!(r.flags & IGNORE))
usage();
else
return 0;