X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=libbb%2Fcopy_file.c;h=23c0f8320b86f19f5d1a478368843340bd1bf51b;hb=b05bcaf29c9008799aedb535cb42d2e60cc4cbb9;hp=a4be875d244d8e316808833f8a53c9dacc004ac8;hpb=17f8418ea75410c3fbf9c9558f50f22cb8808e3e;p=oweals%2Fbusybox.git diff --git a/libbb/copy_file.c b/libbb/copy_file.c index a4be875d2..23c0f8320 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,6 +415,7 @@ 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); }