From d6bab3f610f1626854e4075e38a3635423121c31 Mon Sep 17 00:00:00 2001 From: Tai Chi Minh Ralph Eastwood Date: Mon, 9 Feb 2015 19:53:24 +0000 Subject: [PATCH 1/3] recurse: add symlink derefencing flags -H and -L --- chgrp.c | 12 +++++++++--- chmod.c | 6 +++--- chown.c | 12 +++++++++--- libutil/recurse.c | 10 ++++++---- libutil/rm.c | 2 +- tar.c | 12 ++++++++---- util.h | 2 +- 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/chgrp.c b/chgrp.c index ede0233..27027dd 100644 --- a/chgrp.c +++ b/chgrp.c @@ -10,19 +10,20 @@ static int gid; static int status; static int rflag; +static char fflag = 'P'; static struct stat st; static char *chown_f_name = "chown"; static int (*chown_f)(const char *, uid_t, gid_t) = chown; static void -chgrp(const char *path) +chgrp(const char *path, char fflag) { if (chown_f(path, st.st_uid, gid) < 0) { weprintf("%s %s:", chown_f_name, path); status = 1; } if (rflag) - recurse(path, chgrp); + recurse(path, chgrp, fflag); } static void @@ -44,6 +45,11 @@ main(int argc, char *argv[]) case 'R': rflag = 1; break; + case 'H': + case 'L': + case 'P': + fflag = ARGC(); + break; default: usage(); } ARGEND; @@ -67,7 +73,7 @@ main(int argc, char *argv[]) status = 1; continue; } - chgrp(*argv); + chgrp(*argv, fflag); } return status; } diff --git a/chmod.c b/chmod.c index 9fbdf4e..e5074be 100644 --- a/chmod.c +++ b/chmod.c @@ -9,7 +9,7 @@ static mode_t mask = 0; static int ret = 0; void -chmodr(const char *path) +chmodr(const char *path, char fflag) { struct stat st; mode_t m; @@ -26,7 +26,7 @@ chmodr(const char *path) ret = 1; } if (rflag) - recurse(path, chmodr); + recurse(path, chmodr, fflag); } static void @@ -65,7 +65,7 @@ done: usage(); for (++i; i < argc; i++) - chmodr(argv[i]); + chmodr(argv[i], 'P'); return ret; } diff --git a/chown.c b/chown.c index 575af43..228d4a2 100644 --- a/chown.c +++ b/chown.c @@ -9,6 +9,7 @@ #include "util.h" static int rflag = 0; +static int fflag = 'P'; static uid_t uid = -1; static gid_t gid = -1; static int ret = 0; @@ -16,14 +17,14 @@ static char *chown_f_name = "chown"; static int (*chown_f)(const char *, uid_t, gid_t) = chown; static void -chownpwgr(const char *path) +chownpwgr(const char *path, int fflag) { if (chown_f(path, uid, gid) < 0) { weprintf("%s %s:", chown_f_name, path); ret = 1; } if (rflag) - recurse(path, chownpwgr); + recurse(path, chownpwgr, fflag); } static void @@ -48,6 +49,11 @@ main(int argc, char *argv[]) case 'r': rflag = 1; break; + case 'H': + case 'L': + case 'P': + fflag = ARGC(); + break; default: usage(); } ARGEND; @@ -88,7 +94,7 @@ main(int argc, char *argv[]) } } for (; argc > 0; argc--, argv++) - chownpwgr(argv[0]); + chownpwgr(argv[0], fflag); return ret; } diff --git a/libutil/recurse.c b/libutil/recurse.c index f9044e9..f2028f5 100644 --- a/libutil/recurse.c +++ b/libutil/recurse.c @@ -11,14 +11,16 @@ #include "../util.h" void -recurse(const char *path, void (*fn)(const char *)) +recurse(const char *path, void (*fn)(const char *, char), char follow) { char buf[PATH_MAX]; struct dirent *d; - struct stat st; + struct stat lst, st; DIR *dp; - if (lstat(path, &st) < 0 || !S_ISDIR(st.st_mode)) + 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)))) return; if (!(dp = opendir(path))) @@ -35,7 +37,7 @@ recurse(const char *path, void (*fn)(const char *)) eprintf("path too long\n"); if (strlcat(buf, d->d_name, sizeof(buf)) >= sizeof(buf)) eprintf("path too long\n"); - fn(buf); + fn(buf, follow == 'H' ? 'P' : follow); } closedir(dp); diff --git a/libutil/rm.c b/libutil/rm.c index 9aaedab..505ef28 100644 --- a/libutil/rm.c +++ b/libutil/rm.c @@ -12,7 +12,7 @@ void rm(const char *path) { if (rm_rflag) - recurse(path, rm); + recurse(path, rm, 'P'); if (remove(path) < 0) { if (!rm_fflag) weprintf("remove %s:", path); diff --git a/tar.c b/tar.c index 7083b5c..dec1bdc 100644 --- a/tar.c +++ b/tar.c @@ -44,7 +44,7 @@ static void putoctal(char *, unsigned, int); static int archive(const char *); static int unarchive(char *, int, char[Blksiz]); static int print(char *, int , char[Blksiz]); -static void c(const char *); +static void c(const char *, char); static void xt(int (*)(char*, int, char[Blksiz])); static FILE *tarfile; @@ -52,6 +52,7 @@ static ino_t tarinode; static dev_t tardev; static int mflag; +static char fflag = 'P'; static char filtermode; static FILE * @@ -245,10 +246,10 @@ print(char * fname, int l, char b[Blksiz]) } static void -c(const char * path) +c(const char * path, char fflag) { archive(path); - recurse(path, c); + recurse(path, c, fflag); } static void @@ -304,6 +305,9 @@ main(int argc, char *argv[]) usage(); filtermode = ARGC(); break; + case 'h': + fflag = 'L'; + break; default: usage(); } ARGEND; @@ -325,7 +329,7 @@ main(int argc, char *argv[]) tarfile = stdout; } chdir(dir); - c(argv[0]); + c(argv[0], fflag); break; case 't': case 'x': diff --git a/util.h b/util.h index 448f51e..d1970c7 100644 --- a/util.h +++ b/util.h @@ -60,7 +60,7 @@ mode_t getumask(void); char *humansize(double); mode_t parsemode(const char *, mode_t, mode_t); void putword(const char *); -void recurse(const char *, void (*)(const char *)); +void recurse(const char *, void (*)(const char *, char), char); #undef strtonum long long strtonum(const char *, long long, long long, const char **); long long enstrtonum(int, const char *, long long, long long); -- 2.3.0