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"
55 static int g_verbose = 0;
63 char write_path[PATH_MAX];
66 char *dest_dir_path; /* relative to root_path */
67 char full_subvol_path[PATH_MAX];
71 struct subvol_info cur_subvol;
73 * Substitute for cur_subvol::path which is a pointer and we cannot
74 * change it to an array as it's a public API.
76 char cur_subvol_path[PATH_MAX];
78 struct subvol_uuid_search sus;
83 * Buffer to store capabilities from security.capabilities xattr,
84 * usually 20 bytes, but make same room for potentially larger
85 * encodings. Must be set only once per file, denoted by length > 0.
87 char cached_capabilities[64];
88 int cached_capabilities_len;
91 static int finish_subvol(struct btrfs_receive *rctx)
95 struct btrfs_ioctl_received_subvol_args rs_args;
96 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
99 if (rctx->cur_subvol_path[0] == 0)
102 subvol_fd = openat(rctx->mnt_fd, rctx->cur_subvol_path,
103 O_RDONLY | O_NOATIME);
106 error("cannot open %s: %s",
107 rctx->cur_subvol_path, strerror(-ret));
111 memset(&rs_args, 0, sizeof(rs_args));
112 memcpy(rs_args.uuid, rctx->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
113 rs_args.stransid = rctx->cur_subvol.stransid;
115 if (g_verbose >= 1) {
116 uuid_unparse((u8*)rs_args.uuid, uuid_str);
117 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
118 "stransid=%llu\n", uuid_str, rs_args.stransid);
121 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
124 error("ioctl BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s",
128 rctx->cur_subvol.rtransid = rs_args.rtransid;
130 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
133 error("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed: %s",
138 flags |= BTRFS_SUBVOL_RDONLY;
140 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
143 error("failed to make subvolume read only: %s",
151 if (rctx->cur_subvol_path[0]) {
152 rctx->cur_subvol_path[0] = 0;
159 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
163 struct btrfs_receive *rctx = user;
164 struct btrfs_ioctl_vol_args args_v1;
165 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
167 ret = finish_subvol(rctx);
171 if (rctx->cur_subvol.path) {
172 error("subvol: another one already started, path ptr: %s",
173 rctx->cur_subvol.path);
177 if (rctx->cur_subvol_path[0]) {
178 error("subvol: another one already started, path buf: %s",
179 rctx->cur_subvol.path);
184 if (*rctx->dest_dir_path == 0) {
185 strncpy_null(rctx->cur_subvol_path, path);
187 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
190 error("subvol: path invalid: %s", path);
194 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
195 rctx->dest_dir_path, path);
197 error("subvol: path invalid: %s", path);
201 fprintf(stderr, "At subvol %s\n", path);
203 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
204 rctx->cur_subvol.stransid = ctransid;
207 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
208 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
210 rctx->cur_subvol.stransid);
213 memset(&args_v1, 0, sizeof(args_v1));
214 strncpy_null(args_v1.name, path);
215 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
218 error("creating subvolume %s failed: %s", path, strerror(-ret));
226 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
227 const u8 *parent_uuid, u64 parent_ctransid,
231 struct btrfs_receive *rctx = user;
232 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
233 struct btrfs_ioctl_vol_args_v2 args_v2;
234 struct subvol_info *parent_subvol = NULL;
236 ret = finish_subvol(rctx);
240 if (rctx->cur_subvol.path) {
241 error("snapshot: another one already started, path ptr: %s",
242 rctx->cur_subvol.path);
246 if (rctx->cur_subvol_path[0]) {
247 error("snapshot: another one already started, path buf: %s",
248 rctx->cur_subvol.path);
253 if (*rctx->dest_dir_path == 0) {
254 strncpy_null(rctx->cur_subvol_path, path);
256 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
259 error("snapshot: path invalid: %s", path);
263 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
264 rctx->dest_dir_path, path);
266 error("snapshot: path invalid: %s", path);
270 fprintf(stdout, "At snapshot %s\n", path);
272 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
273 rctx->cur_subvol.stransid = ctransid;
276 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
277 fprintf(stderr, "receiving snapshot %s uuid=%s, "
278 "ctransid=%llu ", path, uuid_str,
279 rctx->cur_subvol.stransid);
280 uuid_unparse(parent_uuid, uuid_str);
281 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
282 uuid_str, parent_ctransid);
285 memset(&args_v2, 0, sizeof(args_v2));
286 strncpy_null(args_v2.name, path);
288 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
289 parent_ctransid, NULL,
290 subvol_search_by_received_uuid);
291 if (IS_ERR_OR_NULL(parent_subvol)) {
292 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
293 parent_ctransid, NULL,
294 subvol_search_by_uuid);
296 if (IS_ERR_OR_NULL(parent_subvol)) {
300 ret = PTR_ERR(parent_subvol);
301 error("cannot find parent subvolume");
306 * The path is resolved from the root subvol, but we could be in some
307 * subvolume under the root subvolume, so try and adjust the path to be
308 * relative to our root path.
310 if (rctx->full_root_path) {
314 root_len = strlen(rctx->full_root_path);
315 sub_len = strlen(parent_subvol->path);
317 /* First make sure the parent subvol is actually in our path */
318 if (sub_len < root_len ||
319 strstr(parent_subvol->path, rctx->full_root_path) == NULL) {
321 "parent subvol is not reachable from inside the root subvol");
326 if (sub_len == root_len) {
327 parent_subvol->path[0] = '/';
328 parent_subvol->path[1] = '\0';
331 * root path is foo/bar
332 * subvol path is foo/bar/baz
334 * we need to have baz be the path, so we need to move
335 * the bit after foo/bar/, so path + root_len + 1, and
336 * move the part we care about, so sub_len - root_len -
339 memmove(parent_subvol->path,
340 parent_subvol->path + root_len + 1,
341 sub_len - root_len - 1);
342 parent_subvol->path[sub_len - root_len - 1] = '\0';
345 /*if (rs_args.ctransid > rs_args.rtransid) {
348 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
351 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
355 if (*parent_subvol->path == 0)
356 args_v2.fd = dup(rctx->mnt_fd);
358 args_v2.fd = openat(rctx->mnt_fd, parent_subvol->path,
359 O_RDONLY | O_NOATIME);
360 if (args_v2.fd < 0) {
363 error("cannot open %s: %s",
364 parent_subvol->path, strerror(-ret));
367 "It seems that you have changed your default "
368 "subvolume or you specify other subvolume to\n"
369 "mount btrfs, try to remount this btrfs filesystem "
370 "with fs tree, and run btrfs receive again!\n");
374 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
378 error("creating snapshot %s -> %s failed: %s",
379 parent_subvol->path, path, strerror(-ret));
385 free(parent_subvol->path);
391 static int process_mkfile(const char *path, void *user)
394 struct btrfs_receive *rctx = user;
395 char full_path[PATH_MAX];
397 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
399 error("mkfile: path invalid: %s", path);
404 fprintf(stderr, "mkfile %s\n", path);
406 ret = creat(full_path, 0600);
409 error("mkfile %s failed: %s", path, strerror(-ret));
419 static int process_mkdir(const char *path, void *user)
422 struct btrfs_receive *rctx = user;
423 char full_path[PATH_MAX];
425 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
427 error("mkdir: path invalid: %s", path);
432 fprintf(stderr, "mkdir %s\n", path);
434 ret = mkdir(full_path, 0700);
437 error("mkdir %s failed: %s", path, strerror(-ret));
444 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
447 struct btrfs_receive *rctx = user;
448 char full_path[PATH_MAX];
450 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
452 error("mknod: path invalid: %s", path);
457 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
460 ret = mknod(full_path, mode & S_IFMT, dev);
463 error("mknod %s failed: %s", path, strerror(-ret));
470 static int process_mkfifo(const char *path, void *user)
473 struct btrfs_receive *rctx = user;
474 char full_path[PATH_MAX];
476 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
478 error("mkfifo: path invalid: %s", path);
483 fprintf(stderr, "mkfifo %s\n", path);
485 ret = mkfifo(full_path, 0600);
488 error("mkfifo %s failed: %s", path, strerror(-ret));
495 static int process_mksock(const char *path, void *user)
498 struct btrfs_receive *rctx = user;
499 char full_path[PATH_MAX];
501 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
503 error("mksock: path invalid: %s", path);
508 fprintf(stderr, "mksock %s\n", path);
510 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
513 error("mknod %s failed: %s", path, strerror(-ret));
520 static int process_symlink(const char *path, const char *lnk, void *user)
523 struct btrfs_receive *rctx = user;
524 char full_path[PATH_MAX];
526 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
528 error("symlink: path invalid: %s", path);
533 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
535 ret = symlink(lnk, full_path);
538 error("symlink %s -> %s failed: %s", path,
539 lnk, strerror(-ret));
546 static int process_rename(const char *from, const char *to, void *user)
549 struct btrfs_receive *rctx = user;
550 char full_from[PATH_MAX];
551 char full_to[PATH_MAX];
553 ret = path_cat_out(full_from, rctx->full_subvol_path, from);
555 error("rename: source path invalid: %s", from);
559 ret = path_cat_out(full_to, rctx->full_subvol_path, to);
561 error("rename: target path invalid: %s", to);
566 fprintf(stderr, "rename %s -> %s\n", from, to);
568 ret = rename(full_from, full_to);
571 error("rename %s -> %s failed: %s", from,
579 static int process_link(const char *path, const char *lnk, void *user)
582 struct btrfs_receive *rctx = user;
583 char full_path[PATH_MAX];
584 char full_link_path[PATH_MAX];
586 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
588 error("link: source path invalid: %s", full_path);
592 ret = path_cat_out(full_link_path, rctx->full_subvol_path, lnk);
594 error("link: target path invalid: %s", full_link_path);
599 fprintf(stderr, "link %s -> %s\n", path, lnk);
601 ret = link(full_link_path, full_path);
604 error("link %s -> %s failed: %s", path, lnk, strerror(-ret));
612 static int process_unlink(const char *path, void *user)
615 struct btrfs_receive *rctx = user;
616 char full_path[PATH_MAX];
618 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
620 error("unlink: path invalid: %s", path);
625 fprintf(stderr, "unlink %s\n", path);
627 ret = unlink(full_path);
630 error("unlink %s failed. %s", path, strerror(-ret));
637 static int process_rmdir(const char *path, void *user)
640 struct btrfs_receive *rctx = user;
641 char full_path[PATH_MAX];
643 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
645 error("rmdir: path invalid: %s", path);
650 fprintf(stderr, "rmdir %s\n", path);
652 ret = rmdir(full_path);
655 error("rmdir %s failed: %s", path, strerror(-ret));
662 static int open_inode_for_write(struct btrfs_receive *rctx, const char *path)
666 if (rctx->write_fd != -1) {
667 if (strcmp(rctx->write_path, path) == 0)
669 close(rctx->write_fd);
673 rctx->write_fd = open(path, O_RDWR);
674 if (rctx->write_fd < 0) {
676 error("cannot open %s: %s", path, strerror(-ret));
679 strncpy_null(rctx->write_path, path);
685 static void close_inode_for_write(struct btrfs_receive *rctx)
687 if(rctx->write_fd == -1)
690 close(rctx->write_fd);
692 rctx->write_path[0] = 0;
695 static int process_write(const char *path, const void *data, u64 offset,
699 struct btrfs_receive *rctx = user;
700 char full_path[PATH_MAX];
704 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
706 error("write: path invalid: %s", path);
710 ret = open_inode_for_write(rctx, full_path);
715 w = pwrite(rctx->write_fd, (char*)data + pos, len - pos,
719 error("writing to %s failed: %s",
720 path, strerror(-ret));
730 static int process_clone(const char *path, u64 offset, u64 len,
731 const u8 *clone_uuid, u64 clone_ctransid,
732 const char *clone_path, u64 clone_offset,
736 struct btrfs_receive *rctx = user;
737 struct btrfs_ioctl_clone_range_args clone_args;
738 struct subvol_info *si = NULL;
739 char full_path[PATH_MAX];
740 char *subvol_path = NULL;
741 char full_clone_path[PATH_MAX];
744 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
746 error("clone: source path invalid: %s", path);
750 ret = open_inode_for_write(rctx, full_path);
754 si = subvol_uuid_search(&rctx->sus, 0, clone_uuid, clone_ctransid,
756 subvol_search_by_received_uuid);
757 if (IS_ERR_OR_NULL(si)) {
758 if (memcmp(clone_uuid, rctx->cur_subvol.received_uuid,
759 BTRFS_UUID_SIZE) == 0) {
760 /* TODO check generation of extent */
761 subvol_path = strdup(rctx->cur_subvol_path);
767 error("clone: did not find source subvol");
771 /*if (rs_args.ctransid > rs_args.rtransid) {
774 fprintf(stderr, "ERROR: subvolume %s was "
775 "modified after it was "
777 r->subvol_parent_name);
780 fprintf(stderr, "WARNING: subvolume %s was "
781 "modified after it was "
783 r->subvol_parent_name);
786 subvol_path = strdup(si->path);
789 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
791 error("clone: target path invalid: %s", clone_path);
795 clone_fd = openat(rctx->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
798 error("cannot open %s: %s", full_clone_path, strerror(-ret));
802 clone_args.src_fd = clone_fd;
803 clone_args.src_offset = clone_offset;
804 clone_args.src_length = len;
805 clone_args.dest_offset = offset;
806 ret = ioctl(rctx->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
809 error("failed to clone extents to %s\n%s",
810 path, strerror(-ret));
826 static int process_set_xattr(const char *path, const char *name,
827 const void *data, int len, void *user)
830 struct btrfs_receive *rctx = user;
831 char full_path[PATH_MAX];
833 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
835 error("set_xattr: path invalid: %s", path);
839 if (strcmp("security.capability", name) == 0) {
841 fprintf(stderr, "set_xattr: cache capabilities\n");
842 if (rctx->cached_capabilities_len)
843 warning("capabilities set multiple times per file: %s",
845 if (len > sizeof(rctx->cached_capabilities)) {
846 error("capabilities encoded to %d bytes, buffer too small",
851 rctx->cached_capabilities_len = len;
852 memcpy(rctx->cached_capabilities, data, len);
855 if (g_verbose >= 2) {
856 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
857 "data=%.*s\n", path, name, len,
861 ret = lsetxattr(full_path, name, data, len, 0);
864 error("lsetxattr %s %s=%.*s failed: %s",
865 path, name, len, (char*)data, strerror(-ret));
873 static int process_remove_xattr(const char *path, const char *name, void *user)
876 struct btrfs_receive *rctx = user;
877 char full_path[PATH_MAX];
879 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
881 error("remove_xattr: path invalid: %s", path);
885 if (g_verbose >= 2) {
886 fprintf(stderr, "remove_xattr %s - name=%s\n",
890 ret = lremovexattr(full_path, name);
893 error("lremovexattr %s %s failed: %s",
894 path, name, strerror(-ret));
902 static int process_truncate(const char *path, u64 size, void *user)
905 struct btrfs_receive *rctx = user;
906 char full_path[PATH_MAX];
908 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
910 error("truncate: path invalid: %s", path);
915 fprintf(stderr, "truncate %s size=%llu\n", path, size);
917 ret = truncate(full_path, size);
920 error("truncate %s failed: %s", path, strerror(-ret));
928 static int process_chmod(const char *path, u64 mode, void *user)
931 struct btrfs_receive *rctx = user;
932 char full_path[PATH_MAX];
934 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
936 error("chmod: path invalid: %s", path);
941 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
943 ret = chmod(full_path, mode);
946 error("chmod %s failed: %s", path, strerror(-ret));
954 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
957 struct btrfs_receive *rctx = user;
958 char full_path[PATH_MAX];
960 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
962 error("chown: path invalid: %s", path);
967 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
970 ret = lchown(full_path, uid, gid);
973 error("chown %s failed: %s", path, strerror(-ret));
977 if (rctx->cached_capabilities_len) {
979 fprintf(stderr, "chown: restore capabilities\n");
980 ret = lsetxattr(full_path, "security.capability",
981 rctx->cached_capabilities,
982 rctx->cached_capabilities_len, 0);
983 memset(rctx->cached_capabilities, 0,
984 sizeof(rctx->cached_capabilities));
985 rctx->cached_capabilities_len = 0;
988 error("restoring capabilities %s: %s",
989 path, strerror(-ret));
998 static int process_utimes(const char *path, struct timespec *at,
999 struct timespec *mt, struct timespec *ct,
1003 struct btrfs_receive *rctx = user;
1004 char full_path[PATH_MAX];
1005 struct timespec tv[2];
1007 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
1009 error("utimes: path invalid: %s", path);
1014 fprintf(stderr, "utimes %s\n", path);
1018 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1021 error("utimes %s failed: %s",
1022 path, strerror(-ret));
1030 static int process_update_extent(const char *path, u64 offset, u64 len,
1034 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1035 path, (unsigned long long)offset,
1036 (unsigned long long)len);
1039 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1045 static struct btrfs_send_ops send_ops = {
1046 .subvol = process_subvol,
1047 .snapshot = process_snapshot,
1048 .mkfile = process_mkfile,
1049 .mkdir = process_mkdir,
1050 .mknod = process_mknod,
1051 .mkfifo = process_mkfifo,
1052 .mksock = process_mksock,
1053 .symlink = process_symlink,
1054 .rename = process_rename,
1055 .link = process_link,
1056 .unlink = process_unlink,
1057 .rmdir = process_rmdir,
1058 .write = process_write,
1059 .clone = process_clone,
1060 .set_xattr = process_set_xattr,
1061 .remove_xattr = process_remove_xattr,
1062 .truncate = process_truncate,
1063 .chmod = process_chmod,
1064 .chown = process_chown,
1065 .utimes = process_utimes,
1066 .update_extent = process_update_extent,
1069 static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
1070 char *realmnt, int r_fd, u64 max_errors)
1074 char *dest_dir_full_path;
1075 char root_subvol_path[PATH_MAX];
1079 dest_dir_full_path = realpath(tomnt, NULL);
1080 if (!dest_dir_full_path) {
1082 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1085 rctx->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1086 if (rctx->dest_dir_fd < 0) {
1088 error("cannot open destination directory %s: %s",
1089 dest_dir_full_path, strerror(-ret));
1094 rctx->root_path = realmnt;
1096 ret = find_mount_root(dest_dir_full_path, &rctx->root_path);
1098 error("failed to determine mount point for %s: %s",
1099 dest_dir_full_path, strerror(-ret));
1104 error("%s doesn't belong to btrfs mount point",
1105 dest_dir_full_path);
1110 rctx->mnt_fd = open(rctx->root_path, O_RDONLY | O_NOATIME);
1111 if (rctx->mnt_fd < 0) {
1113 error("cannot open %s: %s", rctx->root_path, strerror(-ret));
1118 * If we use -m or a default subvol we want to resolve the path to the
1119 * subvolume we're sitting in so that we can adjust the paths of any
1120 * subvols we want to receive in.
1122 ret = btrfs_list_get_path_rootid(rctx->mnt_fd, &subvol_id);
1126 root_subvol_path[0] = 0;
1127 ret = btrfs_subvolid_resolve(rctx->mnt_fd, root_subvol_path,
1128 PATH_MAX, subvol_id);
1130 error("cannot resolve our subvol path");
1135 * Ok we're inside of a subvol off of the root subvol, we need to
1136 * actually set full_root_path.
1138 if (*root_subvol_path)
1139 rctx->full_root_path = root_subvol_path;
1141 if (rctx->dest_dir_chroot) {
1142 if (chroot(dest_dir_full_path)) {
1144 error("failed to chroot to %s: %s",
1145 dest_dir_full_path, strerror(-ret));
1150 error("failed to chdir to / after chroot: %s",
1154 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1155 rctx->root_path = strdup("/");
1156 rctx->dest_dir_path = rctx->root_path;
1159 * find_mount_root returns a root_path that is a subpath of
1160 * dest_dir_full_path. Now get the other part of root_path,
1161 * which is the destination dir relative to root_path.
1163 rctx->dest_dir_path = dest_dir_full_path + strlen(rctx->root_path);
1164 while (rctx->dest_dir_path[0] == '/')
1165 rctx->dest_dir_path++;
1168 ret = subvol_uuid_search_init(rctx->mnt_fd, &rctx->sus);
1174 if (rctx->cached_capabilities_len) {
1176 fprintf(stderr, "clear cached capabilities\n");
1177 memset(rctx->cached_capabilities, 0,
1178 sizeof(rctx->cached_capabilities));
1179 rctx->cached_capabilities_len = 0;
1182 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops,
1184 rctx->honor_end_cmd,
1188 /* Empty stream is invalid */
1189 if (ret && count == 0) {
1190 error("empty stream is not considered valid");
1198 close_inode_for_write(rctx);
1199 ret = finish_subvol(rctx);
1206 if (rctx->write_fd != -1) {
1207 close(rctx->write_fd);
1208 rctx->write_fd = -1;
1211 if (rctx->root_path != realmnt)
1212 free(rctx->root_path);
1213 rctx->root_path = NULL;
1214 rctx->dest_dir_path = NULL;
1215 free(dest_dir_full_path);
1216 subvol_uuid_search_finit(&rctx->sus);
1217 if (rctx->mnt_fd != -1) {
1218 close(rctx->mnt_fd);
1221 if (rctx->dest_dir_fd != -1) {
1222 close(rctx->dest_dir_fd);
1223 rctx->dest_dir_fd = -1;
1229 int cmd_receive(int argc, char **argv)
1232 char fromfile[PATH_MAX];
1233 char realmnt[PATH_MAX];
1234 struct btrfs_receive rctx;
1235 int receive_fd = fileno(stdin);
1240 memset(&rctx, 0, sizeof(rctx));
1243 rctx.dest_dir_fd = -1;
1244 rctx.dest_dir_chroot = 0;
1250 enum { GETOPT_VAL_DUMP = 257 };
1251 static const struct option long_opts[] = {
1252 { "max-errors", required_argument, NULL, 'E' },
1253 { "chroot", no_argument, NULL, 'C' },
1254 { "dump", no_argument, NULL, GETOPT_VAL_DUMP },
1255 { NULL, 0, NULL, 0 }
1258 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1267 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1268 error("input file path too long (%zu)",
1275 rctx.honor_end_cmd = 1;
1278 rctx.dest_dir_chroot = 1;
1281 max_errors = arg_strtou64(optarg);
1284 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1285 error("mount point path too long (%zu)",
1291 case GETOPT_VAL_DUMP:
1296 error("receive args invalid");
1301 if (dump && check_argc_exact(argc - optind, 0))
1302 usage(cmd_receive_usage);
1303 if (!dump && check_argc_exact(argc - optind, 1))
1304 usage(cmd_receive_usage);
1306 tomnt = argv[optind];
1309 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1310 if (receive_fd < 0) {
1311 error("cannot open %s: %s", fromfile, strerror(errno));
1317 struct btrfs_dump_send_args dump_args;
1319 dump_args.root_path[0] = '.';
1320 dump_args.root_path[1] = '\0';
1321 dump_args.full_subvol_path[0] = '.';
1322 dump_args.full_subvol_path[1] = '\0';
1323 ret = btrfs_read_and_process_send_stream(receive_fd,
1324 &btrfs_print_send_ops, &dump_args, 0, 0);
1326 error("failed to dump the send stream: %s",
1329 ret = do_receive(&rctx, tomnt, realmnt, receive_fd, max_errors);
1332 if (receive_fd != fileno(stdin))
1339 const char * const cmd_receive_usage[] = {
1340 "btrfs receive [options] <mount>\n"
1341 "btrfs receive --dump [options]",
1342 "Receive subvolumes from a stream",
1343 "Receives one or more subvolumes that were previously",
1344 "sent with btrfs send. The received subvolumes are stored",
1346 "The receive will fail in case the receiving subvolume",
1347 "already exists. It will also fail in case a previously",
1348 "received subvolume has been changed after it was received.",
1349 "After receiving a subvolume, it is immediately set to",
1352 "-v increase verbosity about performed actions",
1353 "-f FILE read the stream from FILE instead of stdin",
1354 "-e terminate after receiving an <end cmd> marker in the stream.",
1355 " Without this option the receiver side terminates only in case",
1356 " of an error on end of file.",
1357 "-C|--chroot confine the process to <mount> using chroot",
1358 "-E|--max-errors NERR",
1359 " terminate as soon as NERR errors occur while",
1360 " stream processing commands from the stream.",
1361 " Default value is 1. A value of 0 means no limit.",
1362 "-m ROOTMOUNT the root mount point of the destination filesystem.",
1363 " If /proc is not accessible, use this to tell us where",
1364 " this file system is mounted.",
1365 "--dump dump stream metadata, one line per operation,",
1366 " does not require the MOUNT parameter",