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"
20 #include "androidcompat.h"
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
38 #include <sys/types.h>
39 #include <sys/xattr.h>
40 #include <uuid/uuid.h>
47 #include "btrfs-list.h"
50 #include "send-stream.h"
51 #include "send-utils.h"
52 #include "send-dump.h"
54 static int g_verbose = 0;
62 char write_path[PATH_MAX];
65 char *dest_dir_path; /* relative to root_path */
66 char full_subvol_path[PATH_MAX];
70 struct subvol_info cur_subvol;
72 * Substitute for cur_subvol::path which is a pointer and we cannot
73 * change it to an array as it's a public API.
75 char cur_subvol_path[PATH_MAX];
77 struct subvol_uuid_search sus;
82 * Buffer to store capabilities from security.capabilities xattr,
83 * usually 20 bytes, but make same room for potentially larger
84 * encodings. Must be set only once per file, denoted by length > 0.
86 char cached_capabilities[64];
87 int cached_capabilities_len;
90 static int finish_subvol(struct btrfs_receive *rctx)
94 struct btrfs_ioctl_received_subvol_args rs_args;
95 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
98 if (rctx->cur_subvol_path[0] == 0)
101 subvol_fd = openat(rctx->mnt_fd, rctx->cur_subvol_path,
102 O_RDONLY | O_NOATIME);
105 error("cannot open %s: %s",
106 rctx->cur_subvol_path, strerror(-ret));
110 memset(&rs_args, 0, sizeof(rs_args));
111 memcpy(rs_args.uuid, rctx->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
112 rs_args.stransid = rctx->cur_subvol.stransid;
114 if (g_verbose >= 1) {
115 uuid_unparse((u8*)rs_args.uuid, uuid_str);
116 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
117 "stransid=%llu\n", uuid_str, rs_args.stransid);
120 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
123 error("ioctl BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s",
127 rctx->cur_subvol.rtransid = rs_args.rtransid;
129 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
132 error("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed: %s",
137 flags |= BTRFS_SUBVOL_RDONLY;
139 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
142 error("failed to make subvolume read only: %s",
150 if (rctx->cur_subvol_path[0]) {
151 rctx->cur_subvol_path[0] = 0;
158 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
162 struct btrfs_receive *rctx = user;
163 struct btrfs_ioctl_vol_args args_v1;
164 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
166 ret = finish_subvol(rctx);
170 if (rctx->cur_subvol.path) {
171 error("subvol: another one already started, path ptr: %s",
172 rctx->cur_subvol.path);
176 if (rctx->cur_subvol_path[0]) {
177 error("subvol: another one already started, path buf: %s",
178 rctx->cur_subvol.path);
183 if (*rctx->dest_dir_path == 0) {
184 strncpy_null(rctx->cur_subvol_path, path);
186 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
189 error("subvol: path invalid: %s", path);
193 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
194 rctx->dest_dir_path, path);
196 error("subvol: path invalid: %s", path);
200 fprintf(stderr, "At subvol %s\n", path);
202 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
203 rctx->cur_subvol.stransid = ctransid;
206 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
207 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
209 rctx->cur_subvol.stransid);
212 memset(&args_v1, 0, sizeof(args_v1));
213 strncpy_null(args_v1.name, path);
214 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
217 error("creating subvolume %s failed: %s", path, strerror(-ret));
225 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
226 const u8 *parent_uuid, u64 parent_ctransid,
230 struct btrfs_receive *rctx = user;
231 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
232 struct btrfs_ioctl_vol_args_v2 args_v2;
233 struct subvol_info *parent_subvol = NULL;
235 ret = finish_subvol(rctx);
239 if (rctx->cur_subvol.path) {
240 error("snapshot: another one already started, path ptr: %s",
241 rctx->cur_subvol.path);
245 if (rctx->cur_subvol_path[0]) {
246 error("snapshot: another one already started, path buf: %s",
247 rctx->cur_subvol.path);
252 if (*rctx->dest_dir_path == 0) {
253 strncpy_null(rctx->cur_subvol_path, path);
255 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
258 error("snapshot: path invalid: %s", path);
262 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
263 rctx->dest_dir_path, path);
265 error("snapshot: path invalid: %s", path);
269 fprintf(stdout, "At snapshot %s\n", path);
271 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
272 rctx->cur_subvol.stransid = ctransid;
275 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
276 fprintf(stderr, "receiving snapshot %s uuid=%s, "
277 "ctransid=%llu ", path, uuid_str,
278 rctx->cur_subvol.stransid);
279 uuid_unparse(parent_uuid, uuid_str);
280 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
281 uuid_str, parent_ctransid);
284 memset(&args_v2, 0, sizeof(args_v2));
285 strncpy_null(args_v2.name, path);
287 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
288 parent_ctransid, NULL,
289 subvol_search_by_received_uuid);
290 if (IS_ERR(parent_subvol)) {
291 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
292 parent_ctransid, NULL,
293 subvol_search_by_uuid);
295 if (IS_ERR(parent_subvol)) {
296 ret = PTR_ERR(parent_subvol);
297 error("cannot find parent subvolume");
302 * The path is resolved from the root subvol, but we could be in some
303 * subvolume under the root subvolume, so try and adjust the path to be
304 * relative to our root path.
306 if (rctx->full_root_path) {
310 root_len = strlen(rctx->full_root_path);
311 sub_len = strlen(parent_subvol->path);
313 /* First make sure the parent subvol is actually in our path */
314 if (sub_len < root_len ||
315 strstr(parent_subvol->path, rctx->full_root_path) == NULL) {
317 "parent subvol is not reachable from inside the root subvol");
322 if (sub_len == root_len) {
323 parent_subvol->path[0] = '/';
324 parent_subvol->path[1] = '\0';
327 * root path is foo/bar
328 * subvol path is foo/bar/baz
330 * we need to have baz be the path, so we need to move
331 * the bit after foo/bar/, so path + root_len + 1, and
332 * move the part we care about, so sub_len - root_len -
335 memmove(parent_subvol->path,
336 parent_subvol->path + root_len + 1,
337 sub_len - root_len - 1);
338 parent_subvol->path[sub_len - root_len - 1] = '\0';
341 /*if (rs_args.ctransid > rs_args.rtransid) {
344 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
347 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
351 if (*parent_subvol->path == 0)
352 args_v2.fd = dup(rctx->mnt_fd);
354 args_v2.fd = openat(rctx->mnt_fd, parent_subvol->path,
355 O_RDONLY | O_NOATIME);
356 if (args_v2.fd < 0) {
359 error("cannot open %s: %s",
360 parent_subvol->path, strerror(-ret));
363 "It seems that you have changed your default "
364 "subvolume or you specify other subvolume to\n"
365 "mount btrfs, try to remount this btrfs filesystem "
366 "with fs tree, and run btrfs receive again!\n");
370 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
374 error("creating snapshot %s -> %s failed: %s",
375 parent_subvol->path, path, strerror(-ret));
381 free(parent_subvol->path);
387 static int process_mkfile(const char *path, void *user)
390 struct btrfs_receive *rctx = user;
391 char full_path[PATH_MAX];
393 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
395 error("mkfile: path invalid: %s", path);
400 fprintf(stderr, "mkfile %s\n", path);
402 ret = creat(full_path, 0600);
405 error("mkfile %s failed: %s", path, strerror(-ret));
415 static int process_mkdir(const char *path, void *user)
418 struct btrfs_receive *rctx = user;
419 char full_path[PATH_MAX];
421 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
423 error("mkdir: path invalid: %s", path);
428 fprintf(stderr, "mkdir %s\n", path);
430 ret = mkdir(full_path, 0700);
433 error("mkdir %s failed: %s", path, strerror(-ret));
440 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
443 struct btrfs_receive *rctx = user;
444 char full_path[PATH_MAX];
446 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
448 error("mknod: path invalid: %s", path);
453 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
456 ret = mknod(full_path, mode & S_IFMT, dev);
459 error("mknod %s failed: %s", path, strerror(-ret));
466 static int process_mkfifo(const char *path, void *user)
469 struct btrfs_receive *rctx = user;
470 char full_path[PATH_MAX];
472 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
474 error("mkfifo: path invalid: %s", path);
479 fprintf(stderr, "mkfifo %s\n", path);
481 ret = mkfifo(full_path, 0600);
484 error("mkfifo %s failed: %s", path, strerror(-ret));
491 static int process_mksock(const char *path, void *user)
494 struct btrfs_receive *rctx = user;
495 char full_path[PATH_MAX];
497 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
499 error("mksock: path invalid: %s", path);
504 fprintf(stderr, "mksock %s\n", path);
506 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
509 error("mknod %s failed: %s", path, strerror(-ret));
516 static int process_symlink(const char *path, const char *lnk, void *user)
519 struct btrfs_receive *rctx = user;
520 char full_path[PATH_MAX];
522 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
524 error("symlink: path invalid: %s", path);
529 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
531 ret = symlink(lnk, full_path);
534 error("symlink %s -> %s failed: %s", path,
535 lnk, strerror(-ret));
542 static int process_rename(const char *from, const char *to, void *user)
545 struct btrfs_receive *rctx = user;
546 char full_from[PATH_MAX];
547 char full_to[PATH_MAX];
549 ret = path_cat_out(full_from, rctx->full_subvol_path, from);
551 error("rename: source path invalid: %s", from);
555 ret = path_cat_out(full_to, rctx->full_subvol_path, to);
557 error("rename: target path invalid: %s", to);
562 fprintf(stderr, "rename %s -> %s\n", from, to);
564 ret = rename(full_from, full_to);
567 error("rename %s -> %s failed: %s", from,
575 static int process_link(const char *path, const char *lnk, void *user)
578 struct btrfs_receive *rctx = user;
579 char full_path[PATH_MAX];
580 char full_link_path[PATH_MAX];
582 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
584 error("link: source path invalid: %s", full_path);
588 ret = path_cat_out(full_link_path, rctx->full_subvol_path, lnk);
590 error("link: target path invalid: %s", full_link_path);
595 fprintf(stderr, "link %s -> %s\n", path, lnk);
597 ret = link(full_link_path, full_path);
600 error("link %s -> %s failed: %s", path, lnk, strerror(-ret));
608 static int process_unlink(const char *path, void *user)
611 struct btrfs_receive *rctx = user;
612 char full_path[PATH_MAX];
614 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
616 error("unlink: path invalid: %s", path);
621 fprintf(stderr, "unlink %s\n", path);
623 ret = unlink(full_path);
626 error("unlink %s failed. %s", path, strerror(-ret));
633 static int process_rmdir(const char *path, void *user)
636 struct btrfs_receive *rctx = user;
637 char full_path[PATH_MAX];
639 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
641 error("rmdir: path invalid: %s", path);
646 fprintf(stderr, "rmdir %s\n", path);
648 ret = rmdir(full_path);
651 error("rmdir %s failed: %s", path, strerror(-ret));
658 static int open_inode_for_write(struct btrfs_receive *rctx, const char *path)
662 if (rctx->write_fd != -1) {
663 if (strcmp(rctx->write_path, path) == 0)
665 close(rctx->write_fd);
669 rctx->write_fd = open(path, O_RDWR);
670 if (rctx->write_fd < 0) {
672 error("cannot open %s: %s", path, strerror(-ret));
675 strncpy_null(rctx->write_path, path);
681 static void close_inode_for_write(struct btrfs_receive *rctx)
683 if(rctx->write_fd == -1)
686 close(rctx->write_fd);
688 rctx->write_path[0] = 0;
691 static int process_write(const char *path, const void *data, u64 offset,
695 struct btrfs_receive *rctx = user;
696 char full_path[PATH_MAX];
700 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
702 error("write: path invalid: %s", path);
706 ret = open_inode_for_write(rctx, full_path);
711 w = pwrite(rctx->write_fd, (char*)data + pos, len - pos,
715 error("writing to %s failed: %s",
716 path, strerror(-ret));
726 static int process_clone(const char *path, u64 offset, u64 len,
727 const u8 *clone_uuid, u64 clone_ctransid,
728 const char *clone_path, u64 clone_offset,
732 struct btrfs_receive *rctx = user;
733 struct btrfs_ioctl_clone_range_args clone_args;
734 struct subvol_info *si = NULL;
735 char full_path[PATH_MAX];
736 char *subvol_path = NULL;
737 char full_clone_path[PATH_MAX];
740 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
742 error("clone: source path invalid: %s", path);
746 ret = open_inode_for_write(rctx, full_path);
750 si = subvol_uuid_search(&rctx->sus, 0, clone_uuid, clone_ctransid,
752 subvol_search_by_received_uuid);
754 if (memcmp(clone_uuid, rctx->cur_subvol.received_uuid,
755 BTRFS_UUID_SIZE) == 0) {
756 /* TODO check generation of extent */
757 subvol_path = strdup(rctx->cur_subvol_path);
760 error("clone: did not find source subvol");
764 /*if (rs_args.ctransid > rs_args.rtransid) {
767 fprintf(stderr, "ERROR: subvolume %s was "
768 "modified after it was "
770 r->subvol_parent_name);
773 fprintf(stderr, "WARNING: subvolume %s was "
774 "modified after it was "
776 r->subvol_parent_name);
779 subvol_path = strdup(si->path);
782 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
784 error("clone: target path invalid: %s", clone_path);
788 clone_fd = openat(rctx->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
791 error("cannot open %s: %s", full_clone_path, strerror(-ret));
795 clone_args.src_fd = clone_fd;
796 clone_args.src_offset = clone_offset;
797 clone_args.src_length = len;
798 clone_args.dest_offset = offset;
799 ret = ioctl(rctx->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
802 error("failed to clone extents to %s\n%s",
803 path, strerror(-ret));
819 static int process_set_xattr(const char *path, const char *name,
820 const void *data, int len, void *user)
823 struct btrfs_receive *rctx = user;
824 char full_path[PATH_MAX];
826 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
828 error("set_xattr: path invalid: %s", path);
832 if (strcmp("security.capability", name) == 0) {
834 fprintf(stderr, "set_xattr: cache capabilities\n");
835 if (rctx->cached_capabilities_len)
836 warning("capabilities set multiple times per file: %s",
838 if (len > sizeof(rctx->cached_capabilities)) {
839 error("capabilities encoded to %d bytes, buffer too small",
844 rctx->cached_capabilities_len = len;
845 memcpy(rctx->cached_capabilities, data, len);
848 if (g_verbose >= 2) {
849 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
850 "data=%.*s\n", path, name, len,
854 ret = lsetxattr(full_path, name, data, len, 0);
857 error("lsetxattr %s %s=%.*s failed: %s",
858 path, name, len, (char*)data, strerror(-ret));
866 static int process_remove_xattr(const char *path, const char *name, void *user)
869 struct btrfs_receive *rctx = user;
870 char full_path[PATH_MAX];
872 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
874 error("remove_xattr: path invalid: %s", path);
878 if (g_verbose >= 2) {
879 fprintf(stderr, "remove_xattr %s - name=%s\n",
883 ret = lremovexattr(full_path, name);
886 error("lremovexattr %s %s failed: %s",
887 path, name, strerror(-ret));
895 static int process_truncate(const char *path, u64 size, void *user)
898 struct btrfs_receive *rctx = user;
899 char full_path[PATH_MAX];
901 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
903 error("truncate: path invalid: %s", path);
908 fprintf(stderr, "truncate %s size=%llu\n", path, size);
910 ret = truncate(full_path, size);
913 error("truncate %s failed: %s", path, strerror(-ret));
921 static int process_chmod(const char *path, u64 mode, void *user)
924 struct btrfs_receive *rctx = user;
925 char full_path[PATH_MAX];
927 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
929 error("chmod: path invalid: %s", path);
934 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
936 ret = chmod(full_path, mode);
939 error("chmod %s failed: %s", path, strerror(-ret));
947 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
950 struct btrfs_receive *rctx = user;
951 char full_path[PATH_MAX];
953 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
955 error("chown: path invalid: %s", path);
960 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
963 ret = lchown(full_path, uid, gid);
966 error("chown %s failed: %s", path, strerror(-ret));
970 if (rctx->cached_capabilities_len) {
972 fprintf(stderr, "chown: restore capabilities\n");
973 ret = lsetxattr(full_path, "security.capability",
974 rctx->cached_capabilities,
975 rctx->cached_capabilities_len, 0);
976 memset(rctx->cached_capabilities, 0,
977 sizeof(rctx->cached_capabilities));
978 rctx->cached_capabilities_len = 0;
981 error("restoring capabilities %s: %s",
982 path, strerror(-ret));
991 static int process_utimes(const char *path, struct timespec *at,
992 struct timespec *mt, struct timespec *ct,
996 struct btrfs_receive *rctx = user;
997 char full_path[PATH_MAX];
998 struct timespec tv[2];
1000 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
1002 error("utimes: path invalid: %s", path);
1007 fprintf(stderr, "utimes %s\n", path);
1011 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1014 error("utimes %s failed: %s",
1015 path, strerror(-ret));
1023 static int process_update_extent(const char *path, u64 offset, u64 len,
1027 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1028 path, (unsigned long long)offset,
1029 (unsigned long long)len);
1032 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1038 static struct btrfs_send_ops send_ops = {
1039 .subvol = process_subvol,
1040 .snapshot = process_snapshot,
1041 .mkfile = process_mkfile,
1042 .mkdir = process_mkdir,
1043 .mknod = process_mknod,
1044 .mkfifo = process_mkfifo,
1045 .mksock = process_mksock,
1046 .symlink = process_symlink,
1047 .rename = process_rename,
1048 .link = process_link,
1049 .unlink = process_unlink,
1050 .rmdir = process_rmdir,
1051 .write = process_write,
1052 .clone = process_clone,
1053 .set_xattr = process_set_xattr,
1054 .remove_xattr = process_remove_xattr,
1055 .truncate = process_truncate,
1056 .chmod = process_chmod,
1057 .chown = process_chown,
1058 .utimes = process_utimes,
1059 .update_extent = process_update_extent,
1062 static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
1063 char *realmnt, int r_fd, u64 max_errors)
1067 char *dest_dir_full_path;
1068 char root_subvol_path[PATH_MAX];
1072 dest_dir_full_path = realpath(tomnt, NULL);
1073 if (!dest_dir_full_path) {
1075 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1078 rctx->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1079 if (rctx->dest_dir_fd < 0) {
1081 error("cannot open destination directory %s: %s",
1082 dest_dir_full_path, strerror(-ret));
1087 rctx->root_path = realmnt;
1089 ret = find_mount_root(dest_dir_full_path, &rctx->root_path);
1091 error("failed to determine mount point for %s: %s",
1092 dest_dir_full_path, strerror(-ret));
1097 error("%s doesn't belong to btrfs mount point",
1098 dest_dir_full_path);
1103 rctx->mnt_fd = open(rctx->root_path, O_RDONLY | O_NOATIME);
1104 if (rctx->mnt_fd < 0) {
1106 error("cannot open %s: %s", rctx->root_path, strerror(-ret));
1111 * If we use -m or a default subvol we want to resolve the path to the
1112 * subvolume we're sitting in so that we can adjust the paths of any
1113 * subvols we want to receive in.
1115 ret = btrfs_list_get_path_rootid(rctx->mnt_fd, &subvol_id);
1119 root_subvol_path[0] = 0;
1120 ret = btrfs_subvolid_resolve(rctx->mnt_fd, root_subvol_path,
1121 PATH_MAX, subvol_id);
1123 error("cannot resolve our subvol path");
1128 * Ok we're inside of a subvol off of the root subvol, we need to
1129 * actually set full_root_path.
1131 if (*root_subvol_path)
1132 rctx->full_root_path = root_subvol_path;
1134 if (rctx->dest_dir_chroot) {
1135 if (chroot(dest_dir_full_path)) {
1137 error("failed to chroot to %s: %s",
1138 dest_dir_full_path, strerror(-ret));
1143 error("failed to chdir to / after chroot: %s",
1147 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1148 rctx->root_path = strdup("/");
1149 rctx->dest_dir_path = rctx->root_path;
1152 * find_mount_root returns a root_path that is a subpath of
1153 * dest_dir_full_path. Now get the other part of root_path,
1154 * which is the destination dir relative to root_path.
1156 rctx->dest_dir_path = dest_dir_full_path + strlen(rctx->root_path);
1157 while (rctx->dest_dir_path[0] == '/')
1158 rctx->dest_dir_path++;
1161 ret = subvol_uuid_search_init(rctx->mnt_fd, &rctx->sus);
1167 if (rctx->cached_capabilities_len) {
1169 fprintf(stderr, "clear cached capabilities\n");
1170 memset(rctx->cached_capabilities, 0,
1171 sizeof(rctx->cached_capabilities));
1172 rctx->cached_capabilities_len = 0;
1175 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops,
1177 rctx->honor_end_cmd,
1181 /* Empty stream is invalid */
1182 if (ret && count == 0) {
1183 error("empty stream is not considered valid");
1191 close_inode_for_write(rctx);
1192 ret = finish_subvol(rctx);
1199 if (rctx->write_fd != -1) {
1200 close(rctx->write_fd);
1201 rctx->write_fd = -1;
1204 if (rctx->root_path != realmnt)
1205 free(rctx->root_path);
1206 rctx->root_path = NULL;
1207 rctx->dest_dir_path = NULL;
1208 free(dest_dir_full_path);
1209 subvol_uuid_search_finit(&rctx->sus);
1210 if (rctx->mnt_fd != -1) {
1211 close(rctx->mnt_fd);
1214 if (rctx->dest_dir_fd != -1) {
1215 close(rctx->dest_dir_fd);
1216 rctx->dest_dir_fd = -1;
1222 int cmd_receive(int argc, char **argv)
1225 char fromfile[PATH_MAX];
1226 char realmnt[PATH_MAX];
1227 struct btrfs_receive rctx;
1228 int receive_fd = fileno(stdin);
1233 memset(&rctx, 0, sizeof(rctx));
1236 rctx.dest_dir_fd = -1;
1237 rctx.dest_dir_chroot = 0;
1243 enum { GETOPT_VAL_DUMP = 257 };
1244 static const struct option long_opts[] = {
1245 { "max-errors", required_argument, NULL, 'E' },
1246 { "chroot", no_argument, NULL, 'C' },
1247 { "dump", no_argument, NULL, GETOPT_VAL_DUMP },
1248 { NULL, 0, NULL, 0 }
1251 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1260 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1261 error("input file path too long (%zu)",
1268 rctx.honor_end_cmd = 1;
1271 rctx.dest_dir_chroot = 1;
1274 max_errors = arg_strtou64(optarg);
1277 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1278 error("mount point path too long (%zu)",
1284 case GETOPT_VAL_DUMP:
1289 error("receive args invalid");
1294 if (dump && check_argc_exact(argc - optind, 0))
1295 usage(cmd_receive_usage);
1296 if (!dump && check_argc_exact(argc - optind, 1))
1297 usage(cmd_receive_usage);
1299 tomnt = argv[optind];
1302 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1303 if (receive_fd < 0) {
1304 error("cannot open %s: %s", fromfile, strerror(errno));
1310 struct btrfs_dump_send_args dump_args;
1312 dump_args.root_path[0] = '.';
1313 dump_args.root_path[1] = '\0';
1314 dump_args.full_subvol_path[0] = '.';
1315 dump_args.full_subvol_path[1] = '\0';
1316 ret = btrfs_read_and_process_send_stream(receive_fd,
1317 &btrfs_print_send_ops, &dump_args, 0, 0);
1319 error("failed to dump the send stream: %s",
1322 ret = do_receive(&rctx, tomnt, realmnt, receive_fd, max_errors);
1325 if (receive_fd != fileno(stdin))
1332 const char * const cmd_receive_usage[] = {
1333 "btrfs receive [options] <mount>\n"
1334 "btrfs receive --dump [options]",
1335 "Receive subvolumes from a stream",
1336 "Receives one or more subvolumes that were previously",
1337 "sent with btrfs send. The received subvolumes are stored",
1339 "The receive will fail in case the receiving subvolume",
1340 "already exists. It will also fail in case a previously",
1341 "received subvolume has been changed after it was received.",
1342 "After receiving a subvolume, it is immediately set to",
1345 "-v increase verbosity about performed actions",
1346 "-f FILE read the stream from FILE instead of stdin",
1347 "-e terminate after receiving an <end cmd> marker in the stream.",
1348 " Without this option the receiver side terminates only in case",
1349 " of an error on end of file.",
1350 "-C|--chroot confine the process to <mount> using chroot",
1351 "-E|--max-errors NERR",
1352 " terminate as soon as NERR errors occur while",
1353 " stream processing commands from the stream.",
1354 " Default value is 1. A value of 0 means no limit.",
1355 "-m ROOTMOUNT the root mount point of the destination filesystem.",
1356 " If /proc is not accessible, use this to tell us where",
1357 " this file system is mounted.",
1358 "--dump dump stream metadata, one line per operation,",
1359 " does not require the MOUNT parameter",