From da757ff7d1949e74f7209fb45a930d857dede1e0 Mon Sep 17 00:00:00 2001 From: Connor Lane Smith Date: Wed, 25 May 2011 00:24:33 +0100 Subject: [PATCH] add chown --- Makefile | 6 ++--- chown.1 | 15 ++++++++++++ chown.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ rm.c | 38 ++++------------------------- util.h | 1 + util/recurse.c | 40 ++++++++++++++++++++++++++++++ 6 files changed, 130 insertions(+), 36 deletions(-) create mode 100644 chown.1 create mode 100644 chown.c create mode 100644 util/recurse.c diff --git a/Makefile b/Makefile index a7a5d84..031edad 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ include config.mk -LIB = util/enmasse.o util/eprintf.o -SRC = basename.c cat.c date.c dirname.c echo.c false.c grep.c ln.c pwd.c rm.c \ - sleep.c tee.c touch.c true.c wc.c +LIB = util/enmasse.o util/eprintf.o util/recurse.o +SRC = basename.c cat.c chown.c date.c dirname.c echo.c false.c grep.c ln.c \ + pwd.c rm.c sleep.c tee.c touch.c true.c wc.c OBJ = $(SRC:.c=.o) $(LIB) BIN = $(SRC:.c=) MAN = $(SRC:.c=.1) diff --git a/chown.1 b/chown.1 new file mode 100644 index 0000000..9b53e88 --- /dev/null +++ b/chown.1 @@ -0,0 +1,15 @@ +.TH CHOWN 1 sbase\-VERSION +.SH NAME +chown \- change file ownership +.SH SYNOPSIS +.B chown +.RB [ -Rr ] +.RI [ owner ][: group ] +.RI [ files ...] +.SH DESCRIPTION +.B chown +changes the user or group ownership for the given files. +.SH OPTIONS +.TP +.B -R, -r +change directory ownership recursively. diff --git a/chown.c b/chown.c new file mode 100644 index 0000000..a6a2b3e --- /dev/null +++ b/chown.c @@ -0,0 +1,66 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "util.h" + +static void chownpwgr(const char *); + +static bool rflag = false; +static struct passwd *pw = NULL; +static struct group *gr = NULL; + +int +main(int argc, char *argv[]) +{ + char c, *owner, *group; + + while((c = getopt(argc, argv, "Rr")) != -1) + switch(c) { + case 'R': + case 'r': + rflag = true; + break; + default: + exit(EXIT_FAILURE); + } + if(optind == argc) + eprintf("usage: %s [-Rr] [owner][:group] [file...]\n", argv[0]); + owner = argv[optind++]; + if((group = strchr(owner, ':'))) + *group++ = '\0'; + + if(owner && *owner) { + errno = 0; + pw = getpwnam(owner); + if(errno != 0) + eprintf("getpwnam %s:", owner); + else if(!pw) + eprintf("getpwnam %s: no such user\n", owner); + } + if(group && *group) { + errno = 0; + gr = getgrnam(group); + if(errno != 0) + eprintf("getgrnam %s:", group); + else if(!gr) + eprintf("getgrnam %s: no such user\n", group); + } + for(; optind < argc; optind++) + chownpwgr(argv[optind]); + return EXIT_SUCCESS; +} + +void +chownpwgr(const char *path) +{ + if(chown(path, pw ? pw->pw_uid : -1, gr ? gr->gr_gid : -1) != 0) + eprintf("chown %s:", path); + if(rflag) + recurse(path, chownpwgr); +} diff --git a/rm.c b/rm.c index fe6e2ce..b6017ad 100644 --- a/rm.c +++ b/rm.c @@ -1,10 +1,7 @@ /* See LICENSE file for copyright and license details. */ -#include -#include #include #include #include -#include #include #include "util.h" @@ -34,36 +31,11 @@ main(int argc, char *argv[]) return EXIT_SUCCESS; } -void rm(const char *path) +void +rm(const char *path) { - if(remove(path) == 0) - return; - if(errno == ENOTEMPTY && rflag) { - char *buf; - long size; - struct dirent *d; - DIR *dp; - - if((size = pathconf(".", _PC_PATH_MAX)) < 0) - size = BUFSIZ; - if(!(buf = malloc(size))) - eprintf("malloc:"); - if(!getcwd(buf, size)) - eprintf("getcwd:"); - if(!(dp = opendir(path))) - eprintf("opendir %s:", path); - if(chdir(path) != 0) - eprintf("chdir %s:", path); - while((d = readdir(dp))) - if(strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) - rm(d->d_name); - - closedir(dp); - if(chdir(buf) != 0) - eprintf("chdir %s:", buf); - if(remove(path) == 0) - return; - } - if(!fflag) + if(rflag) + recurse(path, rm); + if(remove(path) != 0 && !fflag) eprintf("remove %s:", path); } diff --git a/util.h b/util.h index ad0b4f7..a75bd1d 100644 --- a/util.h +++ b/util.h @@ -2,3 +2,4 @@ void enmasse(int, char **, int (*)(const char *, const char *)); void eprintf(const char *, ...); +void recurse(const char *, void (*)(const char *)); diff --git a/util/recurse.c b/util/recurse.c new file mode 100644 index 0000000..9caa5b1 --- /dev/null +++ b/util/recurse.c @@ -0,0 +1,40 @@ +/* See LICENSE file for copyright and license details. */ +#include +#include +#include +#include +#include +#include +#include "../util.h" + +void +recurse(const char *path, void (*fn)(const char *)) +{ + char *buf; + long size; + struct dirent *d; + DIR *dp; + + if(!(dp = opendir(path))) { + if(errno == ENOTDIR) + return; + else + eprintf("opendir %s:", path); + } + if((size = pathconf(".", _PC_PATH_MAX)) < 0) + size = BUFSIZ; + if(!(buf = malloc(size))) + eprintf("malloc:"); + if(!getcwd(buf, size)) + eprintf("getcwd:"); + if(chdir(path) != 0) + eprintf("chdir %s:", path); + while((d = readdir(dp))) + if(strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) + fn(d->d_name); + + closedir(dp); + if(chdir(buf) != 0) + eprintf("chdir %s:", buf); + free(buf); +}