aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-07-13 20:30:02 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-07-13 20:30:02 +0200
commit79fb6ac7a5acc4178b66314c573aeada1d387ed9 (patch)
tree421fd899e9dfcc5533b3107af6eba3de0f153044
parent253f555f01fa380083a7436a569397a4e7f997b0 (diff)
downloadbusybox-w32-79fb6ac7a5acc4178b66314c573aeada1d387ed9.tar.gz
busybox-w32-79fb6ac7a5acc4178b66314c573aeada1d387ed9.tar.bz2
busybox-w32-79fb6ac7a5acc4178b66314c573aeada1d387ed9.zip
cp: optional --reflink support
function old new delta cp_main 428 512 +84 copy_file 1676 1742 +66 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/cp.c24
-rw-r--r--include/libbb.h3
-rw-r--r--libbb/copy_file.c19
3 files changed, 46 insertions, 0 deletions
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 455bffbba..b623aaf33 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -24,6 +24,11 @@
24//config: help 24//config: help
25//config: Enable long options. 25//config: Enable long options.
26//config: Also add support for --parents option. 26//config: Also add support for --parents option.
27//config:
28//config:config FEATURE_CP_REFLINK
29//config: bool "Enable --reflink[=auto]
30//config: default y
31//config: depends on FEATURE_CP_LONG_OPTIONS
27 32
28//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) 33//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp))
29/* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */ 34/* NOEXEC despite cases when it can be a "runner" (cp -r LARGE_DIR NEW_DIR) */
@@ -72,10 +77,14 @@ int cp_main(int argc, char **argv)
72#if ENABLE_FEATURE_CP_LONG_OPTIONS 77#if ENABLE_FEATURE_CP_LONG_OPTIONS
73 /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */ 78 /*OPT_rmdest = FILEUTILS_RMDEST = 1 << FILEUTILS_CP_OPTNUM */
74 OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1), 79 OPT_parents = 1 << (FILEUTILS_CP_OPTNUM+1),
80 OPT_reflink = 1 << (FILEUTILS_CP_OPTNUM+2),
75#endif 81#endif
76 }; 82 };
77 83
78#if ENABLE_FEATURE_CP_LONG_OPTIONS 84#if ENABLE_FEATURE_CP_LONG_OPTIONS
85# if ENABLE_FEATURE_CP_REFLINK
86 char *reflink = NULL;
87# endif
79 flags = getopt32long(argv, "^" 88 flags = getopt32long(argv, "^"
80 FILEUTILS_CP_OPTSTR 89 FILEUTILS_CP_OPTSTR
81 "\0" 90 "\0"
@@ -99,7 +108,22 @@ int cp_main(int argc, char **argv)
99 "update\0" No_argument "u" 108 "update\0" No_argument "u"
100 "remove-destination\0" No_argument "\xff" 109 "remove-destination\0" No_argument "\xff"
101 "parents\0" No_argument "\xfe" 110 "parents\0" No_argument "\xfe"
111# if ENABLE_FEATURE_CP_REFLINK
112 "reflink\0" Optional_argument "\xfd"
113 , &reflink
114# endif
102 ); 115 );
116# if ENABLE_FEATURE_CP_REFLINK
117 BUILD_BUG_ON(OPT_reflink != FILEUTILS_REFLINK);
118 if (flags & FILEUTILS_REFLINK) {
119 if (!reflink)
120 flags |= FILEUTILS_REFLINK_ALWAYS;
121 else if (strcmp(reflink, "always") == 0)
122 flags |= FILEUTILS_REFLINK_ALWAYS;
123 else if (strcmp(reflink, "auto") != 0)
124 bb_show_usage();
125 }
126# endif
103#else 127#else
104 flags = getopt32(argv, "^" 128 flags = getopt32(argv, "^"
105 FILEUTILS_CP_OPTSTR 129 FILEUTILS_CP_OPTSTR
diff --git a/include/libbb.h b/include/libbb.h
index d4ba031df..94caba2bb 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -410,6 +410,9 @@ enum { /* cp.c, mv.c, install.c depend on these values. CAREFUL when changing th
410 FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */ 410 FILEUTILS_PRESERVE_SECURITY_CONTEXT = 1 << 15, /* -c */
411#endif 411#endif
412 FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */ 412 FILEUTILS_RMDEST = 1 << (16 - !ENABLE_SELINUX), /* --remove-destination */
413 /* bit 17 skipped for "cp --parents" */
414 FILEUTILS_REFLINK = 1 << (18 - !ENABLE_SELINUX), /* cp --reflink=auto */
415 FILEUTILS_REFLINK_ALWAYS = 1 << (19 - !ENABLE_SELINUX), /* cp --reflink[=always] */
413 /* 416 /*
414 * Hole. cp may have some bits set here, 417 * Hole. cp may have some bits set here,
415 * they should not affect remove_file()/copy_file() 418 * they should not affect remove_file()/copy_file()
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index 1b8befd65..98bd4fe72 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -340,8 +340,27 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
340 } 340 }
341 } 341 }
342#endif 342#endif
343#if ENABLE_FEATURE_CP_REFLINK
344# undef BTRFS_IOCTL_MAGIC
345# define BTRFS_IOCTL_MAGIC 0x94
346# undef BTRFS_IOC_CLONE
347# define BTRFS_IOC_CLONE _IOW (BTRFS_IOCTL_MAGIC, 9, int)
348 if (flags & FILEUTILS_REFLINK) {
349 retval = ioctl(dst_fd, BTRFS_IOC_CLONE, src_fd);
350 if (retval == 0)
351 goto do_close;
352 /* reflink did not work */
353 if (flags & FILEUTILS_REFLINK_ALWAYS) {
354 bb_perror_msg("failed to clone '%s' from '%s'", dest, source);
355 goto do_close;
356 }
357 /* fall through to standard copy */
358 retval = 0;
359 }
360#endif
343 if (bb_copyfd_eof(src_fd, dst_fd) == -1) 361 if (bb_copyfd_eof(src_fd, dst_fd) == -1)
344 retval = -1; 362 retval = -1;
363 IF_FEATURE_CP_REFLINK(do_close:)
345 /* Careful with writing... */ 364 /* Careful with writing... */
346 if (close(dst_fd) < 0) { 365 if (close(dst_fd) < 0) {
347 bb_perror_msg("error writing to '%s'", dest); 366 bb_perror_msg("error writing to '%s'", dest);