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 }