1 /**
2 * BTRFS_IOC_FILE_CLONE_RANGE.
3 *
4 * License:
5 * This Source Code Form is subject to the terms of
6 * the Mozilla Public License, v. 2.0. If a copy of
7 * the MPL was not distributed with this file, You
8 * can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * Authors:
11 * Vladimir Panteleev <ae@cy.md>
12 */
13
14 module ae.sys.btrfs.clone_range;
15
16 version(linux):
17
18 import core.stdc.errno;
19 import core.sys.posix.sys.ioctl;
20
21 import std.exception;
22 import std.stdio : File;
23
24 import ae.sys.btrfs.common;
25
26 private:
27
28 enum BTRFS_IOC_FILE_CLONE_RANGE = _IOW!btrfs_ioctl_clone_range_args(BTRFS_IOCTL_MAGIC, 13);
29
30 struct btrfs_ioctl_clone_range_args
31 {
32 long src_fd;
33 ulong src_offset, src_length;
34 ulong dest_offset;
35 }
36
37 public:
38
39 /// Submit a `BTRFS_IOC_FILE_CLONE_RANGE` ioctl.
40 void cloneRange(
41 ref const File srcFile, ulong srcOffset,
42 ref const File dstFile, ulong dstOffset,
43 ulong length)
44 {
45 btrfs_ioctl_clone_range_args args;
46
47 args.src_fd = srcFile.fileno;
48 args.src_offset = srcOffset;
49 args.src_length = length;
50 args.dest_offset = dstOffset;
51
52 int ret = ioctl(dstFile.fileno, BTRFS_IOC_FILE_CLONE_RANGE, &args);
53 errnoEnforce(ret >= 0, "ioctl(BTRFS_IOC_FILE_CLONE_RANGE)");
54 }
55
56 unittest
57 {
58 if (!checkBtrfs())
59 return;
60 import std.range, std.random, std.algorithm, std.file;
61 enum blockSize = 16*1024; // TODO: detect
62 auto data = blockSize.iota.map!(n => uniform!ubyte).array();
63 std.file.write("test1.bin", data);
64 scope(exit) remove("test1.bin");
65 auto f1 = File("test1.bin", "rb");
66 scope(exit) remove("test2.bin");
67 auto f2 = File("test2.bin", "wb");
68 cloneRange(f1, 0, f2, 0, blockSize);
69 f2.close();
70 f1.close();
71 assert(std.file.read("test2.bin") == data);
72 }