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"
34 #include <sys/types.h>
35 #include <sys/ioctl.h>
37 #include <sys/types.h>
38 #include <sys/xattr.h>
39 #include <uuid/uuid.h>
46 #include "btrfs-list.h"
49 #include "send-stream.h"
50 #include "send-utils.h"
52 static int g_verbose = 0;
60 char write_path[PATH_MAX];
63 char *dest_dir_path; /* relative to root_path */
64 char full_subvol_path[PATH_MAX];
68 struct subvol_info cur_subvol;
70 * Substitute for cur_subvol::path which is a pointer and we cannot
71 * change it to an array as it's a public API.
73 char cur_subvol_path[PATH_MAX];
75 struct subvol_uuid_search sus;
80 * Buffer to store capabilities from security.capabilities xattr,
81 * usually 20 bytes, but make same room for potentially larger
82 * encodings. Must be set only once per file, denoted by length > 0.
84 char cached_capabilities[64];
85 int cached_capabilities_len;
88 static int finish_subvol(struct btrfs_receive *r)
92 struct btrfs_ioctl_received_subvol_args rs_args;
93 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
96 if (r->cur_subvol_path[0] == 0)
99 subvol_fd = openat(r->mnt_fd, r->cur_subvol_path,
100 O_RDONLY | O_NOATIME);
103 fprintf(stderr, "ERROR: open %s failed. %s\n",
104 r->cur_subvol_path, strerror(-ret));
108 memset(&rs_args, 0, sizeof(rs_args));
109 memcpy(rs_args.uuid, r->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
110 rs_args.stransid = r->cur_subvol.stransid;
112 if (g_verbose >= 1) {
113 uuid_unparse((u8*)rs_args.uuid, uuid_str);
114 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
115 "stransid=%llu\n", uuid_str, rs_args.stransid);
118 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
121 fprintf(stderr, "ERROR: BTRFS_IOC_SET_RECEIVED_SUBVOL failed. %s\n",
125 r->cur_subvol.rtransid = rs_args.rtransid;
127 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
130 fprintf(stderr, "ERROR: BTRFS_IOC_SUBVOL_GETFLAGS failed. %s\n",
135 flags |= BTRFS_SUBVOL_RDONLY;
137 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
140 fprintf(stderr, "ERROR: failed to make subvolume read only. "
141 "%s\n", strerror(-ret));
148 if (r->cur_subvol_path[0]) {
149 r->cur_subvol_path[0] = 0;
156 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
160 struct btrfs_receive *r = user;
161 struct btrfs_ioctl_vol_args args_v1;
162 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
164 ret = finish_subvol(r);
168 BUG_ON(r->cur_subvol.path);
169 BUG_ON(r->cur_subvol_path[0]);
171 if (strlen(r->dest_dir_path) == 0) {
172 strncpy_null(r->cur_subvol_path, path);
174 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
176 fprintf(stderr, "ERROR: subvol: path invalid: %s\n",
181 ret = path_cat3_out(r->full_subvol_path, r->root_path,
182 r->dest_dir_path, path);
184 fprintf(stderr, "ERROR: subvol: path invalid: %s\n", path);
188 fprintf(stderr, "At subvol %s\n", path);
190 memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
191 r->cur_subvol.stransid = ctransid;
194 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
195 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
197 r->cur_subvol.stransid);
200 memset(&args_v1, 0, sizeof(args_v1));
201 strncpy_null(args_v1.name, path);
202 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
205 fprintf(stderr, "ERROR: creating subvolume %s failed. "
206 "%s\n", path, strerror(-ret));
214 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
215 const u8 *parent_uuid, u64 parent_ctransid,
219 struct btrfs_receive *r = user;
220 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
221 struct btrfs_ioctl_vol_args_v2 args_v2;
222 struct subvol_info *parent_subvol = NULL;
224 ret = finish_subvol(r);
228 BUG_ON(r->cur_subvol.path);
229 BUG_ON(r->cur_subvol_path[0]);
231 if (strlen(r->dest_dir_path) == 0) {
232 strncpy_null(r->cur_subvol_path, path);
234 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
236 fprintf(stderr, "ERROR: snapshot: path invalid: %s\n",
241 ret = path_cat3_out(r->full_subvol_path, r->root_path,
242 r->dest_dir_path, path);
244 fprintf(stderr, "ERROR: snapshot: path invalid: %s\n", path);
248 fprintf(stdout, "At snapshot %s\n", path);
250 memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
251 r->cur_subvol.stransid = ctransid;
254 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
255 fprintf(stderr, "receiving snapshot %s uuid=%s, "
256 "ctransid=%llu ", path, uuid_str,
257 r->cur_subvol.stransid);
258 uuid_unparse(parent_uuid, uuid_str);
259 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
260 uuid_str, parent_ctransid);
263 memset(&args_v2, 0, sizeof(args_v2));
264 strncpy_null(args_v2.name, path);
266 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
267 parent_ctransid, NULL, subvol_search_by_received_uuid);
268 if (!parent_subvol) {
269 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
270 parent_ctransid, NULL, subvol_search_by_uuid);
272 if (!parent_subvol) {
274 fprintf(stderr, "ERROR: could not find parent subvolume\n");
279 * The path is resolved from the root subvol, but we could be in some
280 * subvolume under the root subvolume, so try and adjust the path to be
281 * relative to our root path.
283 if (r->full_root_path) {
287 root_len = strlen(r->full_root_path);
288 sub_len = strlen(parent_subvol->path);
290 /* First make sure the parent subvol is actually in our path */
291 if (sub_len < root_len ||
292 strstr(parent_subvol->path, r->full_root_path) == NULL) {
293 fprintf(stderr, "ERROR: parent subvol is not reachable"
294 " from inside the root subvol.\n");
299 if (sub_len == root_len) {
300 parent_subvol->path[0] = '/';
301 parent_subvol->path[1] = '\0';
304 * root path is foo/bar
305 * subvol path is foo/bar/baz
307 * we need to have baz be the path, so we need to move
308 * the bit after foo/bar/, so path + root_len + 1, and
309 * move the part we care about, so sub_len - root_len -
312 memmove(parent_subvol->path,
313 parent_subvol->path + root_len + 1,
314 sub_len - root_len - 1);
315 parent_subvol->path[sub_len - root_len - 1] = '\0';
318 /*if (rs_args.ctransid > rs_args.rtransid) {
321 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
324 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
328 if (strlen(parent_subvol->path) == 0)
329 args_v2.fd = dup(r->mnt_fd);
331 args_v2.fd = openat(r->mnt_fd, parent_subvol->path,
332 O_RDONLY | O_NOATIME);
333 if (args_v2.fd < 0) {
336 fprintf(stderr, "ERROR: open %s failed. %s\n",
337 parent_subvol->path, strerror(-ret));
340 "It seems that you have changed your default "
341 "subvolume or you specify other subvolume to\n"
342 "mount btrfs, try to remount this btrfs filesystem "
343 "with fs tree, and run btrfs receive again!\n");
347 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
351 fprintf(stderr, "ERROR: creating snapshot %s -> %s "
352 "failed. %s\n", parent_subvol->path,
353 path, strerror(-ret));
359 free(parent_subvol->path);
365 static int process_mkfile(const char *path, void *user)
368 struct btrfs_receive *r = user;
369 char full_path[PATH_MAX];
371 ret = path_cat_out(full_path, r->full_subvol_path, path);
373 fprintf(stderr, "ERROR: mkfile: path invalid: %s\n", path);
378 fprintf(stderr, "mkfile %s\n", path);
380 ret = creat(full_path, 0600);
383 fprintf(stderr, "ERROR: mkfile %s failed. %s\n", path,
394 static int process_mkdir(const char *path, void *user)
397 struct btrfs_receive *r = user;
398 char full_path[PATH_MAX];
400 ret = path_cat_out(full_path, r->full_subvol_path, path);
402 fprintf(stderr, "ERROR: mkdir: path invalid: %s\n", path);
407 fprintf(stderr, "mkdir %s\n", path);
409 ret = mkdir(full_path, 0700);
412 fprintf(stderr, "ERROR: mkdir %s failed. %s\n", path,
420 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
423 struct btrfs_receive *r = user;
424 char full_path[PATH_MAX];
426 ret = path_cat_out(full_path, r->full_subvol_path, path);
428 fprintf(stderr, "ERROR: mknod: path invalid: %s\n", path);
433 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
436 ret = mknod(full_path, mode & S_IFMT, dev);
439 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
447 static int process_mkfifo(const char *path, void *user)
450 struct btrfs_receive *r = user;
451 char full_path[PATH_MAX];
453 ret = path_cat_out(full_path, r->full_subvol_path, path);
455 fprintf(stderr, "ERROR: mkfifo: path invalid: %s\n", path);
460 fprintf(stderr, "mkfifo %s\n", path);
462 ret = mkfifo(full_path, 0600);
465 fprintf(stderr, "ERROR: mkfifo %s failed. %s\n", path,
473 static int process_mksock(const char *path, void *user)
476 struct btrfs_receive *r = user;
477 char full_path[PATH_MAX];
479 ret = path_cat_out(full_path, r->full_subvol_path, path);
481 fprintf(stderr, "ERROR: mksock: path invalid: %s\n", path);
486 fprintf(stderr, "mksock %s\n", path);
488 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
491 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
499 static int process_symlink(const char *path, const char *lnk, void *user)
502 struct btrfs_receive *r = user;
503 char full_path[PATH_MAX];
505 ret = path_cat_out(full_path, r->full_subvol_path, path);
507 fprintf(stderr, "ERROR: symlink: path invalid: %s\n", path);
512 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
514 ret = symlink(lnk, full_path);
517 fprintf(stderr, "ERROR: symlink %s -> %s failed. %s\n", path,
518 lnk, strerror(-ret));
525 static int process_rename(const char *from, const char *to, void *user)
528 struct btrfs_receive *r = user;
529 char full_from[PATH_MAX];
530 char full_to[PATH_MAX];
532 ret = path_cat_out(full_from, r->full_subvol_path, from);
534 fprintf(stderr, "ERROR: rename: source path invalid: %s\n",
539 ret = path_cat_out(full_to, r->full_subvol_path, to);
541 fprintf(stderr, "ERROR: rename: target path invalid: %s\n",
547 fprintf(stderr, "rename %s -> %s\n", from, to);
549 ret = rename(full_from, full_to);
552 fprintf(stderr, "ERROR: rename %s -> %s failed. %s\n", from,
560 static int process_link(const char *path, const char *lnk, void *user)
563 struct btrfs_receive *r = user;
564 char full_path[PATH_MAX];
565 char full_link_path[PATH_MAX];
567 ret = path_cat_out(full_path, r->full_subvol_path, path);
569 fprintf(stderr, "ERROR: link: source path invalid: %s\n",
574 ret = path_cat_out(full_link_path, r->full_subvol_path, lnk);
576 fprintf(stderr, "ERROR: link: target path invalid: %s\n",
582 fprintf(stderr, "link %s -> %s\n", path, lnk);
584 ret = link(full_link_path, full_path);
587 fprintf(stderr, "ERROR: link %s -> %s failed. %s\n", path,
588 lnk, strerror(-ret));
596 static int process_unlink(const char *path, void *user)
599 struct btrfs_receive *r = user;
600 char full_path[PATH_MAX];
602 ret = path_cat_out(full_path, r->full_subvol_path, path);
604 fprintf(stderr, "ERROR: unlink: path invalid: %s\n", path);
609 fprintf(stderr, "unlink %s\n", path);
611 ret = unlink(full_path);
614 fprintf(stderr, "ERROR: unlink %s failed. %s\n", path,
622 static int process_rmdir(const char *path, void *user)
625 struct btrfs_receive *r = user;
626 char full_path[PATH_MAX];
628 ret = path_cat_out(full_path, r->full_subvol_path, path);
630 fprintf(stderr, "ERROR: rmdir: path invalid: %s\n", path);
635 fprintf(stderr, "rmdir %s\n", path);
637 ret = rmdir(full_path);
640 fprintf(stderr, "ERROR: rmdir %s failed. %s\n", path,
648 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
652 if (r->write_fd != -1) {
653 if (strcmp(r->write_path, path) == 0)
659 r->write_fd = open(path, O_RDWR);
660 if (r->write_fd < 0) {
662 fprintf(stderr, "ERROR: open %s failed. %s\n", path,
666 strncpy_null(r->write_path, path);
672 static void close_inode_for_write(struct btrfs_receive *r)
674 if(r->write_fd == -1)
679 r->write_path[0] = 0;
682 static int process_write(const char *path, const void *data, u64 offset,
686 struct btrfs_receive *r = user;
687 char full_path[PATH_MAX];
691 ret = path_cat_out(full_path, r->full_subvol_path, path);
693 fprintf(stderr, "ERROR: write: path invalid: %s\n", path);
697 ret = open_inode_for_write(r, full_path);
702 w = pwrite(r->write_fd, (char*)data + pos, len - pos,
706 fprintf(stderr, "ERROR: writing to %s failed. %s\n",
707 path, strerror(-ret));
717 static int process_clone(const char *path, u64 offset, u64 len,
718 const u8 *clone_uuid, u64 clone_ctransid,
719 const char *clone_path, u64 clone_offset,
723 struct btrfs_receive *r = user;
724 struct btrfs_ioctl_clone_range_args clone_args;
725 struct subvol_info *si = NULL;
726 char full_path[PATH_MAX];
727 char *subvol_path = NULL;
728 char full_clone_path[PATH_MAX];
731 ret = path_cat_out(full_path, r->full_subvol_path, path);
733 fprintf(stderr, "ERROR: clone: source path invalid: %s\n",
738 ret = open_inode_for_write(r, full_path);
742 si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL,
743 subvol_search_by_received_uuid);
745 if (memcmp(clone_uuid, r->cur_subvol.received_uuid,
746 BTRFS_UUID_SIZE) == 0) {
747 /* TODO check generation of extent */
748 subvol_path = strdup(r->cur_subvol_path);
751 fprintf(stderr, "ERROR: did not find source subvol.\n");
755 /*if (rs_args.ctransid > rs_args.rtransid) {
758 fprintf(stderr, "ERROR: subvolume %s was "
759 "modified after it was "
761 r->subvol_parent_name);
764 fprintf(stderr, "WARNING: subvolume %s was "
765 "modified after it was "
767 r->subvol_parent_name);
770 subvol_path = strdup(si->path);
773 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
775 fprintf(stderr, "ERROR: clone: target path invalid: %s\n",
780 clone_fd = openat(r->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
783 fprintf(stderr, "ERROR: failed to open %s. %s\n",
784 full_clone_path, strerror(-ret));
788 clone_args.src_fd = clone_fd;
789 clone_args.src_offset = clone_offset;
790 clone_args.src_length = len;
791 clone_args.dest_offset = offset;
792 ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
795 fprintf(stderr, "ERROR: failed to clone extents to %s\n%s\n",
796 path, strerror(-ret));
812 static int process_set_xattr(const char *path, const char *name,
813 const void *data, int len, void *user)
816 struct btrfs_receive *r = user;
817 char full_path[PATH_MAX];
819 ret = path_cat_out(full_path, r->full_subvol_path, path);
821 fprintf(stderr, "ERROR: set_xattr: path invalid: %s\n", path);
825 if (strcmp("security.capability", name) == 0) {
827 fprintf(stderr, "set_xattr: cache capabilities\n");
828 if (r->cached_capabilities_len)
830 "WARNING: capabilities set multiple times per file: %s\n",
832 if (len > sizeof(r->cached_capabilities)) {
834 "ERROR: capabilities encoded to %d bytes, buffer too small\n",
839 r->cached_capabilities_len = len;
840 memcpy(r->cached_capabilities, data, len);
843 if (g_verbose >= 2) {
844 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
845 "data=%.*s\n", path, name, len,
849 ret = lsetxattr(full_path, name, data, len, 0);
852 fprintf(stderr, "ERROR: lsetxattr %s %s=%.*s failed. %s\n",
853 path, name, len, (char*)data, strerror(-ret));
861 static int process_remove_xattr(const char *path, const char *name, void *user)
864 struct btrfs_receive *r = user;
865 char full_path[PATH_MAX];
867 ret = path_cat_out(full_path, r->full_subvol_path, path);
869 fprintf(stderr, "ERROR: remove_xattr: path invalid: %s\n",
874 if (g_verbose >= 2) {
875 fprintf(stderr, "remove_xattr %s - name=%s\n",
879 ret = lremovexattr(full_path, name);
882 fprintf(stderr, "ERROR: lremovexattr %s %s failed. %s\n",
883 path, name, strerror(-ret));
891 static int process_truncate(const char *path, u64 size, void *user)
894 struct btrfs_receive *r = user;
895 char full_path[PATH_MAX];
897 ret = path_cat_out(full_path, r->full_subvol_path, path);
899 fprintf(stderr, "ERROR: truncate: path invalid: %s\n", path);
904 fprintf(stderr, "truncate %s size=%llu\n", path, size);
906 ret = truncate(full_path, size);
909 fprintf(stderr, "ERROR: truncate %s failed. %s\n",
910 path, strerror(-ret));
918 static int process_chmod(const char *path, u64 mode, void *user)
921 struct btrfs_receive *r = user;
922 char full_path[PATH_MAX];
924 ret = path_cat_out(full_path, r->full_subvol_path, path);
926 fprintf(stderr, "ERROR: chmod: path invalid: %s\n", path);
931 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
933 ret = chmod(full_path, mode);
936 fprintf(stderr, "ERROR: chmod %s failed. %s\n",
937 path, strerror(-ret));
945 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
948 struct btrfs_receive *r = user;
949 char full_path[PATH_MAX];
951 ret = path_cat_out(full_path, r->full_subvol_path, path);
953 fprintf(stderr, "ERROR: chown: path invalid: %s\n", path);
958 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
961 ret = lchown(full_path, uid, gid);
964 fprintf(stderr, "ERROR: chown %s failed. %s\n",
965 path, strerror(-ret));
969 if (r->cached_capabilities_len) {
971 fprintf(stderr, "chown: restore capabilities\n");
972 ret = lsetxattr(full_path, "security.capability",
973 r->cached_capabilities,
974 r->cached_capabilities_len, 0);
975 memset(r->cached_capabilities, 0,
976 sizeof(r->cached_capabilities));
977 r->cached_capabilities_len = 0;
980 fprintf(stderr, "ERROR: restoring capabilities %s: %s\n",
981 path, strerror(-ret));
990 static int process_utimes(const char *path, struct timespec *at,
991 struct timespec *mt, struct timespec *ct,
995 struct btrfs_receive *r = user;
996 char full_path[PATH_MAX];
997 struct timespec tv[2];
999 ret = path_cat_out(full_path, r->full_subvol_path, path);
1001 fprintf(stderr, "ERROR: utimes: path invalid: %s\n", path);
1006 fprintf(stderr, "utimes %s\n", path);
1010 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1013 fprintf(stderr, "ERROR: utimes %s failed. %s\n",
1014 path, strerror(-ret));
1022 static int process_update_extent(const char *path, u64 offset, u64 len,
1026 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1027 path, (unsigned long long)offset,
1028 (unsigned long long)len);
1031 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1037 static struct btrfs_send_ops send_ops = {
1038 .subvol = process_subvol,
1039 .snapshot = process_snapshot,
1040 .mkfile = process_mkfile,
1041 .mkdir = process_mkdir,
1042 .mknod = process_mknod,
1043 .mkfifo = process_mkfifo,
1044 .mksock = process_mksock,
1045 .symlink = process_symlink,
1046 .rename = process_rename,
1047 .link = process_link,
1048 .unlink = process_unlink,
1049 .rmdir = process_rmdir,
1050 .write = process_write,
1051 .clone = process_clone,
1052 .set_xattr = process_set_xattr,
1053 .remove_xattr = process_remove_xattr,
1054 .truncate = process_truncate,
1055 .chmod = process_chmod,
1056 .chown = process_chown,
1057 .utimes = process_utimes,
1058 .update_extent = process_update_extent,
1061 static int do_receive(struct btrfs_receive *r, const char *tomnt,
1062 char *realmnt, int r_fd, u64 max_errors)
1066 char *dest_dir_full_path;
1067 char root_subvol_path[PATH_MAX];
1070 dest_dir_full_path = realpath(tomnt, NULL);
1071 if (!dest_dir_full_path) {
1073 fprintf(stderr, "ERROR: realpath(%s) failed. %s\n", tomnt,
1077 r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1078 if (r->dest_dir_fd < 0) {
1081 "ERROR: failed to open destination directory %s. %s\n",
1082 dest_dir_full_path, strerror(-ret));
1087 r->root_path = realmnt;
1089 ret = find_mount_root(dest_dir_full_path, &r->root_path);
1092 "ERROR: failed to determine mount point for %s: %s\n",
1093 dest_dir_full_path, strerror(-ret));
1099 "ERROR: %s doesn't belong to btrfs mount point\n",
1100 dest_dir_full_path);
1105 r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
1106 if (r->mnt_fd < 0) {
1108 fprintf(stderr, "ERROR: failed to open %s. %s\n", r->root_path,
1114 * If we use -m or a default subvol we want to resolve the path to the
1115 * subvolume we're sitting in so that we can adjust the paths of any
1116 * subvols we want to receive in.
1118 ret = btrfs_list_get_path_rootid(r->mnt_fd, &subvol_id);
1120 fprintf(stderr, "ERROR: couldn't resolve our subvolid %d\n",
1125 root_subvol_path[0] = 0;
1126 ret = btrfs_subvolid_resolve(r->mnt_fd, root_subvol_path,
1127 PATH_MAX, subvol_id);
1129 fprintf(stderr, "ERROR: couldn't resolve our subvol path\n");
1134 * Ok we're inside of a subvol off of the root subvol, we need to
1135 * actually set full_root_path.
1137 if (strlen(root_subvol_path))
1138 r->full_root_path = root_subvol_path;
1140 if (r->dest_dir_chroot) {
1141 if (chroot(dest_dir_full_path)) {
1144 "ERROR: failed to chroot to %s, %s\n",
1152 "ERROR: failed to chdir to /, %s\n",
1156 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1157 r->root_path = strdup("/");
1158 r->dest_dir_path = r->root_path;
1161 * find_mount_root returns a root_path that is a subpath of
1162 * dest_dir_full_path. Now get the other part of root_path,
1163 * which is the destination dir relative to root_path.
1165 r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
1166 while (r->dest_dir_path[0] == '/')
1170 ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
1175 if (r->cached_capabilities_len) {
1177 fprintf(stderr, "clear cached capabilities\n");
1178 memset(r->cached_capabilities, 0,
1179 sizeof(r->cached_capabilities));
1180 r->cached_capabilities_len = 0;
1183 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
1191 close_inode_for_write(r);
1192 ret = finish_subvol(r);
1199 if (r->write_fd != -1) {
1204 r->root_path = NULL;
1205 r->dest_dir_path = NULL;
1206 free(dest_dir_full_path);
1207 subvol_uuid_search_finit(&r->sus);
1208 if (r->mnt_fd != -1) {
1212 if (r->dest_dir_fd != -1) {
1213 close(r->dest_dir_fd);
1214 r->dest_dir_fd = -1;
1220 int cmd_receive(int argc, char **argv)
1223 char fromfile[PATH_MAX];
1224 char realmnt[PATH_MAX];
1225 struct btrfs_receive r;
1226 int receive_fd = fileno(stdin);
1230 memset(&r, 0, sizeof(r));
1234 r.dest_dir_chroot = 0;
1240 static const struct option long_opts[] = {
1241 { "max-errors", required_argument, NULL, 'E' },
1242 { "chroot", no_argument, NULL, 'C' },
1243 { NULL, 0, NULL, 0 }
1246 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1255 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1257 "ERROR: input file path too long (%zu)\n",
1264 r.honor_end_cmd = 1;
1267 r.dest_dir_chroot = 1;
1270 max_errors = arg_strtou64(optarg);
1273 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1275 "ERROR: mount point path too long (%zu)\n",
1283 fprintf(stderr, "ERROR: receive args invalid.\n");
1288 if (check_argc_exact(argc - optind, 1))
1289 usage(cmd_receive_usage);
1291 tomnt = argv[optind];
1294 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1295 if (receive_fd < 0) {
1296 fprintf(stderr, "ERROR: failed to open %s\n", fromfile);
1301 ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1308 const char * const cmd_receive_usage[] = {
1309 "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1310 "Receive subvolumes from stdin.",
1311 "Receives one or more subvolumes that were previously",
1312 "sent with btrfs send. The received subvolumes are stored",
1314 "btrfs receive will fail in case a receiving subvolume",
1315 "already exists. It will also fail in case a previously",
1316 "received subvolume was changed after it was received.",
1317 "After receiving a subvolume, it is immediately set to",
1319 "-v Enable verbose debug output. Each",
1320 " occurrence of this option increases the",
1321 " verbose level more.",
1322 "-f <infile> By default, btrfs receive uses stdin",
1323 " to receive the subvolumes. Use this",
1324 " option to specify a file to use instead.",
1325 "-e Terminate after receiving an <end cmd>",
1326 " in the data stream. Without this option,",
1327 " the receiver terminates only if an error",
1328 " is recognized or on EOF.",
1329 "-C|--chroot confine the process to <mount> using chroot",
1330 "--max-errors <N> Terminate as soon as N errors happened while",
1331 " processing commands from the send stream.",
1332 " Default value is 1. A value of 0 means no limit.",
1333 "-m <mountpoint> The root mount point of the destination fs.",
1334 " If you do not have /proc use this to tell us where ",
1335 " this file system is mounted.",