2 * Copyright (C) 2012 Alexander Block. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include "kerncompat.h"
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
36 #include <sys/types.h>
37 #include <sys/xattr.h>
38 #include <uuid/uuid.h>
45 #include "btrfs-list.h"
48 #include "send-stream.h"
49 #include "send-utils.h"
51 static int g_verbose = 0;
59 char write_path[PATH_MAX];
62 char *dest_dir_path; /* relative to root_path */
63 char full_subvol_path[PATH_MAX];
67 struct subvol_info cur_subvol;
69 * Substitute for cur_subvol::path which is a pointer and we cannot
70 * change it to an array as it's a public API.
72 char cur_subvol_path[PATH_MAX];
74 struct subvol_uuid_search sus;
79 * Buffer to store capabilities from security.capabilities xattr,
80 * usually 20 bytes, but make same room for potentially larger
81 * encodings. Must be set only once per file, denoted by length > 0.
83 char cached_capabilities[64];
84 int cached_capabilities_len;
87 static int finish_subvol(struct btrfs_receive *r)
91 struct btrfs_ioctl_received_subvol_args rs_args;
92 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
95 if (r->cur_subvol_path[0] == 0)
98 subvol_fd = openat(r->mnt_fd, r->cur_subvol_path,
99 O_RDONLY | O_NOATIME);
102 fprintf(stderr, "ERROR: open %s failed. %s\n",
103 r->cur_subvol_path, strerror(-ret));
107 memset(&rs_args, 0, sizeof(rs_args));
108 memcpy(rs_args.uuid, r->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
109 rs_args.stransid = r->cur_subvol.stransid;
111 if (g_verbose >= 1) {
112 uuid_unparse((u8*)rs_args.uuid, uuid_str);
113 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
114 "stransid=%llu\n", uuid_str, rs_args.stransid);
117 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
120 fprintf(stderr, "ERROR: BTRFS_IOC_SET_RECEIVED_SUBVOL failed. %s\n",
124 r->cur_subvol.rtransid = rs_args.rtransid;
126 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
129 fprintf(stderr, "ERROR: BTRFS_IOC_SUBVOL_GETFLAGS failed. %s\n",
134 flags |= BTRFS_SUBVOL_RDONLY;
136 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
139 fprintf(stderr, "ERROR: failed to make subvolume read only. "
140 "%s\n", strerror(-ret));
147 if (r->cur_subvol_path[0]) {
148 r->cur_subvol_path[0] = 0;
155 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
159 struct btrfs_receive *r = user;
160 struct btrfs_ioctl_vol_args args_v1;
161 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
163 ret = finish_subvol(r);
167 BUG_ON(r->cur_subvol.path);
168 BUG_ON(r->cur_subvol_path[0]);
170 if (strlen(r->dest_dir_path) == 0) {
171 strncpy_null(r->cur_subvol_path, path);
173 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
175 fprintf(stderr, "ERROR: subvol: path invalid: %s\n",
180 ret = path_cat3_out(r->full_subvol_path, r->root_path,
181 r->dest_dir_path, path);
183 fprintf(stderr, "ERROR: subvol: path invalid: %s\n", path);
187 fprintf(stderr, "At subvol %s\n", path);
189 memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
190 r->cur_subvol.stransid = ctransid;
193 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
194 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
196 r->cur_subvol.stransid);
199 memset(&args_v1, 0, sizeof(args_v1));
200 strncpy_null(args_v1.name, path);
201 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
204 fprintf(stderr, "ERROR: creating subvolume %s failed. "
205 "%s\n", path, strerror(-ret));
213 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
214 const u8 *parent_uuid, u64 parent_ctransid,
218 struct btrfs_receive *r = user;
219 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
220 struct btrfs_ioctl_vol_args_v2 args_v2;
221 struct subvol_info *parent_subvol = NULL;
223 ret = finish_subvol(r);
227 BUG_ON(r->cur_subvol.path);
228 BUG_ON(r->cur_subvol_path[0]);
230 if (strlen(r->dest_dir_path) == 0) {
231 strncpy_null(r->cur_subvol_path, path);
233 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
235 fprintf(stderr, "ERROR: snapshot: path invalid: %s\n",
240 ret = path_cat3_out(r->full_subvol_path, r->root_path,
241 r->dest_dir_path, path);
243 fprintf(stderr, "ERROR: snapshot: path invalid: %s\n", path);
247 fprintf(stdout, "At snapshot %s\n", path);
249 memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
250 r->cur_subvol.stransid = ctransid;
253 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
254 fprintf(stderr, "receiving snapshot %s uuid=%s, "
255 "ctransid=%llu ", path, uuid_str,
256 r->cur_subvol.stransid);
257 uuid_unparse(parent_uuid, uuid_str);
258 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
259 uuid_str, parent_ctransid);
262 memset(&args_v2, 0, sizeof(args_v2));
263 strncpy_null(args_v2.name, path);
265 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
266 parent_ctransid, NULL, subvol_search_by_received_uuid);
267 if (!parent_subvol) {
268 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
269 parent_ctransid, NULL, subvol_search_by_uuid);
271 if (!parent_subvol) {
273 fprintf(stderr, "ERROR: could not find parent subvolume\n");
278 * The path is resolved from the root subvol, but we could be in some
279 * subvolume under the root subvolume, so try and adjust the path to be
280 * relative to our root path.
282 if (r->full_root_path) {
286 root_len = strlen(r->full_root_path);
287 sub_len = strlen(parent_subvol->path);
289 /* First make sure the parent subvol is actually in our path */
290 if (sub_len < root_len ||
291 strstr(parent_subvol->path, r->full_root_path) == NULL) {
292 fprintf(stderr, "ERROR: parent subvol is not reachable"
293 " from inside the root subvol.\n");
298 if (sub_len == root_len) {
299 parent_subvol->path[0] = '/';
300 parent_subvol->path[1] = '\0';
303 * root path is foo/bar
304 * subvol path is foo/bar/baz
306 * we need to have baz be the path, so we need to move
307 * the bit after foo/bar/, so path + root_len + 1, and
308 * move the part we care about, so sub_len - root_len -
311 memmove(parent_subvol->path,
312 parent_subvol->path + root_len + 1,
313 sub_len - root_len - 1);
314 parent_subvol->path[sub_len - root_len - 1] = '\0';
317 /*if (rs_args.ctransid > rs_args.rtransid) {
320 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
323 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
327 if (strlen(parent_subvol->path) == 0)
328 args_v2.fd = dup(r->mnt_fd);
330 args_v2.fd = openat(r->mnt_fd, parent_subvol->path,
331 O_RDONLY | O_NOATIME);
332 if (args_v2.fd < 0) {
335 fprintf(stderr, "ERROR: open %s failed. %s\n",
336 parent_subvol->path, strerror(-ret));
339 "It seems that you have changed your default "
340 "subvolume or you specify other subvolume to\n"
341 "mount btrfs, try to remount this btrfs filesystem "
342 "with fs tree, and run btrfs receive again!\n");
346 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
350 fprintf(stderr, "ERROR: creating snapshot %s -> %s "
351 "failed. %s\n", parent_subvol->path,
352 path, strerror(-ret));
358 free(parent_subvol->path);
364 static int process_mkfile(const char *path, void *user)
367 struct btrfs_receive *r = user;
368 char full_path[PATH_MAX];
370 ret = path_cat_out(full_path, r->full_subvol_path, path);
372 fprintf(stderr, "ERROR: mkfile: path invalid: %s\n", path);
377 fprintf(stderr, "mkfile %s\n", path);
379 ret = creat(full_path, 0600);
382 fprintf(stderr, "ERROR: mkfile %s failed. %s\n", path,
393 static int process_mkdir(const char *path, void *user)
396 struct btrfs_receive *r = user;
397 char full_path[PATH_MAX];
399 ret = path_cat_out(full_path, r->full_subvol_path, path);
401 fprintf(stderr, "ERROR: mkdir: path invalid: %s\n", path);
406 fprintf(stderr, "mkdir %s\n", path);
408 ret = mkdir(full_path, 0700);
411 fprintf(stderr, "ERROR: mkdir %s failed. %s\n", path,
419 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
422 struct btrfs_receive *r = user;
423 char full_path[PATH_MAX];
425 ret = path_cat_out(full_path, r->full_subvol_path, path);
427 fprintf(stderr, "ERROR: mknod: path invalid: %s\n", path);
432 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
435 ret = mknod(full_path, mode & S_IFMT, dev);
438 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
446 static int process_mkfifo(const char *path, void *user)
449 struct btrfs_receive *r = user;
450 char full_path[PATH_MAX];
452 ret = path_cat_out(full_path, r->full_subvol_path, path);
454 fprintf(stderr, "ERROR: mkfifo: path invalid: %s\n", path);
459 fprintf(stderr, "mkfifo %s\n", path);
461 ret = mkfifo(full_path, 0600);
464 fprintf(stderr, "ERROR: mkfifo %s failed. %s\n", path,
472 static int process_mksock(const char *path, void *user)
475 struct btrfs_receive *r = user;
476 char full_path[PATH_MAX];
478 ret = path_cat_out(full_path, r->full_subvol_path, path);
480 fprintf(stderr, "ERROR: mksock: path invalid: %s\n", path);
485 fprintf(stderr, "mksock %s\n", path);
487 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
490 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
498 static int process_symlink(const char *path, const char *lnk, void *user)
501 struct btrfs_receive *r = user;
502 char full_path[PATH_MAX];
504 ret = path_cat_out(full_path, r->full_subvol_path, path);
506 fprintf(stderr, "ERROR: symlink: path invalid: %s\n", path);
511 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
513 ret = symlink(lnk, full_path);
516 fprintf(stderr, "ERROR: symlink %s -> %s failed. %s\n", path,
517 lnk, strerror(-ret));
524 static int process_rename(const char *from, const char *to, void *user)
527 struct btrfs_receive *r = user;
528 char full_from[PATH_MAX];
529 char full_to[PATH_MAX];
531 ret = path_cat_out(full_from, r->full_subvol_path, from);
533 fprintf(stderr, "ERROR: rename: source path invalid: %s\n",
538 ret = path_cat_out(full_to, r->full_subvol_path, to);
540 fprintf(stderr, "ERROR: rename: target path invalid: %s\n",
546 fprintf(stderr, "rename %s -> %s\n", from, to);
548 ret = rename(full_from, full_to);
551 fprintf(stderr, "ERROR: rename %s -> %s failed. %s\n", from,
559 static int process_link(const char *path, const char *lnk, void *user)
562 struct btrfs_receive *r = user;
563 char full_path[PATH_MAX];
564 char full_link_path[PATH_MAX];
566 ret = path_cat_out(full_path, r->full_subvol_path, path);
568 fprintf(stderr, "ERROR: link: source path invalid: %s\n",
573 ret = path_cat_out(full_link_path, r->full_subvol_path, lnk);
575 fprintf(stderr, "ERROR: link: target path invalid: %s\n",
581 fprintf(stderr, "link %s -> %s\n", path, lnk);
583 ret = link(full_link_path, full_path);
586 fprintf(stderr, "ERROR: link %s -> %s failed. %s\n", path,
587 lnk, strerror(-ret));
595 static int process_unlink(const char *path, void *user)
598 struct btrfs_receive *r = user;
599 char full_path[PATH_MAX];
601 ret = path_cat_out(full_path, r->full_subvol_path, path);
603 fprintf(stderr, "ERROR: unlink: path invalid: %s\n", path);
608 fprintf(stderr, "unlink %s\n", path);
610 ret = unlink(full_path);
613 fprintf(stderr, "ERROR: unlink %s failed. %s\n", path,
621 static int process_rmdir(const char *path, void *user)
624 struct btrfs_receive *r = user;
625 char full_path[PATH_MAX];
627 ret = path_cat_out(full_path, r->full_subvol_path, path);
629 fprintf(stderr, "ERROR: rmdir: path invalid: %s\n", path);
634 fprintf(stderr, "rmdir %s\n", path);
636 ret = rmdir(full_path);
639 fprintf(stderr, "ERROR: rmdir %s failed. %s\n", path,
647 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
651 if (r->write_fd != -1) {
652 if (strcmp(r->write_path, path) == 0)
658 r->write_fd = open(path, O_RDWR);
659 if (r->write_fd < 0) {
661 fprintf(stderr, "ERROR: open %s failed. %s\n", path,
665 strncpy_null(r->write_path, path);
671 static void close_inode_for_write(struct btrfs_receive *r)
673 if(r->write_fd == -1)
678 r->write_path[0] = 0;
681 static int process_write(const char *path, const void *data, u64 offset,
685 struct btrfs_receive *r = user;
686 char full_path[PATH_MAX];
690 ret = path_cat_out(full_path, r->full_subvol_path, path);
692 fprintf(stderr, "ERROR: write: path invalid: %s\n", path);
696 ret = open_inode_for_write(r, full_path);
701 w = pwrite(r->write_fd, (char*)data + pos, len - pos,
705 fprintf(stderr, "ERROR: writing to %s failed. %s\n",
706 path, strerror(-ret));
716 static int process_clone(const char *path, u64 offset, u64 len,
717 const u8 *clone_uuid, u64 clone_ctransid,
718 const char *clone_path, u64 clone_offset,
722 struct btrfs_receive *r = user;
723 struct btrfs_ioctl_clone_range_args clone_args;
724 struct subvol_info *si = NULL;
725 char full_path[PATH_MAX];
726 char *subvol_path = NULL;
727 char full_clone_path[PATH_MAX];
730 ret = path_cat_out(full_path, r->full_subvol_path, path);
732 fprintf(stderr, "ERROR: clone: source path invalid: %s\n",
737 ret = open_inode_for_write(r, full_path);
741 si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL,
742 subvol_search_by_received_uuid);
744 if (memcmp(clone_uuid, r->cur_subvol.received_uuid,
745 BTRFS_UUID_SIZE) == 0) {
746 /* TODO check generation of extent */
747 subvol_path = strdup(r->cur_subvol_path);
750 fprintf(stderr, "ERROR: did not find source subvol.\n");
754 /*if (rs_args.ctransid > rs_args.rtransid) {
757 fprintf(stderr, "ERROR: subvolume %s was "
758 "modified after it was "
760 r->subvol_parent_name);
763 fprintf(stderr, "WARNING: subvolume %s was "
764 "modified after it was "
766 r->subvol_parent_name);
769 subvol_path = strdup(si->path);
772 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
774 fprintf(stderr, "ERROR: clone: target path invalid: %s\n",
779 clone_fd = openat(r->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
782 fprintf(stderr, "ERROR: failed to open %s. %s\n",
783 full_clone_path, strerror(-ret));
787 clone_args.src_fd = clone_fd;
788 clone_args.src_offset = clone_offset;
789 clone_args.src_length = len;
790 clone_args.dest_offset = offset;
791 ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
794 fprintf(stderr, "ERROR: failed to clone extents to %s\n%s\n",
795 path, strerror(-ret));
811 static int process_set_xattr(const char *path, const char *name,
812 const void *data, int len, void *user)
815 struct btrfs_receive *r = user;
816 char full_path[PATH_MAX];
818 ret = path_cat_out(full_path, r->full_subvol_path, path);
820 fprintf(stderr, "ERROR: set_xattr: path invalid: %s\n", path);
824 if (strcmp("security.capability", name) == 0) {
826 fprintf(stderr, "set_xattr: cache capabilities\n");
827 if (r->cached_capabilities_len)
829 "WARNING: capabilities set multiple times per file: %s\n",
831 if (len > sizeof(r->cached_capabilities)) {
833 "ERROR: capabilities encoded to %d bytes, buffer too small\n",
838 r->cached_capabilities_len = len;
839 memcpy(r->cached_capabilities, data, len);
842 if (g_verbose >= 2) {
843 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
844 "data=%.*s\n", path, name, len,
848 ret = lsetxattr(full_path, name, data, len, 0);
851 fprintf(stderr, "ERROR: lsetxattr %s %s=%.*s failed. %s\n",
852 path, name, len, (char*)data, strerror(-ret));
860 static int process_remove_xattr(const char *path, const char *name, void *user)
863 struct btrfs_receive *r = user;
864 char full_path[PATH_MAX];
866 ret = path_cat_out(full_path, r->full_subvol_path, path);
868 fprintf(stderr, "ERROR: remove_xattr: path invalid: %s\n",
873 if (g_verbose >= 2) {
874 fprintf(stderr, "remove_xattr %s - name=%s\n",
878 ret = lremovexattr(full_path, name);
881 fprintf(stderr, "ERROR: lremovexattr %s %s failed. %s\n",
882 path, name, strerror(-ret));
890 static int process_truncate(const char *path, u64 size, void *user)
893 struct btrfs_receive *r = user;
894 char full_path[PATH_MAX];
896 ret = path_cat_out(full_path, r->full_subvol_path, path);
898 fprintf(stderr, "ERROR: truncate: path invalid: %s\n", path);
903 fprintf(stderr, "truncate %s size=%llu\n", path, size);
905 ret = truncate(full_path, size);
908 fprintf(stderr, "ERROR: truncate %s failed. %s\n",
909 path, strerror(-ret));
917 static int process_chmod(const char *path, u64 mode, void *user)
920 struct btrfs_receive *r = user;
921 char full_path[PATH_MAX];
923 ret = path_cat_out(full_path, r->full_subvol_path, path);
925 fprintf(stderr, "ERROR: chmod: path invalid: %s\n", path);
930 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
932 ret = chmod(full_path, mode);
935 fprintf(stderr, "ERROR: chmod %s failed. %s\n",
936 path, strerror(-ret));
944 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
947 struct btrfs_receive *r = user;
948 char full_path[PATH_MAX];
950 ret = path_cat_out(full_path, r->full_subvol_path, path);
952 fprintf(stderr, "ERROR: chown: path invalid: %s\n", path);
957 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
960 ret = lchown(full_path, uid, gid);
963 fprintf(stderr, "ERROR: chown %s failed. %s\n",
964 path, strerror(-ret));
968 if (r->cached_capabilities_len) {
970 fprintf(stderr, "chown: restore capabilities\n");
971 ret = lsetxattr(full_path, "security.capability",
972 r->cached_capabilities,
973 r->cached_capabilities_len, 0);
974 memset(r->cached_capabilities, 0,
975 sizeof(r->cached_capabilities));
976 r->cached_capabilities_len = 0;
979 fprintf(stderr, "ERROR: restoring capabilities %s: %s\n",
980 path, strerror(-ret));
989 static int process_utimes(const char *path, struct timespec *at,
990 struct timespec *mt, struct timespec *ct,
994 struct btrfs_receive *r = user;
995 char full_path[PATH_MAX];
996 struct timespec tv[2];
998 ret = path_cat_out(full_path, r->full_subvol_path, path);
1000 fprintf(stderr, "ERROR: utimes: path invalid: %s\n", path);
1005 fprintf(stderr, "utimes %s\n", path);
1009 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1012 fprintf(stderr, "ERROR: utimes %s failed. %s\n",
1013 path, strerror(-ret));
1021 static int process_update_extent(const char *path, u64 offset, u64 len,
1025 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1026 path, (unsigned long long)offset,
1027 (unsigned long long)len);
1030 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1036 static struct btrfs_send_ops send_ops = {
1037 .subvol = process_subvol,
1038 .snapshot = process_snapshot,
1039 .mkfile = process_mkfile,
1040 .mkdir = process_mkdir,
1041 .mknod = process_mknod,
1042 .mkfifo = process_mkfifo,
1043 .mksock = process_mksock,
1044 .symlink = process_symlink,
1045 .rename = process_rename,
1046 .link = process_link,
1047 .unlink = process_unlink,
1048 .rmdir = process_rmdir,
1049 .write = process_write,
1050 .clone = process_clone,
1051 .set_xattr = process_set_xattr,
1052 .remove_xattr = process_remove_xattr,
1053 .truncate = process_truncate,
1054 .chmod = process_chmod,
1055 .chown = process_chown,
1056 .utimes = process_utimes,
1057 .update_extent = process_update_extent,
1060 static int do_receive(struct btrfs_receive *r, const char *tomnt,
1061 char *realmnt, int r_fd, u64 max_errors)
1065 char *dest_dir_full_path;
1066 char root_subvol_path[PATH_MAX];
1069 dest_dir_full_path = realpath(tomnt, NULL);
1070 if (!dest_dir_full_path) {
1072 fprintf(stderr, "ERROR: realpath(%s) failed. %s\n", tomnt,
1076 r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1077 if (r->dest_dir_fd < 0) {
1080 "ERROR: failed to open destination directory %s. %s\n",
1081 dest_dir_full_path, strerror(-ret));
1086 r->root_path = realmnt;
1088 ret = find_mount_root(dest_dir_full_path, &r->root_path);
1091 "ERROR: failed to determine mount point for %s: %s\n",
1092 dest_dir_full_path, strerror(-ret));
1098 "ERROR: %s doesn't belong to btrfs mount point\n",
1099 dest_dir_full_path);
1104 r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
1105 if (r->mnt_fd < 0) {
1107 fprintf(stderr, "ERROR: failed to open %s. %s\n", r->root_path,
1113 * If we use -m or a default subvol we want to resolve the path to the
1114 * subvolume we're sitting in so that we can adjust the paths of any
1115 * subvols we want to receive in.
1117 ret = btrfs_list_get_path_rootid(r->mnt_fd, &subvol_id);
1119 fprintf(stderr, "ERROR: couldn't resolve our subvolid %d\n",
1124 root_subvol_path[0] = 0;
1125 ret = btrfs_subvolid_resolve(r->mnt_fd, root_subvol_path,
1126 PATH_MAX, subvol_id);
1128 fprintf(stderr, "ERROR: couldn't resolve our subvol path\n");
1133 * Ok we're inside of a subvol off of the root subvol, we need to
1134 * actually set full_root_path.
1136 if (strlen(root_subvol_path))
1137 r->full_root_path = root_subvol_path;
1139 if (r->dest_dir_chroot) {
1140 if (chroot(dest_dir_full_path)) {
1143 "ERROR: failed to chroot to %s, %s\n",
1151 "ERROR: failed to chdir to /, %s\n",
1155 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1156 r->root_path = strdup("/");
1157 r->dest_dir_path = r->root_path;
1160 * find_mount_root returns a root_path that is a subpath of
1161 * dest_dir_full_path. Now get the other part of root_path,
1162 * which is the destination dir relative to root_path.
1164 r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
1165 while (r->dest_dir_path[0] == '/')
1169 ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
1174 if (r->cached_capabilities_len) {
1176 fprintf(stderr, "clear cached capabilities\n");
1177 memset(r->cached_capabilities, 0,
1178 sizeof(r->cached_capabilities));
1179 r->cached_capabilities_len = 0;
1182 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
1190 close_inode_for_write(r);
1191 ret = finish_subvol(r);
1198 if (r->write_fd != -1) {
1203 r->root_path = NULL;
1204 r->dest_dir_path = NULL;
1205 free(dest_dir_full_path);
1206 subvol_uuid_search_finit(&r->sus);
1207 if (r->mnt_fd != -1) {
1211 if (r->dest_dir_fd != -1) {
1212 close(r->dest_dir_fd);
1213 r->dest_dir_fd = -1;
1219 int cmd_receive(int argc, char **argv)
1222 char fromfile[PATH_MAX];
1223 char realmnt[PATH_MAX];
1224 struct btrfs_receive r;
1225 int receive_fd = fileno(stdin);
1229 memset(&r, 0, sizeof(r));
1233 r.dest_dir_chroot = 0;
1239 static const struct option long_opts[] = {
1240 { "max-errors", required_argument, NULL, 'E' },
1241 { "chroot", no_argument, NULL, 'C' },
1242 { NULL, 0, NULL, 0 }
1245 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1254 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1256 "ERROR: input file path too long (%zu)\n",
1263 r.honor_end_cmd = 1;
1266 r.dest_dir_chroot = 1;
1269 max_errors = arg_strtou64(optarg);
1272 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1274 "ERROR: mount point path too long (%zu)\n",
1282 fprintf(stderr, "ERROR: receive args invalid.\n");
1287 if (check_argc_exact(argc - optind, 1))
1288 usage(cmd_receive_usage);
1290 tomnt = argv[optind];
1293 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1294 if (receive_fd < 0) {
1295 fprintf(stderr, "ERROR: failed to open %s\n", fromfile);
1300 ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1307 const char * const cmd_receive_usage[] = {
1308 "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1309 "Receive subvolumes from stdin.",
1310 "Receives one or more subvolumes that were previously",
1311 "sent with btrfs send. The received subvolumes are stored",
1313 "btrfs receive will fail in case a receiving subvolume",
1314 "already exists. It will also fail in case a previously",
1315 "received subvolume was changed after it was received.",
1316 "After receiving a subvolume, it is immediately set to",
1318 "-v Enable verbose debug output. Each",
1319 " occurrence of this option increases the",
1320 " verbose level more.",
1321 "-f <infile> By default, btrfs receive uses stdin",
1322 " to receive the subvolumes. Use this",
1323 " option to specify a file to use instead.",
1324 "-e Terminate after receiving an <end cmd>",
1325 " in the data stream. Without this option,",
1326 " the receiver terminates only if an error",
1327 " is recognized or on EOF.",
1328 "-C|--chroot confine the process to <mount> using chroot",
1329 "--max-errors <N> Terminate as soon as N errors happened while",
1330 " processing commands from the send stream.",
1331 " Default value is 1. A value of 0 means no limit.",
1332 "-m <mountpoint> The root mount point of the destination fs.",
1333 " If you do not have /proc use this to tell us where ",
1334 " this file system is mounted.",