- mode = 0666;
- if (flags & OPT_MODE) bb_parse_mode(mode_str, &mode);
- uid = (flags & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid();
- gid = (flags & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid();
- if (flags & (OPT_OWNER|OPT_GROUP)) umask(0);
-
- /* Create directories
- * don't use bb_make_directory() as it can't change uid or gid
- * 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) {
- if (errno != EEXIST) {
- bb_perror_msg("cannot create %s", *argv);
- ret = EXIT_FAILURE;
- break;
- }
- }
- if ((flags & (OPT_OWNER|OPT_GROUP))
- && lchown(*argv, uid, gid) == -1
- ) {
- bb_perror_msg("cannot change ownership of %s", *argv);
+ mode = 0755; /* GNU coreutils 6.10 compat */
+ if (opts & OPT_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++;
+
+ /* 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)
+ bb_show_usage();
+
+ while ((arg = *argv++) != NULL) {
+ char *dest = last;
+ 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)) {
+ ret = EXIT_FAILURE;
+ goto next;
+ }
+ } else {
+ if (opts & OPT_MKDIR_LEADING) {
+ char *ddir = xstrdup(dest);
+ bb_make_directory(dirname(ddir), 0755, FILEUTILS_RECUR);
+ /* errors are not checked. copy_file
+ * will fail if dir is not created. */
+ free(ddir);
+ }
+ if (isdir)
+ dest = concat_path_file(last, bb_basename(arg));
+ if (copy_file(arg, dest, copy_flags) != 0) {
+ /* copy is not made */
+ ret = EXIT_FAILURE;
+ goto next;
+ }
+ if (opts & OPT_STRIP) {
+ char *args[4];
+ args[0] = (char*)"strip";
+ args[1] = (char*)"-p"; /* -p --preserve-dates */
+ args[2] = dest;
+ args[3] = NULL;
+ if (spawn_and_wait(args)) {
+ bb_perror_msg("strip");