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 *rctx)
93 struct btrfs_ioctl_received_subvol_args rs_args;
94 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
97 if (rctx->cur_subvol_path[0] == 0)
100 subvol_fd = openat(rctx->mnt_fd, rctx->cur_subvol_path,
101 O_RDONLY | O_NOATIME);
104 error("cannot open %s: %s",
105 rctx->cur_subvol_path, strerror(-ret));
109 memset(&rs_args, 0, sizeof(rs_args));
110 memcpy(rs_args.uuid, rctx->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
111 rs_args.stransid = rctx->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 rctx->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 (rctx->cur_subvol_path[0]) {
150 rctx->cur_subvol_path[0] = 0;
157 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
161 struct btrfs_receive *rctx = user;
162 struct btrfs_ioctl_vol_args args_v1;
163 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
165 ret = finish_subvol(rctx);
169 if (rctx->cur_subvol.path) {
170 error("subvol: another one already started, path ptr: %s",
171 rctx->cur_subvol.path);
175 if (rctx->cur_subvol_path[0]) {
176 error("subvol: another one already started, path buf: %s",
177 rctx->cur_subvol.path);
182 if (*rctx->dest_dir_path == 0) {
183 strncpy_null(rctx->cur_subvol_path, path);
185 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
188 error("subvol: path invalid: %s", path);
192 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
193 rctx->dest_dir_path, path);
195 error("subvol: path invalid: %s", path);
199 fprintf(stderr, "At subvol %s\n", path);
201 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
202 rctx->cur_subvol.stransid = ctransid;
205 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
206 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
208 rctx->cur_subvol.stransid);
211 memset(&args_v1, 0, sizeof(args_v1));
212 strncpy_null(args_v1.name, path);
213 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
216 error("creating subvolume %s failed: %s", path, strerror(-ret));
224 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
225 const u8 *parent_uuid, u64 parent_ctransid,
229 struct btrfs_receive *rctx = user;
230 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
231 struct btrfs_ioctl_vol_args_v2 args_v2;
232 struct subvol_info *parent_subvol = NULL;
234 ret = finish_subvol(rctx);
238 if (rctx->cur_subvol.path) {
239 error("snapshot: another one already started, path ptr: %s",
240 rctx->cur_subvol.path);
244 if (rctx->cur_subvol_path[0]) {
245 error("snapshot: another one already started, path buf: %s",
246 rctx->cur_subvol.path);
251 if (*rctx->dest_dir_path == 0) {
252 strncpy_null(rctx->cur_subvol_path, path);
254 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
257 error("snapshot: path invalid: %s", path);
261 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
262 rctx->dest_dir_path, path);
264 error("snapshot: path invalid: %s", path);
268 fprintf(stdout, "At snapshot %s\n", path);
270 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
271 rctx->cur_subvol.stransid = ctransid;
274 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
275 fprintf(stderr, "receiving snapshot %s uuid=%s, "
276 "ctransid=%llu ", path, uuid_str,
277 rctx->cur_subvol.stransid);
278 uuid_unparse(parent_uuid, uuid_str);
279 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
280 uuid_str, parent_ctransid);
283 memset(&args_v2, 0, sizeof(args_v2));
284 strncpy_null(args_v2.name, path);
286 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
287 parent_ctransid, NULL,
288 subvol_search_by_received_uuid);
289 if (!parent_subvol) {
290 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
291 parent_ctransid, NULL,
292 subvol_search_by_uuid);
294 if (!parent_subvol) {
296 error("cannot find parent subvolume");
301 * The path is resolved from the root subvol, but we could be in some
302 * subvolume under the root subvolume, so try and adjust the path to be
303 * relative to our root path.
305 if (rctx->full_root_path) {
309 root_len = strlen(rctx->full_root_path);
310 sub_len = strlen(parent_subvol->path);
312 /* First make sure the parent subvol is actually in our path */
313 if (sub_len < root_len ||
314 strstr(parent_subvol->path, rctx->full_root_path) == NULL) {
316 "parent subvol is not reachable from inside the root subvol");
321 if (sub_len == root_len) {
322 parent_subvol->path[0] = '/';
323 parent_subvol->path[1] = '\0';
326 * root path is foo/bar
327 * subvol path is foo/bar/baz
329 * we need to have baz be the path, so we need to move
330 * the bit after foo/bar/, so path + root_len + 1, and
331 * move the part we care about, so sub_len - root_len -
334 memmove(parent_subvol->path,
335 parent_subvol->path + root_len + 1,
336 sub_len - root_len - 1);
337 parent_subvol->path[sub_len - root_len - 1] = '\0';
340 /*if (rs_args.ctransid > rs_args.rtransid) {
343 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
346 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
350 if (*parent_subvol->path == 0)
351 args_v2.fd = dup(rctx->mnt_fd);
353 args_v2.fd = openat(rctx->mnt_fd, parent_subvol->path,
354 O_RDONLY | O_NOATIME);
355 if (args_v2.fd < 0) {
358 error("cannot open %s: %s",
359 parent_subvol->path, strerror(-ret));
362 "It seems that you have changed your default "
363 "subvolume or you specify other subvolume to\n"
364 "mount btrfs, try to remount this btrfs filesystem "
365 "with fs tree, and run btrfs receive again!\n");
369 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
373 error("creating snapshot %s -> %s failed: %s",
374 parent_subvol->path, path, strerror(-ret));
380 free(parent_subvol->path);
386 static int process_mkfile(const char *path, void *user)
389 struct btrfs_receive *rctx = user;
390 char full_path[PATH_MAX];
392 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
394 error("mkfile: path invalid: %s", path);
399 fprintf(stderr, "mkfile %s\n", path);
401 ret = creat(full_path, 0600);
404 error("mkfile %s failed: %s", path, strerror(-ret));
414 static int process_mkdir(const char *path, void *user)
417 struct btrfs_receive *rctx = user;
418 char full_path[PATH_MAX];
420 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
422 error("mkdir: path invalid: %s", path);
427 fprintf(stderr, "mkdir %s\n", path);
429 ret = mkdir(full_path, 0700);
432 error("mkdir %s failed: %s", path, strerror(-ret));
439 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
442 struct btrfs_receive *rctx = user;
443 char full_path[PATH_MAX];
445 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
447 error("mknod: path invalid: %s", path);
452 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
455 ret = mknod(full_path, mode & S_IFMT, dev);
458 error("mknod %s failed: %s", path, strerror(-ret));
465 static int process_mkfifo(const char *path, void *user)
468 struct btrfs_receive *rctx = user;
469 char full_path[PATH_MAX];
471 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
473 error("mkfifo: path invalid: %s", path);
478 fprintf(stderr, "mkfifo %s\n", path);
480 ret = mkfifo(full_path, 0600);
483 error("mkfifo %s failed: %s", path, strerror(-ret));
490 static int process_mksock(const char *path, void *user)
493 struct btrfs_receive *rctx = user;
494 char full_path[PATH_MAX];
496 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
498 error("mksock: path invalid: %s", path);
503 fprintf(stderr, "mksock %s\n", path);
505 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
508 error("mknod %s failed: %s", path, strerror(-ret));
515 static int process_symlink(const char *path, const char *lnk, void *user)
518 struct btrfs_receive *rctx = user;
519 char full_path[PATH_MAX];
521 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
523 error("symlink: path invalid: %s", path);
528 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
530 ret = symlink(lnk, full_path);
533 error("symlink %s -> %s failed: %s", path,
534 lnk, strerror(-ret));
541 static int process_rename(const char *from, const char *to, void *user)
544 struct btrfs_receive *rctx = user;
545 char full_from[PATH_MAX];
546 char full_to[PATH_MAX];
548 ret = path_cat_out(full_from, rctx->full_subvol_path, from);
550 error("rename: source path invalid: %s", from);
554 ret = path_cat_out(full_to, rctx->full_subvol_path, to);
556 error("rename: target path invalid: %s", to);
561 fprintf(stderr, "rename %s -> %s\n", from, to);
563 ret = rename(full_from, full_to);
566 error("rename %s -> %s failed: %s", from,
574 static int process_link(const char *path, const char *lnk, void *user)
577 struct btrfs_receive *rctx = user;
578 char full_path[PATH_MAX];
579 char full_link_path[PATH_MAX];
581 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
583 error("link: source path invalid: %s", full_path);
587 ret = path_cat_out(full_link_path, rctx->full_subvol_path, lnk);
589 error("link: target path invalid: %s", full_link_path);
594 fprintf(stderr, "link %s -> %s\n", path, lnk);
596 ret = link(full_link_path, full_path);
599 error("link %s -> %s failed: %s", path, lnk, strerror(-ret));
607 static int process_unlink(const char *path, void *user)
610 struct btrfs_receive *rctx = user;
611 char full_path[PATH_MAX];
613 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
615 error("unlink: path invalid: %s", path);
620 fprintf(stderr, "unlink %s\n", path);
622 ret = unlink(full_path);
625 error("unlink %s failed. %s", path, strerror(-ret));
632 static int process_rmdir(const char *path, void *user)
635 struct btrfs_receive *rctx = user;
636 char full_path[PATH_MAX];
638 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
640 error("rmdir: path invalid: %s", path);
645 fprintf(stderr, "rmdir %s\n", path);
647 ret = rmdir(full_path);
650 error("rmdir %s failed: %s", path, strerror(-ret));
657 static int open_inode_for_write(struct btrfs_receive *rctx, const char *path)
661 if (rctx->write_fd != -1) {
662 if (strcmp(rctx->write_path, path) == 0)
664 close(rctx->write_fd);
668 rctx->write_fd = open(path, O_RDWR);
669 if (rctx->write_fd < 0) {
671 error("cannot open %s: %s", path, strerror(-ret));
674 strncpy_null(rctx->write_path, path);
680 static void close_inode_for_write(struct btrfs_receive *rctx)
682 if(rctx->write_fd == -1)
685 close(rctx->write_fd);
687 rctx->write_path[0] = 0;
690 static int process_write(const char *path, const void *data, u64 offset,
694 struct btrfs_receive *rctx = user;
695 char full_path[PATH_MAX];
699 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
701 error("write: path invalid: %s", path);
705 ret = open_inode_for_write(rctx, full_path);
710 w = pwrite(rctx->write_fd, (char*)data + pos, len - pos,
714 error("writing to %s failed: %s",
715 path, strerror(-ret));
725 static int process_clone(const char *path, u64 offset, u64 len,
726 const u8 *clone_uuid, u64 clone_ctransid,
727 const char *clone_path, u64 clone_offset,
731 struct btrfs_receive *rctx = user;
732 struct btrfs_ioctl_clone_range_args clone_args;
733 struct subvol_info *si = NULL;
734 char full_path[PATH_MAX];
735 char *subvol_path = NULL;
736 char full_clone_path[PATH_MAX];
739 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
741 error("clone: source path invalid: %s", path);
745 ret = open_inode_for_write(rctx, full_path);
749 si = subvol_uuid_search(&rctx->sus, 0, clone_uuid, clone_ctransid,
751 subvol_search_by_received_uuid);
753 if (memcmp(clone_uuid, rctx->cur_subvol.received_uuid,
754 BTRFS_UUID_SIZE) == 0) {
755 /* TODO check generation of extent */
756 subvol_path = strdup(rctx->cur_subvol_path);
759 error("clone: did not find source subvol");
763 /*if (rs_args.ctransid > rs_args.rtransid) {
766 fprintf(stderr, "ERROR: subvolume %s was "
767 "modified after it was "
769 r->subvol_parent_name);
772 fprintf(stderr, "WARNING: subvolume %s was "
773 "modified after it was "
775 r->subvol_parent_name);
778 subvol_path = strdup(si->path);
781 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
783 error("clone: target path invalid: %s", clone_path);
787 clone_fd = openat(rctx->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
790 error("cannot open %s: %s", full_clone_path, strerror(-ret));
794 clone_args.src_fd = clone_fd;
795 clone_args.src_offset = clone_offset;
796 clone_args.src_length = len;
797 clone_args.dest_offset = offset;
798 ret = ioctl(rctx->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
801 error("failed to clone extents to %s\n%s",
802 path, strerror(-ret));
818 static int process_set_xattr(const char *path, const char *name,
819 const void *data, int len, void *user)
822 struct btrfs_receive *rctx = user;
823 char full_path[PATH_MAX];
825 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
827 error("set_xattr: path invalid: %s", path);
831 if (strcmp("security.capability", name) == 0) {
833 fprintf(stderr, "set_xattr: cache capabilities\n");
834 if (rctx->cached_capabilities_len)
835 warning("capabilities set multiple times per file: %s",
837 if (len > sizeof(rctx->cached_capabilities)) {
838 error("capabilities encoded to %d bytes, buffer too small",
843 rctx->cached_capabilities_len = len;
844 memcpy(rctx->cached_capabilities, data, len);
847 if (g_verbose >= 2) {
848 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
849 "data=%.*s\n", path, name, len,
853 ret = lsetxattr(full_path, name, data, len, 0);
856 error("lsetxattr %s %s=%.*s failed: %s",
857 path, name, len, (char*)data, strerror(-ret));
865 static int process_remove_xattr(const char *path, const char *name, void *user)
868 struct btrfs_receive *rctx = user;
869 char full_path[PATH_MAX];
871 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
873 error("remove_xattr: path invalid: %s", path);
877 if (g_verbose >= 2) {
878 fprintf(stderr, "remove_xattr %s - name=%s\n",
882 ret = lremovexattr(full_path, name);
885 error("lremovexattr %s %s failed: %s",
886 path, name, strerror(-ret));
894 static int process_truncate(const char *path, u64 size, void *user)
897 struct btrfs_receive *rctx = user;
898 char full_path[PATH_MAX];
900 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
902 error("truncate: path invalid: %s", path);
907 fprintf(stderr, "truncate %s size=%llu\n", path, size);
909 ret = truncate(full_path, size);
912 error("truncate %s failed: %s", path, strerror(-ret));
920 static int process_chmod(const char *path, u64 mode, void *user)
923 struct btrfs_receive *rctx = user;
924 char full_path[PATH_MAX];
926 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
928 error("chmod: path invalid: %s", path);
933 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
935 ret = chmod(full_path, mode);
938 error("chmod %s failed: %s", path, strerror(-ret));
946 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
949 struct btrfs_receive *rctx = user;
950 char full_path[PATH_MAX];
952 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
954 error("chown: path invalid: %s", path);
959 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
962 ret = lchown(full_path, uid, gid);
965 error("chown %s failed: %s", path, strerror(-ret));
969 if (rctx->cached_capabilities_len) {
971 fprintf(stderr, "chown: restore capabilities\n");
972 ret = lsetxattr(full_path, "security.capability",
973 rctx->cached_capabilities,
974 rctx->cached_capabilities_len, 0);
975 memset(rctx->cached_capabilities, 0,
976 sizeof(rctx->cached_capabilities));
977 rctx->cached_capabilities_len = 0;
980 error("restoring capabilities %s: %s",
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 *rctx = user;
996 char full_path[PATH_MAX];
997 struct timespec tv[2];
999 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
1001 error("utimes: path invalid: %s", path);
1006 fprintf(stderr, "utimes %s\n", path);
1010 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1013 error("utimes %s failed: %s",
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 *rctx, 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];
1071 dest_dir_full_path = realpath(tomnt, NULL);
1072 if (!dest_dir_full_path) {
1074 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1077 rctx->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1078 if (rctx->dest_dir_fd < 0) {
1080 error("cannot open destination directory %s: %s",
1081 dest_dir_full_path, strerror(-ret));
1086 rctx->root_path = realmnt;
1088 ret = find_mount_root(dest_dir_full_path, &rctx->root_path);
1090 error("failed to determine mount point for %s: %s",
1091 dest_dir_full_path, strerror(-ret));
1096 error("%s doesn't belong to btrfs mount point",
1097 dest_dir_full_path);
1102 rctx->mnt_fd = open(rctx->root_path, O_RDONLY | O_NOATIME);
1103 if (rctx->mnt_fd < 0) {
1105 error("cannot open %s: %s", rctx->root_path, strerror(-ret));
1110 * If we use -m or a default subvol we want to resolve the path to the
1111 * subvolume we're sitting in so that we can adjust the paths of any
1112 * subvols we want to receive in.
1114 ret = btrfs_list_get_path_rootid(rctx->mnt_fd, &subvol_id);
1118 root_subvol_path[0] = 0;
1119 ret = btrfs_subvolid_resolve(rctx->mnt_fd, root_subvol_path,
1120 PATH_MAX, subvol_id);
1122 error("cannot resolve our subvol path");
1127 * Ok we're inside of a subvol off of the root subvol, we need to
1128 * actually set full_root_path.
1130 if (*root_subvol_path)
1131 rctx->full_root_path = root_subvol_path;
1133 if (rctx->dest_dir_chroot) {
1134 if (chroot(dest_dir_full_path)) {
1136 error("failed to chroot to %s: %s",
1137 dest_dir_full_path, strerror(-ret));
1142 error("failed to chdir to / after chroot: %s",
1146 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1147 rctx->root_path = strdup("/");
1148 rctx->dest_dir_path = rctx->root_path;
1151 * find_mount_root returns a root_path that is a subpath of
1152 * dest_dir_full_path. Now get the other part of root_path,
1153 * which is the destination dir relative to root_path.
1155 rctx->dest_dir_path = dest_dir_full_path + strlen(rctx->root_path);
1156 while (rctx->dest_dir_path[0] == '/')
1157 rctx->dest_dir_path++;
1160 ret = subvol_uuid_search_init(rctx->mnt_fd, &rctx->sus);
1166 if (rctx->cached_capabilities_len) {
1168 fprintf(stderr, "clear cached capabilities\n");
1169 memset(rctx->cached_capabilities, 0,
1170 sizeof(rctx->cached_capabilities));
1171 rctx->cached_capabilities_len = 0;
1174 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops,
1176 rctx->honor_end_cmd,
1180 /* Empty stream is invalid */
1181 if (ret && count == 0) {
1182 error("empty stream is not considered valid");
1190 close_inode_for_write(rctx);
1191 ret = finish_subvol(rctx);
1198 if (rctx->write_fd != -1) {
1199 close(rctx->write_fd);
1200 rctx->write_fd = -1;
1203 if (rctx->root_path != realmnt)
1204 free(rctx->root_path);
1205 rctx->root_path = NULL;
1206 rctx->dest_dir_path = NULL;
1207 free(dest_dir_full_path);
1208 subvol_uuid_search_finit(&rctx->sus);
1209 if (rctx->mnt_fd != -1) {
1210 close(rctx->mnt_fd);
1213 if (rctx->dest_dir_fd != -1) {
1214 close(rctx->dest_dir_fd);
1215 rctx->dest_dir_fd = -1;
1221 int cmd_receive(int argc, char **argv)
1224 char fromfile[PATH_MAX];
1225 char realmnt[PATH_MAX];
1226 struct btrfs_receive rctx;
1227 int receive_fd = fileno(stdin);
1231 memset(&rctx, 0, sizeof(rctx));
1234 rctx.dest_dir_fd = -1;
1235 rctx.dest_dir_chroot = 0;
1241 static const struct option long_opts[] = {
1242 { "max-errors", required_argument, NULL, 'E' },
1243 { "chroot", no_argument, NULL, 'C' },
1244 { NULL, 0, NULL, 0 }
1247 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1256 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1257 error("input file path too long (%zu)",
1264 rctx.honor_end_cmd = 1;
1267 rctx.dest_dir_chroot = 1;
1270 max_errors = arg_strtou64(optarg);
1273 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1274 error("mount point path too long (%zu)",
1282 error("receive args invalid");
1287 if (check_argc_exact(argc - optind, 1))
1288 usage(cmd_receive_usage);
1290 tomnt = argv[optind];
1293 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1294 if (receive_fd < 0) {
1295 error("cannot open %s: %s", fromfile, strerror(errno));
1300 ret = do_receive(&rctx, tomnt, realmnt, receive_fd, max_errors);
1301 if (receive_fd != fileno(stdin))
1309 const char * const cmd_receive_usage[] = {
1310 "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1311 "Receive subvolumes from stdin.",
1312 "Receives one or more subvolumes that were previously",
1313 "sent with btrfs send. The received subvolumes are stored",
1315 "btrfs receive will fail in case a receiving subvolume",
1316 "already exists. It will also fail in case a previously",
1317 "received subvolume was changed after it was received.",
1318 "After receiving a subvolume, it is immediately set to",
1320 "-v Enable verbose debug output. Each",
1321 " occurrence of this option increases the",
1322 " verbose level more.",
1323 "-f <infile> By default, btrfs receive uses stdin",
1324 " to receive the subvolumes. Use this",
1325 " option to specify a file to use instead.",
1326 "-e Terminate after receiving an <end cmd>",
1327 " in the data stream. Without this option,",
1328 " the receiver terminates only if an error",
1329 " is recognized or on EOF.",
1330 "-C|--chroot confine the process to <mount> using chroot",
1331 "--max-errors <N> Terminate as soon as N errors happened while",
1332 " processing commands from the send stream.",
1333 " Default value is 1. A value of 0 means no limit.",
1334 "-m <mountpoint> The root mount point of the destination fs.",
1335 " If you do not have /proc use this to tell us where ",
1336 " this file system is mounted.",