1303 files changed, 32187 insertions, 57138 deletions
diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 9333a8d..23c0f83 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c @@ -64,6 +64,11 @@ static int ask_and_unlink(const char *dest, int flags) bb_perror_msg("can't create '%s'", dest); return -1; /* error */ } +#if ENABLE_FEATURE_CP_LONG_OPTIONS + if (flags & FILEUTILS_RMDEST) + if (flags & FILEUTILS_VERBOSE) + printf("removed '%s'\n", dest); +#endif return 1; /* ok (to try again) */ } @@ -210,6 +215,22 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) goto preserve_mode_ugid_time; } + if (dest_exists) { + if (flags & FILEUTILS_UPDATE) { + if (source_stat.st_mtime <= dest_stat.st_mtime) { + return 0; /* source file must be newer */ + } + } +#if ENABLE_FEATURE_CP_LONG_OPTIONS + if (flags & FILEUTILS_RMDEST) { + ovr = ask_and_unlink(dest, flags); + if (ovr <= 0) + return ovr; + dest_exists = 0; + } +#endif + } + if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) { int (*lf)(const char *oldpath, const char *newpath); make_links: @@ -275,11 +296,16 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) if (!S_ISREG(source_stat.st_mode)) new_mode = 0666; - // POSIX way is a security problem versus (sym)link attacks - if (!ENABLE_FEATURE_NON_POSIX_CP) { - dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); - } else { /* safe way: */ + if (ENABLE_FEATURE_NON_POSIX_CP || (flags & FILEUTILS_INTERACTIVE)) { + /* + * O_CREAT|O_EXCL: require that file did not exist before creation + */ dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode); + } else { /* POSIX, and not "cp -i" */ + /* + * O_CREAT|O_TRUNC: create, or truncate (security problem versus (sym)link attacks) + */ + dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); } if (dst_fd == -1) { ovr = ask_and_unlink(dest, flags); @@ -354,7 +380,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) } /* _Not_ jumping to preserve_mode_ugid_time: * symlinks don't have those */ - return 0; + goto verb_and_exit; } if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode) || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode) @@ -389,5 +415,10 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) bb_perror_msg("can't preserve %s of '%s'", "permissions", dest); } + verb_and_exit: + if (flags & FILEUTILS_VERBOSE) { + printf("'%s' -> '%s'\n", source, dest); + } + return retval; } |