sbase

suckless unix tools
git clone git://git.suckless.org/sbase
Log | Files | Refs | README | LICENSE

commit e14d9412f8397f5d27914386210f50a320e86fac
parent e2edbdcb87c89d69ab8cbf1a753ead75ccea5949
Author: FRIGN <dev@frign.de>
Date:   Sat, 18 Apr 2015 21:24:17 +0200

Properly handle recursion in recurse()

The restructuring of recurse() in the last few weeks actually broke
the recursion-flags in different tools.
As a long-term goal, the recursor should have a field "maxdepth"
which should be "1" for the non-Rflag-case. "0" stands for unlimited.

Diffstat:
Mchgrp.c | 7+++----
Mchmod.c | 7+++----
Mchown.c | 7+++----
Mfs.h | 1+
Mlibutil/recurse.c | 2+-
Mlibutil/rm.c | 15+++++++++++----
Mmv.c | 1-
Mrm.c | 4++--
8 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/chgrp.c b/chgrp.c @@ -9,7 +9,6 @@ #include "util.h" static int hflag = 0; -static int Rflag = 0; static gid_t gid = -1; static int ret = 0; @@ -30,7 +29,7 @@ chgrp(const char *path, struct stat *st, void *data, struct recursor *r) if (st && chownf(path, st->st_uid, gid) < 0) { weprintf("%s %s:", chownf_name, path); ret = 1; - } else if (Rflag && st && S_ISDIR(st->st_mode)) { + } else if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { recurse(path, NULL, r); } } @@ -45,14 +44,14 @@ int main(int argc, char *argv[]) { struct group *gr; - struct recursor r = { .fn = chgrp, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0 }; + struct recursor r = { .fn = chgrp, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS }; ARGBEGIN { case 'h': hflag = 1; break; case 'R': - Rflag = 1; + r.flags &= ~NODIRS; break; case 'H': case 'L': diff --git a/chmod.c b/chmod.c @@ -4,7 +4,6 @@ #include "fs.h" #include "util.h" -static int Rflag = 0; static char *modestr = ""; static mode_t mask = 0; static int ret = 0; @@ -18,7 +17,7 @@ chmodr(const char *path, struct stat *st, void *data, struct recursor *r) if (chmod(path, m) < 0) { weprintf("chmod %s:", path); ret = 1; - } else if (Rflag && st && S_ISDIR(st->st_mode)) { + } else if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { recurse(path, NULL, r); } } @@ -32,7 +31,7 @@ usage(void) int main(int argc, char *argv[]) { - struct recursor r = { .fn = chmodr, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0}; + struct recursor r = { .fn = chmodr, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS}; size_t i; argv0 = argv[0], argc--, argv++; @@ -43,7 +42,7 @@ main(int argc, char *argv[]) for (i = 1; (*argv)[i]; i++) { switch ((*argv)[i]) { case 'R': - Rflag = 1; + r.flags &= ~NODIRS; break; case 'H': case 'L': diff --git a/chown.c b/chown.c @@ -11,7 +11,6 @@ #include "util.h" static int hflag = 0; -static int Rflag = 0; static uid_t uid = -1; static gid_t gid = -1; static int ret = 0; @@ -33,7 +32,7 @@ chownpwgr(const char *path, struct stat *st, void *data, struct recursor *r) if (chownf(path, uid, gid) < 0) { weprintf("%s %s:", chownf_name, path); ret = 1; - } else if (Rflag && st && S_ISDIR(st->st_mode)) { + } else if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { recurse(path, NULL, r); } } @@ -49,7 +48,7 @@ main(int argc, char *argv[]) { struct group *gr; struct passwd *pw; - struct recursor r = { .fn = chownpwgr, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0}; + struct recursor r = { .fn = chownpwgr, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS}; char *owner, *group; ARGBEGIN { @@ -58,7 +57,7 @@ main(int argc, char *argv[]) break; case 'r': case 'R': - Rflag = 1; + r.flags &= ~NODIRS; break; case 'H': case 'L': diff --git a/fs.h b/fs.h @@ -19,6 +19,7 @@ struct recursor { enum { SAMEDEV = 1 << 0, DIRFIRST = 1 << 1, + NODIRS = 1 << 2, }; extern int cp_aflag; diff --git a/libutil/recurse.c b/libutil/recurse.c @@ -37,7 +37,7 @@ recurse(const char *path, void *data, struct recursor *r) recurse_status = 1; return; } - if (!S_ISDIR(st.st_mode)) { + if (!S_ISDIR(st.st_mode) || (S_ISDIR(st.st_mode) && (r->flags & NODIRS))) { (r->fn)(path, &st, data, r); return; } diff --git a/libutil/rm.c b/libutil/rm.c @@ -3,22 +3,29 @@ #include <errno.h> #include <stdio.h> +#include <unistd.h> #include "../fs.h" #include "../util.h" int rm_fflag = 0; -int rm_rflag = 0; int rm_status = 0; void rm(const char *path, struct stat *st, void *data, struct recursor *r) { - if (rm_rflag && st && S_ISDIR(st->st_mode)) + if (!(r->flags & NODIRS) && st && S_ISDIR(st->st_mode)) { recurse(path, NULL, r); - if (remove(path) < 0) { + + if (rmdir(path) < 0) { + if (!rm_fflag) + weprintf("rmdir %s:", path); + if (!(rm_fflag && errno == ENOENT)) + rm_status = 1; + } + } else if (unlink(path) < 0) { if (!rm_fflag) - weprintf("remove %s:", path); + weprintf("unlink %s:", path); if (!(rm_fflag && errno == ENOENT)) rm_status = 1; } diff --git a/mv.c b/mv.c @@ -19,7 +19,6 @@ mv(const char *s1, const char *s2, int depth) if (errno == EXDEV) { cp_aflag = cp_rflag = cp_pflag = 1; cp_follow = 'P'; - rm_rflag = 1; cp(s1, s2, depth); rm(s1, NULL, NULL, &r); return (mv_status = cp_status || rm_status); diff --git a/rm.c b/rm.c @@ -11,7 +11,7 @@ usage(void) int main(int argc, char *argv[]) { - struct recursor r = { .fn = rm, .hist = NULL, .depth = 0, .follow = 'P', .flags = 0}; + struct recursor r = { .fn = rm, .hist = NULL, .depth = 0, .follow = 'P', .flags = NODIRS }; ARGBEGIN { case 'f': @@ -19,7 +19,7 @@ main(int argc, char *argv[]) break; case 'R': case 'r': - rm_rflag = 1; + r.flags &= ~NODIRS; break; default: usage();