1303 files changed, 32187 insertions, 57138 deletions
diff --git a/coreutils/install.c b/coreutils/install.c index 445497f..831f9b8 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -5,10 +5,26 @@ * * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//config:config INSTALL +//config: bool "install" +//config: default y +//config: help +//config: Copy files and set attributes. +//config: +//config:config FEATURE_INSTALL_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on INSTALL && LONG_OPTS +//config: help +//config: Support long options for the install applet. + +//applet:IF_INSTALL(APPLET(install, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_INSTALL) += install.o /* -v, -b, -c are ignored */ //usage:#define install_trivial_usage -//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [SOURCE]... DEST" +//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [-t DIR] [SOURCE]... DEST" //usage:#define install_full_usage "\n\n" //usage: "Copy files and set attributes\n" //usage: "\n -c Just copy (default)" @@ -19,6 +35,7 @@ //usage: "\n -o USER Set ownership" //usage: "\n -g GRP Set group ownership" //usage: "\n -m MODE Set permissions" +//usage: "\n -t DIR Install to DIR" //usage: IF_SELINUX( //usage: "\n -Z Set security context" //usage: ) @@ -28,12 +45,16 @@ #if ENABLE_FEATURE_INSTALL_LONG_OPTIONS static const char install_longopts[] ALIGN1 = + IF_FEATURE_VERBOSE( + "verbose\0" No_argument "v" + ) "directory\0" No_argument "d" "preserve-timestamps\0" No_argument "p" "strip\0" No_argument "s" "group\0" Required_argument "g" "mode\0" Required_argument "m" "owner\0" Required_argument "o" + "target-directory\0" Required_argument "t" /* autofs build insists of using -b --suffix=.orig */ /* TODO? (short option for --suffix is -S) */ #if ENABLE_SELINUX @@ -89,11 +110,11 @@ int install_main(int argc, char **argv) const char *gid_str; const char *uid_str; const char *mode_str; + int mkdir_flags = FILEUTILS_RECUR; int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE; int opts; - int min_args = 1; int ret = EXIT_SUCCESS; - int isdir = 0; + int isdir; #if ENABLE_SELINUX security_context_t scontext; bool use_default_selinux_context = 1; @@ -109,21 +130,22 @@ int install_main(int argc, char **argv) OPT_GROUP = 1 << 7, OPT_MODE = 1 << 8, OPT_OWNER = 1 << 9, + OPT_TARGET = 1 << 10, #if ENABLE_SELINUX - OPT_SET_SECURITY_CONTEXT = 1 << 10, - OPT_PRESERVE_SECURITY_CONTEXT = 1 << 11, + OPT_SET_SECURITY_CONTEXT = 1 << 11, + OPT_PRESERVE_SECURITY_CONTEXT = 1 << 12, #endif }; #if ENABLE_FEATURE_INSTALL_LONG_OPTIONS applet_long_options = install_longopts; #endif - opt_complementary = "s--d:d--s" IF_FEATURE_INSTALL_LONG_OPTIONS(IF_SELINUX(":Z--\xff:\xff--Z")); + opt_complementary = "t--d:d--t:s--d:d--s" IF_FEATURE_INSTALL_LONG_OPTIONS(IF_SELINUX(":Z--\xff:\xff--Z")); /* -c exists for backwards compatibility, it's needed */ - /* -v is ignored ("print name of each created directory") */ /* -b is ignored ("make a backup of each existing destination file") */ - opts = getopt32(argv, "cvb" "Ddpsg:m:o:" IF_SELINUX("Z:"), - &gid_str, &mode_str, &uid_str IF_SELINUX(, &scontext)); + opts = getopt32(argv, "cvb" "Ddpsg:m:o:t:" IF_SELINUX("Z:"), + &gid_str, &mode_str, &uid_str, &last + IF_SELINUX(, &scontext)); argc -= optind; argv += optind; @@ -141,6 +163,11 @@ int install_main(int argc, char **argv) } #endif + if ((opts & OPT_v) && FILEUTILS_VERBOSE) { + mkdir_flags |= FILEUTILS_VERBOSE; + copy_flags |= FILEUTILS_VERBOSE; + } + /* preserve access and modification time, this is GNU behaviour, * BSD only preserves modification time */ if (opts & OPT_PRESERVE_TIME) { @@ -148,39 +175,44 @@ int install_main(int argc, char **argv) } mode = 0755; /* GNU coreutils 6.10 compat */ if (opts & OPT_MODE) - bb_parse_mode(mode_str, &mode); + mode = bb_parse_mode(mode_str, mode); uid = (opts & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid(); gid = (opts & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid(); - last = argv[argc - 1]; - if (!(opts & OPT_DIRECTORY)) { - argv[argc - 1] = NULL; - min_args++; - + /* If -t DIR is in use, then isdir=true, last="DIR" */ + isdir = (opts & OPT_TARGET); + if (!(opts & (OPT_TARGET|OPT_DIRECTORY))) { + /* Neither -t DIR nor -d is in use */ + argc--; + last = argv[argc]; + argv[argc] = NULL; /* coreutils install resolves link in this case, don't use lstat */ isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode); } - if (argc < min_args) + if (argc < 1) bb_show_usage(); while ((arg = *argv++) != NULL) { - char *dest = last; + char *dest; + if (opts & OPT_DIRECTORY) { dest = arg; /* GNU coreutils 6.9 does not set uid:gid * on intermediate created directories * (only on last one) */ - if (bb_make_directory(dest, 0755, FILEUTILS_RECUR)) { + if (bb_make_directory(dest, 0755, mkdir_flags)) { ret = EXIT_FAILURE; goto next; } } else { + dest = last; if (opts & OPT_MKDIR_LEADING) { char *ddir = xstrdup(dest); - bb_make_directory(dirname(ddir), 0755, FILEUTILS_RECUR); + bb_make_directory(dirname(ddir), 0755, mkdir_flags); /* errors are not checked. copy_file - * will fail if dir is not created. */ + * will fail if dir is not created. + */ free(ddir); } if (isdir) |