commit da757ff7d1949e74f7209fb45a930d857dede1e0
parent c367d4d05fbab633bdb29ddb4795ae957785cfbd
Author: Connor Lane Smith <cls@lubutu.com>
Date: Wed, 25 May 2011 00:24:33 +0100
add chown
Diffstat:
M | Makefile | | | 6 | +++--- |
A | chown.1 | | | 15 | +++++++++++++++ |
A | chown.c | | | 66 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | rm.c | | | 38 | +++++--------------------------------- |
M | util.h | | | 1 | + |
A | util/recurse.c | | | 40 | ++++++++++++++++++++++++++++++++++++++++ |
6 files changed, 130 insertions(+), 36 deletions(-)
diff --git 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
@@ -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
@@ -0,0 +1,66 @@
+/* See LICENSE file for copyright and license details. */
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#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
@@ -1,10 +1,7 @@
/* See LICENSE file for copyright and license details. */
-#include <dirent.h>
-#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#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
@@ -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
@@ -0,0 +1,40 @@
+/* See LICENSE file for copyright and license details. */
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#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);
+}