From 8dc92fbd6cb4f5ac8e5297db06028cee535200d8 Mon Sep 17 00:00:00 2001 From: FRIGN Date: Mon, 2 Mar 2015 21:43:56 +0100 Subject: [PATCH] Refactor enmasse() and recurse() to reflect depth The HLP-changes to sbase have been a great addition of functionality, but they kind of "polluted" the enmasse() and recurse() prototypes. As this will come in handy in the future, knowing at which "depth" you are inside a recursing function is an important functionality. Instead of having a special HLP-flag passed to enmasse, each sub- function needs to provide it on its own and can calculate results based on the current depth (for instance, 'H' implies 'P' at depth > 0). A special case is recurse(), because it actually depends on the follow-type. A new flag "recurse_follow" brings consistency into what used to be spread across different naming conventions (fflag, HLP_flag, ...). This also fixes numerous bugs with the behaviour of HLP in the tools using it. --- chgrp.c | 27 +++++++++++++++------------ chmod.c | 9 ++++----- chown.c | 25 ++++++++++++++----------- cp.c | 2 +- fs.h | 2 +- libutil/cp.c | 10 ++++++---- libutil/enmasse.c | 6 +++--- libutil/fnck.c | 4 ++-- libutil/recurse.c | 18 +++++++++++------- libutil/rm.c | 4 ++-- mv.c | 7 ++++--- tar.c | 11 +++++------ util.h | 5 +++-- 13 files changed, 71 insertions(+), 59 deletions(-) diff --git a/chgrp.c b/chgrp.c index 0d55ce8..0ca2466 100644 --- a/chgrp.c +++ b/chgrp.c @@ -10,20 +10,19 @@ static int gid; static int status; static int Rflag; -static int fflag = 'P'; static struct stat st; -static char *chown_f_name = "chown"; -static int (*chown_f)(const char *, uid_t, gid_t) = chown; +static char *chownf_name = "chown"; +static int (*chownf)(const char *, uid_t, gid_t) = chown; static void -chgrp(const char *path, int fflag) +chgrp(const char *path, int depth) { - if (chown_f(path, st.st_uid, gid) < 0) { - weprintf("%s %s:", chown_f_name, path); + if (chownf(path, st.st_uid, gid) < 0) { + weprintf("%s %s:", chownf_name, path); status = 1; } if (Rflag) - recurse(path, chgrp, fflag); + recurse(path, chgrp, depth); } static void @@ -39,8 +38,8 @@ main(int argc, char *argv[]) ARGBEGIN { case 'h': - chown_f_name = "lchown"; - chown_f = lchown; + chownf_name = "lchown"; + chownf = lchown; break; case 'R': Rflag = 1; @@ -48,14 +47,18 @@ main(int argc, char *argv[]) case 'H': case 'L': case 'P': - fflag = ARGC(); + recurse_follow = ARGC(); break; default: usage(); } ARGEND; - if (argc < 2 || (chown_f == lchown && Rflag)) + if (argc < 2) usage(); + if (recurse_follow == 'P') { + chownf_name = "lchown"; + chownf = lchown; + } errno = 0; gr = getgrnam(argv[0]); @@ -73,7 +76,7 @@ main(int argc, char *argv[]) status = 1; continue; } - chgrp(*argv, fflag); + chgrp(*argv, 0); } return status; } diff --git a/chmod.c b/chmod.c index ac94a53..a29b04a 100644 --- a/chmod.c +++ b/chmod.c @@ -4,13 +4,12 @@ #include "util.h" static int Rflag = 0; -static int fflag = 'P'; static char *modestr = ""; static mode_t mask = 0; static int ret = 0; void -chmodr(const char *path, int fflag) +chmodr(const char *path, int depth) { struct stat st; mode_t m; @@ -27,7 +26,7 @@ chmodr(const char *path, int fflag) ret = 1; } if (Rflag) - recurse(path, chmodr, fflag); + recurse(path, chmodr, depth); } static void @@ -50,7 +49,7 @@ main(int argc, char *argv[]) case 'H': case 'L': case 'P': - fflag = argv[i][1]; + recurse_follow = argv[i][1]; break; case 'r': case 'w': case 'x': case 's': case 't': /* @@ -71,7 +70,7 @@ done: usage(); for (++i; i < argc; i++) - chmodr(argv[i], fflag); + chmodr(argv[i], 0); return ret; } diff --git a/chown.c b/chown.c index 332cb62..cd76f9c 100644 --- a/chown.c +++ b/chown.c @@ -9,22 +9,21 @@ #include "util.h" static int rflag = 0; -static int HLPflag = 'P'; static uid_t uid = -1; static gid_t gid = -1; static int ret = 0; -static char *chown_f_name = "chown"; -static int (*chown_f)(const char *, uid_t, gid_t) = chown; +static char *chownf_name = "chown"; +static int (*chownf)(const char *, uid_t, gid_t) = chown; static void -chownpwgr(const char *path, int HLPflag) +chownpwgr(const char *path, int depth) { - if (chown_f(path, uid, gid) < 0) { - weprintf("%s %s:", chown_f_name, path); + if (chownf(path, uid, gid) < 0) { + weprintf("%s %s:", chownf_name, path); ret = 1; } if (rflag) - recurse(path, chownpwgr, HLPflag); + recurse(path, chownpwgr, depth); } static void @@ -42,8 +41,8 @@ main(int argc, char *argv[]) ARGBEGIN { case 'h': - chown_f_name = "lchown"; - chown_f = lchown; + chownf_name = "lchown"; + chownf = lchown; break; case 'r': case 'R': @@ -52,7 +51,7 @@ main(int argc, char *argv[]) case 'H': case 'L': case 'P': - HLPflag = ARGC(); + recurse_follow = ARGC(); break; default: usage(); @@ -60,6 +59,10 @@ main(int argc, char *argv[]) if (argc == 0) usage(); + if (recurse_follow == 'P') { + chownf_name = "lchown"; + chownf = lchown; + } owner = argv[0]; argv++; @@ -94,7 +97,7 @@ main(int argc, char *argv[]) } } for (; argc > 0; argc--, argv++) - chownpwgr(argv[0], HLPflag); + chownpwgr(argv[0], 0); return ret; } diff --git a/cp.c b/cp.c index cc976d1..4bba1b5 100644 --- a/cp.c +++ b/cp.c @@ -51,7 +51,7 @@ main(int argc, char *argv[]) if (!S_ISDIR(st.st_mode)) eprintf("%s: not a directory\n", argv[argc - 1]); } - enmasse(argc, argv, cp, cp_HLPflag); + enmasse(argc, argv, cp); return cp_status; } diff --git a/fs.h b/fs.h index 7c59515..53cc39a 100644 --- a/fs.h +++ b/fs.h @@ -11,5 +11,5 @@ extern int rm_fflag; extern int rm_rflag; extern int rm_status; -int cp(const char *, const char *, char); +int cp(const char *, const char *, int); void rm(const char *, int); diff --git a/libutil/cp.c b/libutil/cp.c index 9145590..e58716e 100644 --- a/libutil/cp.c +++ b/libutil/cp.c @@ -24,7 +24,7 @@ int cp_status = 0; int cp_HLPflag = 'L'; int -cp(const char *s1, const char *s2, char ff) +cp(const char *s1, const char *s2, int depth) { FILE *f1, *f2; char *ns1, *ns2; @@ -39,9 +39,11 @@ cp(const char *s1, const char *s2, char ff) if (cp_vflag) printf("'%s' -> '%s'\n", s1, s2); - r = ff == 'P' ? lstat(s1, &st) : stat(s1, &st); + r = (cp_HLPflag == 'P' || (cp_HLPflag == 'H' && depth > 0)) ? + lstat(s1, &st) : stat(s1, &st); if (r < 0) { - weprintf("%s %s:", ff == 'P' ? "lstat" : "stat", s1); + weprintf("%s %s:", (cp_HLPflag == 'P' || + (cp_HLPflag == 'H' && depth > 0)) ? "lstat" : "stat", s1); cp_status = 1; return 0; } @@ -83,7 +85,7 @@ cp(const char *s1, const char *s2, char ff) eprintf("%s/%s: filename too long\n", s2, d->d_name); } - fnck(ns1, ns2, cp, ff == 'H' ? 'P' : ff); + fnck(ns1, ns2, cp, depth + 1); } } closedir(dp); diff --git a/libutil/enmasse.c b/libutil/enmasse.c index 6281b79..24af279 100644 --- a/libutil/enmasse.c +++ b/libutil/enmasse.c @@ -9,7 +9,7 @@ #include "../util.h" void -enmasse(int argc, char *argv[], int (*fn)(const char *, const char *, char), char ff) +enmasse(int argc, char *argv[], int (*fn)(const char *, const char *, int)) { char *buf, *dir; int i, len; @@ -18,7 +18,7 @@ enmasse(int argc, char *argv[], int (*fn)(const char *, const char *, char), cha size_t dlen; if (argc == 2 && !(stat(argv[1], &st) == 0 && S_ISDIR(st.st_mode))) { - fnck(argv[0], argv[1], fn, ff); + fnck(argv[0], argv[1], fn, 0); return; } else { dir = (argc == 1) ? "." : argv[--argc]; @@ -35,7 +35,7 @@ enmasse(int argc, char *argv[], int (*fn)(const char *, const char *, char), cha eprintf("%s/%s: filename too long\n", dir, basename(argv[i])); } - fnck(argv[i], buf, fn, ff); + fnck(argv[i], buf, fn, 0); } free(buf); } diff --git a/libutil/fnck.c b/libutil/fnck.c index 8afc4b1..92da1f4 100644 --- a/libutil/fnck.c +++ b/libutil/fnck.c @@ -5,7 +5,7 @@ void fnck(const char *a, const char *b, - int (*fn)(const char *, const char *, char), char ff) + int (*fn)(const char *, const char *, int), int depth) { struct stat sta, stb; @@ -16,6 +16,6 @@ fnck(const char *a, const char *b, eprintf("%s -> %s: same file\n", a, b); } - if (fn(a, b, ff) < 0) + if (fn(a, b, depth) < 0) eprintf("%s -> %s:", a, b); } diff --git a/libutil/recurse.c b/libutil/recurse.c index e4ab2e0..f30f160 100644 --- a/libutil/recurse.c +++ b/libutil/recurse.c @@ -10,25 +10,29 @@ #include "../util.h" +int recurse_follow = 'P'; + void -recurse(const char *path, void (*fn)(const char *, int), int follow) +recurse(const char *path, void (*fn)(const char *, int), int depth) { char buf[PATH_MAX]; struct dirent *d; struct stat lst, st; DIR *dp; - if (lstat(path, &lst) < 0 || stat(path, &st) < 0 || - !(S_ISDIR(lst.st_mode) || - (follow != 'P' && S_ISLNK(lst.st_mode) && S_ISDIR(st.st_mode)))) + if (lstat(path, &lst) < 0) + eprintf("lstat %s:", path); + if (stat(path, &st) < 0) + eprintf("stat %s:", path); + if (!S_ISDIR(lst.st_mode) && !(S_ISLNK(lst.st_mode) && S_ISDIR(st.st_mode) && + !(recurse_follow == 'P' || (recurse_follow == 'H' && depth > 0)))) return; if (!(dp = opendir(path))) eprintf("opendir %s:", path); while ((d = readdir(dp))) { - if (strcmp(d->d_name, ".") == 0 || - strcmp(d->d_name, "..") == 0) + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) continue; if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) eprintf("path too long\n"); @@ -37,7 +41,7 @@ recurse(const char *path, void (*fn)(const char *, int), int follow) eprintf("path too long\n"); if (strlcat(buf, d->d_name, sizeof(buf)) >= sizeof(buf)) eprintf("path too long\n"); - fn(buf, follow == 'H' ? 'P' : follow); + fn(buf, depth + 1); } closedir(dp); diff --git a/libutil/rm.c b/libutil/rm.c index 45e972c..60c97c1 100644 --- a/libutil/rm.c +++ b/libutil/rm.c @@ -10,10 +10,10 @@ int rm_rflag = 0; int rm_status = 0; void -rm(const char *path, int flag) +rm(const char *path, int depth) { if (rm_rflag) - recurse(path, rm, 'P'); + recurse(path, rm, depth); if (remove(path) < 0) { if (!rm_fflag) weprintf("remove %s:", path); diff --git a/mv.c b/mv.c index 7481597..b46981c 100644 --- a/mv.c +++ b/mv.c @@ -10,14 +10,15 @@ static int mv_status = 0; static int -mv(const char *s1, const char *s2, char ff) +mv(const char *s1, const char *s2, int depth) { if (rename(s1, s2) == 0) return (mv_status = 0); if (errno == EXDEV) { cp_aflag = cp_rflag = cp_pflag = 1; + cp_HLPflag = 'P'; rm_rflag = 1; - cp(s1, s2, ff); + cp(s1, s2, depth); rm(s1, 0); return (mv_status = cp_status || rm_status); } @@ -48,7 +49,7 @@ main(int argc, char *argv[]) if (argc > 3 && !(stat(argv[argc-1], &st) == 0 && S_ISDIR(st.st_mode))) eprintf("%s: not a directory\n", argv[argc-1]); - enmasse(argc, &argv[0], mv, 'P'); + enmasse(argc, argv, mv); return mv_status; } diff --git a/tar.c b/tar.c index 2057005..bdf34b8 100644 --- a/tar.c +++ b/tar.c @@ -42,7 +42,6 @@ static ino_t tarinode; static dev_t tardev; static int mflag; -static int fflag = 'P'; static char filtermode; static FILE * @@ -234,14 +233,14 @@ print(char * fname, int l, char b[BLKSIZ]) } static void -c(const char * path, int fflag) +c(const char *path, int depth) { archive(path); - recurse(path, c, fflag); + recurse(path, c, depth); } static void -xt(int (*fn)(char*, int, char[BLKSIZ])) +xt(int (*fn)(char *, int, char[BLKSIZ])) { char b[BLKSIZ], fname[257], *s; struct header *h = (void*)b; @@ -293,7 +292,7 @@ main(int argc, char *argv[]) filtermode = ARGC(); break; case 'h': - fflag = 'L'; + recurse_follow = 'L'; break; default: usage(); @@ -316,7 +315,7 @@ main(int argc, char *argv[]) tarfile = stdout; } chdir(dir); - c(argv[0], fflag); + c(argv[0], 0); break; case 't': case 'x': diff --git a/util.h b/util.h index a107a07..2fec2d9 100644 --- a/util.h +++ b/util.h @@ -56,12 +56,13 @@ int enregcomp(int, regex_t *, const char *, int); int eregcomp(regex_t *, const char *, int); /* misc */ -void enmasse(int, char **, int (*)(const char *, const char *, char), char); -void fnck(const char *, const char *, int (*)(const char *, const char *, char), char); +void enmasse(int, char **, int (*)(const char *, const char *, int)); +void fnck(const char *, const char *, int (*)(const char *, const char *, int), int); mode_t getumask(void); char *humansize(double); mode_t parsemode(const char *, mode_t, mode_t); void putword(const char *); +extern int recurse_follow; void recurse(const char *, void (*)(const char *, int), int); #undef strtonum long long strtonum(const char *, long long, long long, const char **);