[PATCH] cp: add -u/--update and --remove-destination
wdlkmpx
wdlkmpx at gmail.com
Sat May 21 22:13:55 UTC 2016
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
More information about the busybox
mailing list