>From 5de3629e2f181779460947ea8693561692425d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Compostella?= Date: Thu, 23 Feb 2012 00:11:41 +0100 Subject: [PATCH] chmod: add --parents option * chmod.c (main): Handle --parents option. --- src/chmod.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/chmod.c b/src/chmod.c index a134e3f..4378459 100644 --- a/src/chmod.c +++ b/src/chmod.c @@ -96,6 +96,7 @@ static struct option const long_options[] = { {"changes", no_argument, NULL, 'c'}, {"recursive", no_argument, NULL, 'R'}, + {"parents", no_argument, NULL, 'p'}, {"no-preserve-root", no_argument, NULL, NO_PRESERVE_ROOT}, {"preserve-root", no_argument, NULL, PRESERVE_ROOT}, {"quiet", no_argument, NULL, 'f'}, @@ -416,6 +417,7 @@ main (int argc, char **argv) size_t mode_alloc = 0; bool ok; bool preserve_root = false; + bool parents = false; char const *reference_file = NULL; int c; @@ -430,7 +432,7 @@ main (int argc, char **argv) recurse = force_silent = diagnose_surprises = false; while ((c = getopt_long (argc, argv, - "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::", + "Rpcfvr::w::x::X::s::t::u::g::o::a::,::+::=::", long_options, NULL)) != -1) { @@ -484,6 +486,9 @@ main (int argc, char **argv) case REFERENCE_FILE_OPTION: reference_file = optarg; break; + case 'p': + parents = true; + break; case 'R': recurse = true; break; @@ -544,6 +549,12 @@ main (int argc, char **argv) umask_value = umask (0); } + if (recurse && parents) + { + error (0, 0, _("--recurse and --parents are mutually exclusive")); + usage (EXIT_FAILURE); + } + if (recurse && preserve_root) { static struct dev_ino dev_ino_buf; @@ -557,8 +568,42 @@ main (int argc, char **argv) root_dev_ino = NULL; } - ok = process_files (argv + optind, - FTS_COMFOLLOW | FTS_PHYSICAL | FTS_DEFER_STAT); + if (! parents) + ok = process_files (argv + optind, + FTS_COMFOLLOW | FTS_PHYSICAL | FTS_DEFER_STAT); + else + { + char **first = argv + optind; + char **end = argv + argc; + while (end != first) + { + ok = process_files (first, + FTS_COMFOLLOW | FTS_PHYSICAL | FTS_DEFER_STAT); + if (! ok) + break; + + char **current = end - 1; + do + { + char *last = last_component (*current); + if (last != *current) { + /* Skiping slashes preceding the last component */ + while (ISSLASH (*--last) && last != *current) + ; + if (! ISSLASH (*last)) + *++last = '\0'; + } + if (last == *current) + { + /* Remove CURRENT by shifting ARGV to left from there */ + end = current - 1; + while (*end && end++) + *end = *(end + 1); + } + } + while (current-- != first); + } + } exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); } -- 1.7.2.5