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 <vladimir@thecybershadow.net> 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 void cloneRange( 40 in ref File srcFile, ulong srcOffset, 41 in ref File dstFile, ulong dstOffset, 42 ulong length) 43 { 44 btrfs_ioctl_clone_range_args args; 45 46 args.src_fd = srcFile.fileno; 47 args.src_offset = srcOffset; 48 args.src_length = length; 49 args.dest_offset = dstOffset; 50 51 int ret = ioctl(dstFile.fileno, BTRFS_IOC_FILE_CLONE_RANGE, &args); 52 errnoEnforce(ret >= 0, "ioctl(BTRFS_IOC_FILE_CLONE_RANGE)"); 53 } 54 55 unittest 56 { 57 if (!checkBtrfs()) 58 return; 59 import std.range, std.random, std.algorithm, std.file; 60 enum blockSize = 16*1024; // TODO: detect 61 auto data = blockSize.iota.map!(n => uniform!ubyte).array(); 62 std.file.write("test1.bin", data); 63 scope(exit) remove("test1.bin"); 64 auto f1 = File("test1.bin", "rb"); 65 scope(exit) remove("test2.bin"); 66 auto f2 = File("test2.bin", "wb"); 67 cloneRange(f1, 0, f2, 0, blockSize); 68 f2.close(); 69 f1.close(); 70 assert(std.file.read("test2.bin") == data); 71 }