diff options
-rw-r--r-- | init/builtins.c | 42 | ||||
-rw-r--r-- | init/readme.txt | 4 |
2 files changed, 44 insertions, 2 deletions
diff --git a/init/builtins.c b/init/builtins.c index ba7fe3f..de067ce 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -35,6 +35,7 @@ #include <cutils/partition_utils.h> #include <sys/system_properties.h> #include <fs_mgr.h> +#include <fts.h> #ifdef HAVE_SELINUX #include <selinux/selinux.h> @@ -804,6 +805,47 @@ int do_chown(int nargs, char **args) { } else if (nargs == 4) { if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0) return -errno; + } else if (nargs == 5) { + int ret = 0; + int ftsflags = FTS_PHYSICAL; + FTS *fts; + FTSENT *ftsent; + char *options = args[1]; + uid_t uid = decode_uid(args[2]); + uid_t gid = decode_uid(args[3]); + char * path_argv[] = {args[4], NULL}; + if (strcmp(options, "-R")) { + ERROR("do_chown: Invalid argument: %s\n", args[1]); + return -EINVAL; + } + fts = fts_open(path_argv, ftsflags, NULL); + if (!fts) { + ERROR("do_chown: Error traversing hierarchy starting at %s\n", path_argv[0]); + return -errno; + } + while ((ftsent = fts_read(fts))) { + switch (ftsent->fts_info) { + case FTS_DP: + case FTS_SL: + break; + case FTS_DNR: + case FTS_ERR: + case FTS_NS: + ERROR("do_chown: Could not access %s\n", ftsent->fts_path); + fts_set(fts, ftsent, FTS_SKIP); + ret = -errno; + break; + default: + if (_chown(ftsent->fts_accpath, uid, gid) < 0) { + ret = -errno; + fts_set(fts, ftsent, FTS_SKIP); + } + break; + } + } + fts_close(fts); + if (ret) + return ret; } else { return -1; } diff --git a/init/readme.txt b/init/readme.txt index fe0d15d..f674db8 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -151,8 +151,8 @@ chdir <directory> chmod <octal-mode> <path> Change file access permissions. -chown <owner> <group> <path> - Change file owner and group. +chown [-R] <owner> <group> <path> + Change file owner and group. "-R" is for recursive chown. chroot <directory> Change process root directory. |