diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-13 20:30:02 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-07-13 20:30:02 +0200 |
commit | 79fb6ac7a5acc4178b66314c573aeada1d387ed9 (patch) | |
tree | 421fd899e9dfcc5533b3107af6eba3de0f153044 | |
parent | 253f555f01fa380083a7436a569397a4e7f997b0 (diff) | |
download | busybox-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.c | 24 | ||||
-rw-r--r-- | include/libbb.h | 3 | ||||
-rw-r--r-- | libbb/copy_file.c | 19 |
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); |