diff --git a/src/clone-cat.cc b/src/clone-cat.cc new file mode 100644 index 0000000..a8a48e8 --- /dev/null +++ b/src/clone-cat.cc @@ -0,0 +1,35 @@ +#include "crucible/error.h" +#include "crucible/fd.h" +#include "crucible/fs.h" + +using namespace crucible; +using namespace std; + +int +main(int argc, char **argv) +{ + if (argc <= 2) { + cerr << "Usage: " << argv[0] << " FILE1 FILE2 [...FILEn] > OUTFILE" << endl; + cerr << "Catenates FILE1..FILEN using copy_file_range" << endl; + return EXIT_FAILURE; + } + + off_t out_pos = 0; + + while (*++argv) { + string filename(*argv); + + Fd input_fd = open_or_die(filename, O_RDONLY); + + Stat st(input_fd); + + off_t len = st.st_size; + + cerr << "clone_range(" << filename << ", 0, " << len << ", STDOUT_FILENO, " << out_pos << ")" << flush; + btrfs_clone_range(input_fd, 0, len, STDOUT_FILENO, out_pos); + out_pos += len; + cerr << endl; + } + + return EXIT_SUCCESS; +} diff --git a/src/clone-split.cc b/src/clone-split.cc new file mode 100644 index 0000000..f7e31e5 --- /dev/null +++ b/src/clone-split.cc @@ -0,0 +1,35 @@ +#include "crucible/error.h" +#include "crucible/fd.h" +#include "crucible/fs.h" + +using namespace crucible; +using namespace std; + +int +main(int argc, char **argv) +{ + if (argc != 3) { + cerr << "Usage: " << argv[0] << " FILE SIZE" << endl; + cerr << "Splits FILE into SIZE-byte pieces using copy_file_range" << endl; + } + + string filename(argv[1]); + off_t out_size(stoull(argv[2], 0, 0)); + + Fd input_fd = open_or_die(filename, O_RDONLY); + + Stat st(input_fd); + + for (off_t pos = 0; pos < st.st_size; pos += out_size) { + char pos_name[64]; + off_t len = min(st.st_size - pos, out_size); + snprintf(pos_name, sizeof(pos_name), "0x%016llx", static_cast(pos)); + string out_name = filename + '.' + pos_name; + cout << out_name << flush; + Fd output_fd = open_or_die(out_name, O_WRONLY | O_EXCL | O_CREAT); + btrfs_clone_range(input_fd, pos, len, output_fd, 0); + cout << endl; + } + + return 0; +}