X-Git-Url: https://git.saurik.com/apple/file_cmds.git/blobdiff_plain/64d2f73f72a44d5cc536043a2a9270edc5de82da..00337e45cbde0be25dd3e61cbd0bd3a55c65ab01:/cp/cp.c diff --git a/cp/cp.c b/cp/cp.c index c08ec23..7af6bbc 100644 --- a/cp/cp.c +++ b/cp/cp.c @@ -100,7 +100,6 @@ volatile sig_atomic_t info; enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE }; static int copy(char *[], enum op, int); -static int mastercmp(const FTSENT * const *, const FTSENT * const *); static void siginfo(int __unused); int @@ -112,7 +111,7 @@ main(int argc, char *argv[]) char *target; Hflag = Lflag = Pflag = 0; - while ((ch = getopt(argc, argv, "HLPRXfinprv")) != -1) + while ((ch = getopt(argc, argv, "HLPRXafinprv")) != -1) switch (ch) { case 'H': Hflag = 1; @@ -160,6 +159,11 @@ main(int argc, char *argv[]) case 'v': vflag = 1; break; + case 'a': + pflag = 1; + Pflag = 1; + Rflag = 1; + break; default: usage(); break; @@ -299,16 +303,45 @@ copy(char *argv[], enum op type, int fts_options) case FTS_ERR: warnx("%s: %s", curr->fts_path, strerror(curr->fts_errno)); - badcp = rval = 1; + rval = 1; continue; case FTS_DC: /* Warn, continue. */ warnx("%s: directory causes a cycle", curr->fts_path); - badcp = rval = 1; + rval = 1; continue; default: ; } +#ifdef __APPLE__ +#ifdef __clang__ +#pragma clang diagnostic push +/* clang doesn't like fts_name[1], but we know better... */ +#pragma clang diagnostic ignored "-Warray-bounds" +#endif + /* Skip ._ when using copyfile and exists */ + if ((pflag || !Xflag) && (curr->fts_level != FTS_ROOTLEVEL) && + (curr->fts_namelen > 2) && /* ._\0 is not AppleDouble */ + (curr->fts_name[0] == '.') && (curr->fts_name[1] == '_')) { +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + struct stat statbuf; + char path[PATH_MAX]; + char *p = strrchr(curr->fts_path, '/'); + if (p) { + size_t s = p + 2 - curr->fts_path; + if (s > sizeof(path)) s = sizeof(path); + strlcpy(path, curr->fts_path, s); + strlcat(path, curr->fts_name+2, sizeof(path)); + } else { + strlcpy(path, curr->fts_name+2, sizeof(path)); + } + if (!lstat(path, &statbuf)) { + continue; + } + } +#endif /* __APPLE__ */ /* * If we are in case (2) or (3) above, we need to append the * source name to the target name. @@ -355,7 +388,7 @@ copy(char *argv[], enum op type, int fts_options) if (target_mid - to.p_path + nlen >= PATH_MAX) { warnx("%s%s: name too long (not copied)", to.p_path, p); - badcp = rval = 1; + rval = 1; continue; } (void)strncat(target_mid, p, nlen); @@ -413,7 +446,7 @@ copy(char *argv[], enum op type, int fts_options) to_stat.st_ino == curr->fts_statp->st_ino) { warnx("%s and %s are identical (not copied).", to.p_path, curr->fts_path); - badcp = rval = 1; + rval = 1; if (S_ISDIR(curr->fts_statp->st_mode)) (void)fts_set(ftsp, curr, FTS_SKIP); continue; @@ -423,7 +456,7 @@ copy(char *argv[], enum op type, int fts_options) warnx("cannot overwrite directory %s with " "non-directory %s", to.p_path, curr->fts_path); - badcp = rval = 1; + rval = 1; continue; } dne = 0; @@ -460,12 +493,13 @@ copy(char *argv[], enum op type, int fts_options) */ if (dne) { if (mkdir(to.p_path, - curr->fts_statp->st_mode | S_IRWXU) < 0) + curr->fts_statp->st_mode | S_IRWXU) < 0) { if (COMPAT_MODE("bin/cp", "unix2003")) { warn("%s", to.p_path); } else { err(1, "%s", to.p_path); } + } } else if (!S_ISDIR(to_stat.st_mode)) { errno = ENOTDIR; if (COMPAT_MODE("bin/cp", "unix2003")) { @@ -521,32 +555,6 @@ copy(char *argv[], enum op type, int fts_options) return (rval); } -/* - * mastercmp -- - * The comparison function for the copy order. The order is to copy - * non-directory files before directory files. The reason for this - * is because files tend to be in the same cylinder group as their - * parent directory, whereas directories tend not to be. Copying the - * files first reduces seeking. - */ -static int -mastercmp(const FTSENT * const *a, const FTSENT * const *b) -{ - int a_info, b_info; - - a_info = (*a)->fts_info; - if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR) - return (0); - b_info = (*b)->fts_info; - if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR) - return (0); - if (a_info == FTS_D) - return (-1); - if (b_info == FTS_D) - return (1); - return (0); -} - static void siginfo(int sig __unused) {