/* git clone https://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs.git cd btrfs-progs make gcc -O2 -luuid -o uu send-utils.o rbtree.o btrfs-list.o /path/to/this/file/uu.c */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "ctree.h" #include "ioctl.h" #include "send-utils.h" #define CLEAR(var) memset(&var, 0, sizeof(var)) int main(int argc, char **argv) { int ret, fd; struct subvol_uuid_search sus; struct btrfs_ioctl_received_subvol_args rs_args; struct subvol_info *si; char uuidbuf[37], parent_uuidbuf[37], received_uuidbuf[37]; if (argc != 3 && argc != 4) { printf("usage: uu srcmnt srcsub_reltosrcmnt [dstsub_abs]\n"); exit(1); } printf("opening srcmnt %s\n", argv[1]); fd = open(argv[1], O_RDONLY | O_NOATIME); if (fd < 0) { printf("failed to open srcmnt %s! %s\n", argv[1], strerror(errno)); exit(2); } puts("initializing sub search"); CLEAR(sus); ret = subvol_uuid_search_init(fd, &sus); if (ret < 0) { printf("failed to initialize sub search! %s\n", strerror(-ret)); exit(3); } printf("searching srcsub %s\n", argv[2]); si = subvol_uuid_search(&sus, 0, NULL, 0, argv[2], subvol_search_by_path); if (!si) { puts("srcsub not found!"); exit(4); } uuid_unparse(si->uuid, uuidbuf); uuid_unparse(si->parent_uuid, parent_uuidbuf); uuid_unparse(si->received_uuid, received_uuidbuf); printf("\nsrcsub found:\n" " uuid=%s\n" " parent_uuid=%s\n" "received_uuid=%s\n" "ctransid=%Lu otransid=%Lu stransid=%Lu rtransid=%Lu\n\n", uuidbuf, parent_uuidbuf, received_uuidbuf, (unsigned long long)(si->ctransid), (unsigned long long)(si->otransid), (unsigned long long)(si->stransid), (unsigned long long)(si->rtransid)); if (argc == 3) goto done; printf("opening dst subvol %s\n", argv[3]); fd = open(argv[3], O_RDONLY | O_NOATIME); if (fd < 0) { printf("failed to open dst subvol %s. %s\n", argv[3], strerror(errno)); exit(5); } printf("\nhere we go with BTRFS_IOC_SET_RECEIVED_SUBVOL:\n" "dstsub.received_uuid = srcsub.uuid == %s\n" "dstsub.stransid = srcsub.ctransid == %Lu\n\n", uuidbuf, (unsigned long long)(si->ctransid)); CLEAR(rs_args); memcpy(rs_args.uuid, si->uuid, BTRFS_UUID_SIZE); rs_args.stransid = si->ctransid; ret = ioctl(fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args); if (ret < 0) { printf("BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s", strerror(-ret)); exit(6); } done: printf("done.\n"); exit(0); }