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"
53 static int g_verbose = 0;
61 char write_path[PATH_MAX];
64 char *dest_dir_path; /* relative to root_path */
65 char full_subvol_path[PATH_MAX];
69 struct subvol_info cur_subvol;
71 * Substitute for cur_subvol::path which is a pointer and we cannot
72 * change it to an array as it's a public API.
74 char cur_subvol_path[PATH_MAX];
76 struct subvol_uuid_search sus;
81 * Buffer to store capabilities from security.capabilities xattr,
82 * usually 20 bytes, but make same room for potentially larger
83 * encodings. Must be set only once per file, denoted by length > 0.
85 char cached_capabilities[64];
86 int cached_capabilities_len;
89 static int finish_subvol(struct btrfs_receive *r)
93 struct btrfs_ioctl_received_subvol_args rs_args;
94 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
97 if (r->cur_subvol_path[0] == 0)
100 subvol_fd = openat(r->mnt_fd, r->cur_subvol_path,
101 O_RDONLY | O_NOATIME);
104 error("cannot open %s: %s\n",
105 r->cur_subvol_path, strerror(-ret));
109 memset(&rs_args, 0, sizeof(rs_args));
110 memcpy(rs_args.uuid, r->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
111 rs_args.stransid = r->cur_subvol.stransid;
113 if (g_verbose >= 1) {
114 uuid_unparse((u8*)rs_args.uuid, uuid_str);
115 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
116 "stransid=%llu\n", uuid_str, rs_args.stransid);
119 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
122 error("ioctl BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s",
126 r->cur_subvol.rtransid = rs_args.rtransid;
128 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
131 error("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed: %s",
136 flags |= BTRFS_SUBVOL_RDONLY;
138 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
141 error("failed to make subvolume read only: %s",
149 if (r->cur_subvol_path[0]) {
150 r->cur_subvol_path[0] = 0;
157 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
161 struct btrfs_receive *r = user;
162 struct btrfs_ioctl_vol_args args_v1;
163 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
165 ret = finish_subvol(r);
169 BUG_ON(r->cur_subvol.path);
170 BUG_ON(r->cur_subvol_path[0]);
172 if (*r->dest_dir_path == 0) {
173 strncpy_null(r->cur_subvol_path, path);
175 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
177 error("subvol: path invalid: %s\n", path);
181 ret = path_cat3_out(r->full_subvol_path, r->root_path,
182 r->dest_dir_path, path);
184 error("subvol: path invalid: %s", 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 error("creating subvolume %s failed: %s", 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 (*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 error("snapshot: path invalid: %s", path);
239 ret = path_cat3_out(r->full_subvol_path, r->root_path,
240 r->dest_dir_path, path);
242 error("snapshot: path invalid: %s", path);
246 fprintf(stdout, "At snapshot %s\n", path);
248 memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
249 r->cur_subvol.stransid = ctransid;
252 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
253 fprintf(stderr, "receiving snapshot %s uuid=%s, "
254 "ctransid=%llu ", path, uuid_str,
255 r->cur_subvol.stransid);
256 uuid_unparse(parent_uuid, uuid_str);
257 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
258 uuid_str, parent_ctransid);
261 memset(&args_v2, 0, sizeof(args_v2));
262 strncpy_null(args_v2.name, path);
264 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
265 parent_ctransid, NULL, subvol_search_by_received_uuid);
266 if (!parent_subvol) {
267 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
268 parent_ctransid, NULL, subvol_search_by_uuid);
270 if (!parent_subvol) {
272 error("cannot find parent subvolume");
277 * The path is resolved from the root subvol, but we could be in some
278 * subvolume under the root subvolume, so try and adjust the path to be
279 * relative to our root path.
281 if (r->full_root_path) {
285 root_len = strlen(r->full_root_path);
286 sub_len = strlen(parent_subvol->path);
288 /* First make sure the parent subvol is actually in our path */
289 if (sub_len < root_len ||
290 strstr(parent_subvol->path, r->full_root_path) == NULL) {
292 "parent subvol is not reachable from inside the root subvol");
297 if (sub_len == root_len) {
298 parent_subvol->path[0] = '/';
299 parent_subvol->path[1] = '\0';
302 * root path is foo/bar
303 * subvol path is foo/bar/baz
305 * we need to have baz be the path, so we need to move
306 * the bit after foo/bar/, so path + root_len + 1, and
307 * move the part we care about, so sub_len - root_len -
310 memmove(parent_subvol->path,
311 parent_subvol->path + root_len + 1,
312 sub_len - root_len - 1);
313 parent_subvol->path[sub_len - root_len - 1] = '\0';
316 /*if (rs_args.ctransid > rs_args.rtransid) {
319 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
322 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
326 if (*parent_subvol->path == 0)
327 args_v2.fd = dup(r->mnt_fd);
329 args_v2.fd = openat(r->mnt_fd, parent_subvol->path,
330 O_RDONLY | O_NOATIME);
331 if (args_v2.fd < 0) {
334 error("cannot open %s: %s",
335 parent_subvol->path, strerror(-ret));
338 "It seems that you have changed your default "
339 "subvolume or you specify other subvolume to\n"
340 "mount btrfs, try to remount this btrfs filesystem "
341 "with fs tree, and run btrfs receive again!\n");
345 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
349 error("creating snapshot %s -> %s failed: %s",
350 parent_subvol->path, path, strerror(-ret));
356 free(parent_subvol->path);
362 static int process_mkfile(const char *path, void *user)
365 struct btrfs_receive *r = user;
366 char full_path[PATH_MAX];
368 ret = path_cat_out(full_path, r->full_subvol_path, path);
370 error("mkfile: path invalid: %s", path);
375 fprintf(stderr, "mkfile %s\n", path);
377 ret = creat(full_path, 0600);
380 error("mkfile %s failed: %s", path, strerror(-ret));
390 static int process_mkdir(const char *path, void *user)
393 struct btrfs_receive *r = user;
394 char full_path[PATH_MAX];
396 ret = path_cat_out(full_path, r->full_subvol_path, path);
398 error("mkdir: path invalid: %s", path);
403 fprintf(stderr, "mkdir %s\n", path);
405 ret = mkdir(full_path, 0700);
408 error("mkdir %s failed: %s", path, strerror(-ret));
415 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
418 struct btrfs_receive *r = user;
419 char full_path[PATH_MAX];
421 ret = path_cat_out(full_path, r->full_subvol_path, path);
423 error("mknod: path invalid: %s", path);
428 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
431 ret = mknod(full_path, mode & S_IFMT, dev);
434 error("mknod %s failed: %s", path, strerror(-ret));
441 static int process_mkfifo(const char *path, void *user)
444 struct btrfs_receive *r = user;
445 char full_path[PATH_MAX];
447 ret = path_cat_out(full_path, r->full_subvol_path, path);
449 error("mkfifo: path invalid: %s", path);
454 fprintf(stderr, "mkfifo %s\n", path);
456 ret = mkfifo(full_path, 0600);
459 error("mkfifo %s failed: %s", path, strerror(-ret));
466 static int process_mksock(const char *path, void *user)
469 struct btrfs_receive *r = user;
470 char full_path[PATH_MAX];
472 ret = path_cat_out(full_path, r->full_subvol_path, path);
474 error("mksock: path invalid: %s", path);
479 fprintf(stderr, "mksock %s\n", path);
481 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
484 error("mknod %s failed: %s", path, strerror(-ret));
491 static int process_symlink(const char *path, const char *lnk, void *user)
494 struct btrfs_receive *r = user;
495 char full_path[PATH_MAX];
497 ret = path_cat_out(full_path, r->full_subvol_path, path);
499 error("symlink: path invalid: %s", path);
504 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
506 ret = symlink(lnk, full_path);
509 error("symlink %s -> %s failed: %s", path,
510 lnk, strerror(-ret));
517 static int process_rename(const char *from, const char *to, void *user)
520 struct btrfs_receive *r = user;
521 char full_from[PATH_MAX];
522 char full_to[PATH_MAX];
524 ret = path_cat_out(full_from, r->full_subvol_path, from);
526 error("rename: source path invalid: %s", from);
530 ret = path_cat_out(full_to, r->full_subvol_path, to);
532 error("rename: target path invalid: %s", to);
537 fprintf(stderr, "rename %s -> %s\n", from, to);
539 ret = rename(full_from, full_to);
542 error("rename %s -> %s failed: %s", from,
550 static int process_link(const char *path, const char *lnk, void *user)
553 struct btrfs_receive *r = user;
554 char full_path[PATH_MAX];
555 char full_link_path[PATH_MAX];
557 ret = path_cat_out(full_path, r->full_subvol_path, path);
559 error("link: source path invalid: %s", full_path);
563 ret = path_cat_out(full_link_path, r->full_subvol_path, lnk);
565 error("link: target path invalid: %s", full_link_path);
570 fprintf(stderr, "link %s -> %s\n", path, lnk);
572 ret = link(full_link_path, full_path);
575 error("link %s -> %s failed: %s", path, lnk, strerror(-ret));
583 static int process_unlink(const char *path, void *user)
586 struct btrfs_receive *r = user;
587 char full_path[PATH_MAX];
589 ret = path_cat_out(full_path, r->full_subvol_path, path);
591 error("unlink: path invalid: %s", path);
596 fprintf(stderr, "unlink %s\n", path);
598 ret = unlink(full_path);
601 error("unlink %s failed. %s", path, strerror(-ret));
608 static int process_rmdir(const char *path, void *user)
611 struct btrfs_receive *r = user;
612 char full_path[PATH_MAX];
614 ret = path_cat_out(full_path, r->full_subvol_path, path);
616 error("rmdir: path invalid: %s", path);
621 fprintf(stderr, "rmdir %s\n", path);
623 ret = rmdir(full_path);
626 error("rmdir %s failed: %s", path, strerror(-ret));
633 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
637 if (r->write_fd != -1) {
638 if (strcmp(r->write_path, path) == 0)
644 r->write_fd = open(path, O_RDWR);
645 if (r->write_fd < 0) {
647 error("cannot open %s: %s", path, strerror(-ret));
650 strncpy_null(r->write_path, path);
656 static void close_inode_for_write(struct btrfs_receive *r)
658 if(r->write_fd == -1)
663 r->write_path[0] = 0;
666 static int process_write(const char *path, const void *data, u64 offset,
670 struct btrfs_receive *r = user;
671 char full_path[PATH_MAX];
675 ret = path_cat_out(full_path, r->full_subvol_path, path);
677 error("write: path invalid: %s", path);
681 ret = open_inode_for_write(r, full_path);
686 w = pwrite(r->write_fd, (char*)data + pos, len - pos,
690 error("writing to %s failed: %s\n",
691 path, strerror(-ret));
701 static int process_clone(const char *path, u64 offset, u64 len,
702 const u8 *clone_uuid, u64 clone_ctransid,
703 const char *clone_path, u64 clone_offset,
707 struct btrfs_receive *r = user;
708 struct btrfs_ioctl_clone_range_args clone_args;
709 struct subvol_info *si = NULL;
710 char full_path[PATH_MAX];
711 char *subvol_path = NULL;
712 char full_clone_path[PATH_MAX];
715 ret = path_cat_out(full_path, r->full_subvol_path, path);
717 error("clone: source path invalid: %s", path);
721 ret = open_inode_for_write(r, full_path);
725 si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL,
726 subvol_search_by_received_uuid);
728 if (memcmp(clone_uuid, r->cur_subvol.received_uuid,
729 BTRFS_UUID_SIZE) == 0) {
730 /* TODO check generation of extent */
731 subvol_path = strdup(r->cur_subvol_path);
734 error("clone: did not find source subvol");
738 /*if (rs_args.ctransid > rs_args.rtransid) {
741 fprintf(stderr, "ERROR: subvolume %s was "
742 "modified after it was "
744 r->subvol_parent_name);
747 fprintf(stderr, "WARNING: subvolume %s was "
748 "modified after it was "
750 r->subvol_parent_name);
753 subvol_path = strdup(si->path);
756 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
758 error("clone: target path invalid: %s", clone_path);
762 clone_fd = openat(r->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
765 error("cannot open %s: %s", full_clone_path, strerror(-ret));
769 clone_args.src_fd = clone_fd;
770 clone_args.src_offset = clone_offset;
771 clone_args.src_length = len;
772 clone_args.dest_offset = offset;
773 ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
776 error("failed to clone extents to %s\n%s\n",
777 path, strerror(-ret));
793 static int process_set_xattr(const char *path, const char *name,
794 const void *data, int len, void *user)
797 struct btrfs_receive *r = user;
798 char full_path[PATH_MAX];
800 ret = path_cat_out(full_path, r->full_subvol_path, path);
802 error("set_xattr: path invalid: %s", path);
806 if (strcmp("security.capability", name) == 0) {
808 fprintf(stderr, "set_xattr: cache capabilities\n");
809 if (r->cached_capabilities_len)
810 warning("capabilities set multiple times per file: %s",
812 if (len > sizeof(r->cached_capabilities)) {
813 error("capabilities encoded to %d bytes, buffer too small",
818 r->cached_capabilities_len = len;
819 memcpy(r->cached_capabilities, data, len);
822 if (g_verbose >= 2) {
823 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
824 "data=%.*s\n", path, name, len,
828 ret = lsetxattr(full_path, name, data, len, 0);
831 error("lsetxattr %s %s=%.*s failed: %s",
832 path, name, len, (char*)data, strerror(-ret));
840 static int process_remove_xattr(const char *path, const char *name, void *user)
843 struct btrfs_receive *r = user;
844 char full_path[PATH_MAX];
846 ret = path_cat_out(full_path, r->full_subvol_path, path);
848 error("remove_xattr: path invalid: %s", path);
852 if (g_verbose >= 2) {
853 fprintf(stderr, "remove_xattr %s - name=%s\n",
857 ret = lremovexattr(full_path, name);
860 error("lremovexattr %s %s failed: %s",
861 path, name, strerror(-ret));
869 static int process_truncate(const char *path, u64 size, void *user)
872 struct btrfs_receive *r = user;
873 char full_path[PATH_MAX];
875 ret = path_cat_out(full_path, r->full_subvol_path, path);
877 error("truncate: path invalid: %s", path);
882 fprintf(stderr, "truncate %s size=%llu\n", path, size);
884 ret = truncate(full_path, size);
887 error("truncate %s failed: %s", path, strerror(-ret));
895 static int process_chmod(const char *path, u64 mode, void *user)
898 struct btrfs_receive *r = user;
899 char full_path[PATH_MAX];
901 ret = path_cat_out(full_path, r->full_subvol_path, path);
903 error("chmod: path invalid: %s", path);
908 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
910 ret = chmod(full_path, mode);
913 error("chmod %s failed: %s", path, strerror(-ret));
921 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
924 struct btrfs_receive *r = user;
925 char full_path[PATH_MAX];
927 ret = path_cat_out(full_path, r->full_subvol_path, path);
929 error("chown: path invalid: %s", path);
934 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
937 ret = lchown(full_path, uid, gid);
940 error("chown %s failed: %s", path, strerror(-ret));
944 if (r->cached_capabilities_len) {
946 fprintf(stderr, "chown: restore capabilities\n");
947 ret = lsetxattr(full_path, "security.capability",
948 r->cached_capabilities,
949 r->cached_capabilities_len, 0);
950 memset(r->cached_capabilities, 0,
951 sizeof(r->cached_capabilities));
952 r->cached_capabilities_len = 0;
955 error("restoring capabilities %s: %s",
956 path, strerror(-ret));
965 static int process_utimes(const char *path, struct timespec *at,
966 struct timespec *mt, struct timespec *ct,
970 struct btrfs_receive *r = user;
971 char full_path[PATH_MAX];
972 struct timespec tv[2];
974 ret = path_cat_out(full_path, r->full_subvol_path, path);
976 error("utimes: path invalid: %s", path);
981 fprintf(stderr, "utimes %s\n", path);
985 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
988 error("utimes %s failed: %s",
989 path, strerror(-ret));
997 static int process_update_extent(const char *path, u64 offset, u64 len,
1001 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1002 path, (unsigned long long)offset,
1003 (unsigned long long)len);
1006 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1012 static struct btrfs_send_ops send_ops = {
1013 .subvol = process_subvol,
1014 .snapshot = process_snapshot,
1015 .mkfile = process_mkfile,
1016 .mkdir = process_mkdir,
1017 .mknod = process_mknod,
1018 .mkfifo = process_mkfifo,
1019 .mksock = process_mksock,
1020 .symlink = process_symlink,
1021 .rename = process_rename,
1022 .link = process_link,
1023 .unlink = process_unlink,
1024 .rmdir = process_rmdir,
1025 .write = process_write,
1026 .clone = process_clone,
1027 .set_xattr = process_set_xattr,
1028 .remove_xattr = process_remove_xattr,
1029 .truncate = process_truncate,
1030 .chmod = process_chmod,
1031 .chown = process_chown,
1032 .utimes = process_utimes,
1033 .update_extent = process_update_extent,
1036 static int do_receive(struct btrfs_receive *r, const char *tomnt,
1037 char *realmnt, int r_fd, u64 max_errors)
1041 char *dest_dir_full_path;
1042 char root_subvol_path[PATH_MAX];
1045 dest_dir_full_path = realpath(tomnt, NULL);
1046 if (!dest_dir_full_path) {
1048 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1051 r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1052 if (r->dest_dir_fd < 0) {
1054 error("cannot open destination directory %s: %s",
1055 dest_dir_full_path, strerror(-ret));
1060 r->root_path = realmnt;
1062 ret = find_mount_root(dest_dir_full_path, &r->root_path);
1064 error("failed to determine mount point for %s: %s",
1065 dest_dir_full_path, strerror(-ret));
1070 error("%s doesn't belong to btrfs mount point",
1071 dest_dir_full_path);
1076 r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
1077 if (r->mnt_fd < 0) {
1079 error("cannot open %s: %s", r->root_path, strerror(-ret));
1084 * If we use -m or a default subvol we want to resolve the path to the
1085 * subvolume we're sitting in so that we can adjust the paths of any
1086 * subvols we want to receive in.
1088 ret = btrfs_list_get_path_rootid(r->mnt_fd, &subvol_id);
1090 error("cannot resolve our subvolid: %d",
1095 root_subvol_path[0] = 0;
1096 ret = btrfs_subvolid_resolve(r->mnt_fd, root_subvol_path,
1097 PATH_MAX, subvol_id);
1099 error("cannot resolve our subvol path");
1104 * Ok we're inside of a subvol off of the root subvol, we need to
1105 * actually set full_root_path.
1107 if (*root_subvol_path)
1108 r->full_root_path = root_subvol_path;
1110 if (r->dest_dir_chroot) {
1111 if (chroot(dest_dir_full_path)) {
1113 error("failed to chroot to %s: %s",
1114 dest_dir_full_path, strerror(-ret));
1119 error("failed to chdir to / after chroot: %s",
1123 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1124 r->root_path = strdup("/");
1125 r->dest_dir_path = r->root_path;
1128 * find_mount_root returns a root_path that is a subpath of
1129 * dest_dir_full_path. Now get the other part of root_path,
1130 * which is the destination dir relative to root_path.
1132 r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
1133 while (r->dest_dir_path[0] == '/')
1137 ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
1142 if (r->cached_capabilities_len) {
1144 fprintf(stderr, "clear cached capabilities\n");
1145 memset(r->cached_capabilities, 0,
1146 sizeof(r->cached_capabilities));
1147 r->cached_capabilities_len = 0;
1150 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
1158 close_inode_for_write(r);
1159 ret = finish_subvol(r);
1166 if (r->write_fd != -1) {
1171 if (r->root_path != realmnt)
1173 r->root_path = NULL;
1174 r->dest_dir_path = NULL;
1175 free(dest_dir_full_path);
1176 subvol_uuid_search_finit(&r->sus);
1177 if (r->mnt_fd != -1) {
1181 if (r->dest_dir_fd != -1) {
1182 close(r->dest_dir_fd);
1183 r->dest_dir_fd = -1;
1189 int cmd_receive(int argc, char **argv)
1192 char fromfile[PATH_MAX];
1193 char realmnt[PATH_MAX];
1194 struct btrfs_receive r;
1195 int receive_fd = fileno(stdin);
1199 memset(&r, 0, sizeof(r));
1203 r.dest_dir_chroot = 0;
1209 static const struct option long_opts[] = {
1210 { "max-errors", required_argument, NULL, 'E' },
1211 { "chroot", no_argument, NULL, 'C' },
1212 { NULL, 0, NULL, 0 }
1215 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1224 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1225 error("input file path too long (%zu)",
1232 r.honor_end_cmd = 1;
1235 r.dest_dir_chroot = 1;
1238 max_errors = arg_strtou64(optarg);
1241 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1242 error("mount point path too long (%zu)",
1250 error("receive args invalid");
1255 if (check_argc_exact(argc - optind, 1))
1256 usage(cmd_receive_usage);
1258 tomnt = argv[optind];
1261 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1262 if (receive_fd < 0) {
1263 error("cannot open %s: %s", fromfile, strerror(errno));
1268 ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1269 if (receive_fd != fileno(stdin))
1277 const char * const cmd_receive_usage[] = {
1278 "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1279 "Receive subvolumes from stdin.",
1280 "Receives one or more subvolumes that were previously",
1281 "sent with btrfs send. The received subvolumes are stored",
1283 "btrfs receive will fail in case a receiving subvolume",
1284 "already exists. It will also fail in case a previously",
1285 "received subvolume was changed after it was received.",
1286 "After receiving a subvolume, it is immediately set to",
1288 "-v Enable verbose debug output. Each",
1289 " occurrence of this option increases the",
1290 " verbose level more.",
1291 "-f <infile> By default, btrfs receive uses stdin",
1292 " to receive the subvolumes. Use this",
1293 " option to specify a file to use instead.",
1294 "-e Terminate after receiving an <end cmd>",
1295 " in the data stream. Without this option,",
1296 " the receiver terminates only if an error",
1297 " is recognized or on EOF.",
1298 "-C|--chroot confine the process to <mount> using chroot",
1299 "--max-errors <N> Terminate as soon as N errors happened while",
1300 " processing commands from the send stream.",
1301 " Default value is 1. A value of 0 means no limit.",
1302 "-m <mountpoint> The root mount point of the destination fs.",
1303 " If you do not have /proc use this to tell us where ",
1304 " this file system is mounted.",