This matches the behavior of GNU coreutils
---
 coreutils/cp.c    | 14 +++++++++++---
 include/libbb.h   |  2 ++
 libbb/copy_file.c | 22 ++++++++++++++++++++++
 3 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/coreutils/cp.c b/coreutils/cp.c
index 247ed0f..cd947be 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -31,6 +31,7 @@
 //usage:     "\n       -f      Overwrite"
 //usage:     "\n       -i      Prompt before overwrite"
 //usage:     "\n       -l,-s   Create (sym)links"
+//usage:     "\n       -u      Copy if SOURCE file is newer than the 
destination"
 
 #include "libbb.h"
 #include "libcoreutils/coreutils.h"
@@ -53,8 +54,10 @@ int cp_main(int argc, char **argv)
                OPT_r = 1 << (sizeof(FILEUTILS_CP_OPTSTR)),
                OPT_P = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+1),
                OPT_v = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+2),
+               OPT_u = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
 #if ENABLE_FEATURE_CP_LONG_OPTIONS
-               OPT_parents = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+3),
+               OPT_parents = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+4),
+               OPT_rmdest  = 1 << (sizeof(FILEUTILS_CP_OPTSTR)+5),
 #endif
        };
 
@@ -76,10 +79,12 @@ int cp_main(int argc, char **argv)
                "recursive\0"      No_argument "R"
                "symbolic-link\0"  No_argument "s"
                "verbose\0"        No_argument "v"
-               "parents\0"        No_argument "\xff"
+               "update\0"         No_argument "u"
+               "parents\0"        No_argument "\xfe"
+               "remove-destination\0" No_argument "\xff"
                ;
 #endif
-       flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPv");
+       flags = getopt32(argv, FILEUTILS_CP_OPTSTR "arPvu");
        /* Options of cp from GNU coreutils 6.10:
         * -a, --archive
         * -f, --force
@@ -161,6 +166,9 @@ int cp_main(int argc, char **argv)
                                bb_error_msg_and_die("with --parents, the 
destination must be a directory");
                        }
                }
+               if (flags & OPT_rmdest) {
+                       flags |= FILEUTILS_RMDEST;
+               }
 #endif
 
                /* ...if neither is a directory...  */
diff --git a/include/libbb.h b/include/libbb.h
index fd40ef7..ece5f32 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -368,6 +368,8 @@ enum {      /* DO NOT CHANGE THESE VALUES!  cp.c, mv.c, 
install.c depend on them. */
        FILEUTILS_IGNORE_CHMOD_ERR = 1 << 11,
        /* -v */
        FILEUTILS_VERBOSE         = (1 << 12) * ENABLE_FEATURE_VERBOSE,
+       FILEUTILS_UPDATE          = 1 << 13, /* -u */
+       FILEUTILS_RMDEST          = 1 << 14, /* cp --remove-destination */
 };
 #define FILEUTILS_CP_OPTSTR "pdRfilsLH" IF_SELINUX("c")
 extern int remove_file(const char *path, int flags) FAST_FUNC;
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index a4be875..44031f2 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -208,6 +208,28 @@ int FAST_FUNC copy_file(const char *source, const char 
*dest, int flags)
                        /* retval = -1; - WRONG! copy *WAS* made */
                }
                goto preserve_mode_ugid_time;
+       } else {
+               /* Not a directory */
+               if (dest_exists) {
+                       if (flags & FILEUTILS_UPDATE) {
+                               if (source_stat.st_mtime <= dest_stat.st_mtime) 
{
+                                       return 0; /* source file must be newer 
*/
+                               }
+                       }
+                       if (flags & FILEUTILS_RMDEST) {
+                               if (unlink(dest) < 0) {
+                                       if (flags & FILEUTILS_VERBOSE) {
+                                               printf("can't remove '%s'\n", 
dest);
+                                       }
+                                       return -1;
+                               } else {
+                                       if (flags & FILEUTILS_VERBOSE) {
+                                               printf("removed '%s'\n", dest);
+                                       }
+                                       dest_exists = 0;
+                               }
+                       }
+               }
        }
 
        if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
-- 
2.8.3

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to