mirror of
git://git.suckless.org/sbase
synced 2026-01-26 05:37:54 +00:00
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:
parent
948e516190
commit
0df8cdc12d
2
README
2
README
@ -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
2
fs.h
@ -24,6 +24,8 @@ enum {
|
||||
SAMEDEV = 1 << 0,
|
||||
DIRFIRST = 1 << 1,
|
||||
SILENT = 1 << 2,
|
||||
CONFIRM = 1 << 3,
|
||||
IGNORE = 1 << 4,
|
||||
};
|
||||
|
||||
extern int cp_aflag;
|
||||
|
||||
43
libutil/rm.c
43
libutil/rm.c
@ -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
2
mv.c
@ -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
9
rm.c
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user