diff --git a/coreutils/install.c b/coreutils/install.c index d087306d6..8575043e1 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -73,11 +73,14 @@ int install_main(int argc, char **argv) mode_t mode; uid_t uid; gid_t gid; + char *arg, *last; const char *gid_str; const char *uid_str; const char *mode_str; int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE; - int ret = EXIT_SUCCESS, flags, i, isdir; + int flags; + int ret = EXIT_SUCCESS; + int isdir; #if ENABLE_SELINUX security_context_t scontext; #endif @@ -103,6 +106,8 @@ int install_main(int argc, char **argv) flags = getopt32(argv, "cdpsg:m:o:" USE_SELINUX("Z:"), &gid_str, &mode_str, &uid_str USE_SELINUX(, &scontext)); + argc -= optind; + argv += optind; #if ENABLE_SELINUX if (flags & OPT_PRESERVE_SECURITY_CONTEXT) { @@ -135,48 +140,50 @@ int install_main(int argc, char **argv) * perhaps bb_make_directory() should be improved. */ if (flags & OPT_DIRECTORY) { - for (argv += optind; *argv; argv++) { - char *old_argv_ptr = *argv + 1; - char *argv_ptr; - do { - argv_ptr = strchr(old_argv_ptr, '/'); - old_argv_ptr = argv_ptr; - if (argv_ptr) { - *argv_ptr = '\0'; - old_argv_ptr++; - } - if (mkdir(*argv, mode | 0111) == -1) { + while ((arg = *argv++) != NULL) { + char *slash = arg; + while (1) { + slash = strchr(slash + 1, '/'); + if (slash) + *slash = '\0'; + if (mkdir(arg, mode | 0111) == -1) { if (errno != EEXIST) { - bb_perror_msg("cannot create %s", *argv); + bb_perror_msg("cannot create %s", arg); ret = EXIT_FAILURE; break; } - } - if ((flags & (OPT_OWNER|OPT_GROUP)) - && lchown(*argv, uid, gid) == -1 + } /* dir was created, chown? */ + else if ((flags & (OPT_OWNER|OPT_GROUP)) + && lchown(arg, uid, gid) == -1 ) { - bb_perror_msg("cannot change ownership of %s", *argv); + bb_perror_msg("cannot change ownership of %s", arg); ret = EXIT_FAILURE; break; } - if (argv_ptr) { - *argv_ptr = '/'; - } - } while (old_argv_ptr); + if (!slash) + break; + *slash = '/'; + } } return ret; } + if (argc < 2) + bb_show_usage(); + + last = argv[argc - 1]; /* coreutils install resolves link in this case, don't use lstat */ - isdir = stat(argv[argc - 1], &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode); + isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode); - for (i = optind; i < argc - 1; i++) { - char *dest; - - dest = argv[argc - 1]; + while ((arg = *argv++) != NULL) { + char *dest = last; if (isdir) - dest = concat_path_file(argv[argc - 1], basename(argv[i])); - ret |= copy_file(argv[i], dest, copy_flags); + dest = concat_path_file(last, basename(arg)); + if (copy_file(arg, dest, copy_flags)) { + /* copy is not made */ + ret = EXIT_FAILURE; + goto next; + } /* Set the file mode */ if ((flags & OPT_MODE) && chmod(dest, mode) == -1) { @@ -204,7 +211,9 @@ int install_main(int argc, char **argv) ret = EXIT_FAILURE; } } - if (ENABLE_FEATURE_CLEAN_UP && isdir) free(dest); + next: + if (ENABLE_FEATURE_CLEAN_UP && isdir) + free(dest); } return ret;