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"
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
36 #include <sys/types.h>
37 #include <sys/xattr.h>
38 #include <uuid/uuid.h>
45 #include "btrfs-list.h"
48 #include "send-stream.h"
49 #include "send-utils.h"
51 static int g_verbose = 0;
62 char *dest_dir_path; /* relative to root_path */
63 char *full_subvol_path;
66 struct subvol_info *cur_subvol;
68 struct subvol_uuid_search sus;
73 * Buffer to store capabilities from security.capabilities xattr,
74 * usually 20 bytes, but make same room for potentially larger
75 * encodings. Must be set only once per file, denoted by length > 0.
77 char cached_capabilities[64];
78 int cached_capabilities_len;
81 static int finish_subvol(struct btrfs_receive *r)
85 struct btrfs_ioctl_received_subvol_args rs_args;
86 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
89 if (r->cur_subvol == NULL)
92 subvol_fd = openat(r->mnt_fd, r->cur_subvol->path,
93 O_RDONLY | O_NOATIME);
96 fprintf(stderr, "ERROR: open %s failed. %s\n",
97 r->cur_subvol->path, strerror(-ret));
101 memset(&rs_args, 0, sizeof(rs_args));
102 memcpy(rs_args.uuid, r->cur_subvol->received_uuid, BTRFS_UUID_SIZE);
103 rs_args.stransid = r->cur_subvol->stransid;
105 if (g_verbose >= 1) {
106 uuid_unparse((u8*)rs_args.uuid, uuid_str);
107 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
108 "stransid=%llu\n", uuid_str, rs_args.stransid);
111 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
114 fprintf(stderr, "ERROR: BTRFS_IOC_SET_RECEIVED_SUBVOL failed. %s\n",
118 r->cur_subvol->rtransid = rs_args.rtransid;
120 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
123 fprintf(stderr, "ERROR: BTRFS_IOC_SUBVOL_GETFLAGS failed. %s\n",
128 flags |= BTRFS_SUBVOL_RDONLY;
130 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
133 fprintf(stderr, "ERROR: failed to make subvolume read only. "
134 "%s\n", strerror(-ret));
142 free(r->cur_subvol->path);
144 r->cur_subvol = NULL;
151 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
155 struct btrfs_receive *r = user;
156 struct btrfs_ioctl_vol_args args_v1;
157 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
159 ret = finish_subvol(r);
163 r->cur_subvol = calloc(1, sizeof(*r->cur_subvol));
165 if (strlen(r->dest_dir_path) == 0)
166 r->cur_subvol->path = strdup(path);
168 r->cur_subvol->path = path_cat(r->dest_dir_path, path);
169 free(r->full_subvol_path);
170 r->full_subvol_path = path_cat3(r->root_path, r->dest_dir_path, path);
172 fprintf(stderr, "At subvol %s\n", path);
174 memcpy(r->cur_subvol->received_uuid, uuid, BTRFS_UUID_SIZE);
175 r->cur_subvol->stransid = ctransid;
178 uuid_unparse((u8*)r->cur_subvol->received_uuid, uuid_str);
179 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
181 r->cur_subvol->stransid);
184 memset(&args_v1, 0, sizeof(args_v1));
185 strncpy_null(args_v1.name, path);
186 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
189 fprintf(stderr, "ERROR: creating subvolume %s failed. "
190 "%s\n", path, strerror(-ret));
198 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
199 const u8 *parent_uuid, u64 parent_ctransid,
203 struct btrfs_receive *r = user;
204 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
205 struct btrfs_ioctl_vol_args_v2 args_v2;
206 struct subvol_info *parent_subvol = NULL;
208 ret = finish_subvol(r);
212 r->cur_subvol = calloc(1, sizeof(*r->cur_subvol));
214 if (strlen(r->dest_dir_path) == 0)
215 r->cur_subvol->path = strdup(path);
217 r->cur_subvol->path = path_cat(r->dest_dir_path, path);
218 free(r->full_subvol_path);
219 r->full_subvol_path = path_cat3(r->root_path, r->dest_dir_path, path);
221 fprintf(stdout, "At snapshot %s\n", path);
223 memcpy(r->cur_subvol->received_uuid, uuid, BTRFS_UUID_SIZE);
224 r->cur_subvol->stransid = ctransid;
227 uuid_unparse((u8*)r->cur_subvol->received_uuid, uuid_str);
228 fprintf(stderr, "receiving snapshot %s uuid=%s, "
229 "ctransid=%llu ", path, uuid_str,
230 r->cur_subvol->stransid);
231 uuid_unparse(parent_uuid, uuid_str);
232 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
233 uuid_str, parent_ctransid);
236 memset(&args_v2, 0, sizeof(args_v2));
237 strncpy_null(args_v2.name, path);
239 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
240 parent_ctransid, NULL, subvol_search_by_received_uuid);
241 if (!parent_subvol) {
242 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
243 parent_ctransid, NULL, subvol_search_by_uuid);
245 if (!parent_subvol) {
247 fprintf(stderr, "ERROR: could not find parent subvolume\n");
251 /*if (rs_args.ctransid > rs_args.rtransid) {
254 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
257 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
261 args_v2.fd = openat(r->mnt_fd, parent_subvol->path,
262 O_RDONLY | O_NOATIME);
263 if (args_v2.fd < 0) {
266 fprintf(stderr, "ERROR: open %s failed. %s\n",
267 parent_subvol->path, strerror(-ret));
270 "It seems that you have changed your default "
271 "subvolume or you specify other subvolume to\n"
272 "mount btrfs, try to remount this btrfs filesystem "
273 "with fs tree, and run btrfs receive again!\n");
277 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
281 fprintf(stderr, "ERROR: creating snapshot %s -> %s "
282 "failed. %s\n", parent_subvol->path,
283 path, strerror(-ret));
289 free(parent_subvol->path);
295 static int process_mkfile(const char *path, void *user)
298 struct btrfs_receive *r = user;
299 char *full_path = path_cat(r->full_subvol_path, path);
302 fprintf(stderr, "mkfile %s\n", path);
304 ret = creat(full_path, 0600);
307 fprintf(stderr, "ERROR: mkfile %s failed. %s\n", path,
319 static int process_mkdir(const char *path, void *user)
322 struct btrfs_receive *r = user;
323 char *full_path = path_cat(r->full_subvol_path, path);
326 fprintf(stderr, "mkdir %s\n", path);
328 ret = mkdir(full_path, 0700);
331 fprintf(stderr, "ERROR: mkdir %s failed. %s\n", path,
339 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
342 struct btrfs_receive *r = user;
343 char *full_path = path_cat(r->full_subvol_path, path);
346 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
349 ret = mknod(full_path, mode & S_IFMT, dev);
352 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
360 static int process_mkfifo(const char *path, void *user)
363 struct btrfs_receive *r = user;
364 char *full_path = path_cat(r->full_subvol_path, path);
367 fprintf(stderr, "mkfifo %s\n", path);
369 ret = mkfifo(full_path, 0600);
372 fprintf(stderr, "ERROR: mkfifo %s failed. %s\n", path,
380 static int process_mksock(const char *path, void *user)
383 struct btrfs_receive *r = user;
384 char *full_path = path_cat(r->full_subvol_path, path);
387 fprintf(stderr, "mksock %s\n", path);
389 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
392 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
400 static int process_symlink(const char *path, const char *lnk, void *user)
403 struct btrfs_receive *r = user;
404 char *full_path = path_cat(r->full_subvol_path, path);
407 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
409 ret = symlink(lnk, full_path);
412 fprintf(stderr, "ERROR: symlink %s -> %s failed. %s\n", path,
413 lnk, strerror(-ret));
420 static int process_rename(const char *from, const char *to, void *user)
423 struct btrfs_receive *r = user;
424 char *full_from = path_cat(r->full_subvol_path, from);
425 char *full_to = path_cat(r->full_subvol_path, to);
428 fprintf(stderr, "rename %s -> %s\n", from, to);
430 ret = rename(full_from, full_to);
433 fprintf(stderr, "ERROR: rename %s -> %s failed. %s\n", from,
442 static int process_link(const char *path, const char *lnk, void *user)
445 struct btrfs_receive *r = user;
446 char *full_path = path_cat(r->full_subvol_path, path);
447 char *full_link_path = path_cat(r->full_subvol_path, lnk);
450 fprintf(stderr, "link %s -> %s\n", path, lnk);
452 ret = link(full_link_path, full_path);
455 fprintf(stderr, "ERROR: link %s -> %s failed. %s\n", path,
456 lnk, strerror(-ret));
460 free(full_link_path);
465 static int process_unlink(const char *path, void *user)
468 struct btrfs_receive *r = user;
469 char *full_path = path_cat(r->full_subvol_path, path);
472 fprintf(stderr, "unlink %s\n", path);
474 ret = unlink(full_path);
477 fprintf(stderr, "ERROR: unlink %s failed. %s\n", path,
485 static int process_rmdir(const char *path, void *user)
488 struct btrfs_receive *r = user;
489 char *full_path = path_cat(r->full_subvol_path, path);
492 fprintf(stderr, "rmdir %s\n", path);
494 ret = rmdir(full_path);
497 fprintf(stderr, "ERROR: rmdir %s failed. %s\n", path,
506 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
510 if (r->write_fd != -1) {
511 if (strcmp(r->write_path, path) == 0)
517 r->write_fd = open(path, O_RDWR);
518 if (r->write_fd < 0) {
520 fprintf(stderr, "ERROR: open %s failed. %s\n", path,
525 r->write_path = strdup(path);
531 static void close_inode_for_write(struct btrfs_receive *r)
533 if(r->write_fd == -1)
538 r->write_path[0] = 0;
541 static int process_write(const char *path, const void *data, u64 offset,
545 struct btrfs_receive *r = user;
546 char *full_path = path_cat(r->full_subvol_path, path);
550 ret = open_inode_for_write(r, full_path);
555 w = pwrite(r->write_fd, (char*)data + pos, len - pos,
559 fprintf(stderr, "ERROR: writing to %s failed. %s\n",
560 path, strerror(-ret));
571 static int process_clone(const char *path, u64 offset, u64 len,
572 const u8 *clone_uuid, u64 clone_ctransid,
573 const char *clone_path, u64 clone_offset,
577 struct btrfs_receive *r = user;
578 struct btrfs_ioctl_clone_range_args clone_args;
579 struct subvol_info *si = NULL;
580 char *full_path = path_cat(r->full_subvol_path, path);
581 char *subvol_path = NULL;
582 char *full_clone_path = NULL;
585 ret = open_inode_for_write(r, full_path);
589 si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL,
590 subvol_search_by_received_uuid);
592 if (memcmp(clone_uuid, r->cur_subvol->received_uuid,
593 BTRFS_UUID_SIZE) == 0) {
594 /* TODO check generation of extent */
595 subvol_path = strdup(r->cur_subvol->path);
598 fprintf(stderr, "ERROR: did not find source subvol.\n");
602 /*if (rs_args.ctransid > rs_args.rtransid) {
605 fprintf(stderr, "ERROR: subvolume %s was "
606 "modified after it was "
608 r->subvol_parent_name);
611 fprintf(stderr, "WARNING: subvolume %s was "
612 "modified after it was "
614 r->subvol_parent_name);
617 subvol_path = strdup(si->path);
620 full_clone_path = path_cat(subvol_path, clone_path);
622 clone_fd = openat(r->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
625 fprintf(stderr, "ERROR: failed to open %s. %s\n",
626 full_clone_path, strerror(-ret));
630 clone_args.src_fd = clone_fd;
631 clone_args.src_offset = clone_offset;
632 clone_args.src_length = len;
633 clone_args.dest_offset = offset;
634 ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
637 fprintf(stderr, "ERROR: failed to clone extents to %s\n%s\n",
638 path, strerror(-ret));
648 free(full_clone_path);
656 static int process_set_xattr(const char *path, const char *name,
657 const void *data, int len, void *user)
660 struct btrfs_receive *r = user;
661 char *full_path = path_cat(r->full_subvol_path, path);
663 if (strcmp("security.capability", name) == 0) {
665 fprintf(stderr, "set_xattr: cache capabilities\n");
666 if (r->cached_capabilities_len)
668 "WARNING: capabilities set multiple times per file: %s\n",
670 if (len > sizeof(r->cached_capabilities)) {
672 "ERROR: capabilities encoded to %d bytes, buffer too small\n",
677 r->cached_capabilities_len = len;
678 memcpy(r->cached_capabilities, data, len);
681 if (g_verbose >= 2) {
682 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
683 "data=%.*s\n", path, name, len,
687 ret = lsetxattr(full_path, name, data, len, 0);
690 fprintf(stderr, "ERROR: lsetxattr %s %s=%.*s failed. %s\n",
691 path, name, len, (char*)data, strerror(-ret));
700 static int process_remove_xattr(const char *path, const char *name, void *user)
703 struct btrfs_receive *r = user;
704 char *full_path = path_cat(r->full_subvol_path, path);
706 if (g_verbose >= 2) {
707 fprintf(stderr, "remove_xattr %s - name=%s\n",
711 ret = lremovexattr(full_path, name);
714 fprintf(stderr, "ERROR: lremovexattr %s %s failed. %s\n",
715 path, name, strerror(-ret));
724 static int process_truncate(const char *path, u64 size, void *user)
727 struct btrfs_receive *r = user;
728 char *full_path = path_cat(r->full_subvol_path, path);
731 fprintf(stderr, "truncate %s size=%llu\n", path, size);
733 ret = truncate(full_path, size);
736 fprintf(stderr, "ERROR: truncate %s failed. %s\n",
737 path, strerror(-ret));
746 static int process_chmod(const char *path, u64 mode, void *user)
749 struct btrfs_receive *r = user;
750 char *full_path = path_cat(r->full_subvol_path, path);
753 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
755 ret = chmod(full_path, mode);
758 fprintf(stderr, "ERROR: chmod %s failed. %s\n",
759 path, strerror(-ret));
768 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
771 struct btrfs_receive *r = user;
772 char *full_path = path_cat(r->full_subvol_path, path);
775 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
778 ret = lchown(full_path, uid, gid);
781 fprintf(stderr, "ERROR: chown %s failed. %s\n",
782 path, strerror(-ret));
786 if (r->cached_capabilities_len) {
788 fprintf(stderr, "chown: restore capabilities\n");
789 ret = lsetxattr(full_path, "security.capability",
790 r->cached_capabilities,
791 r->cached_capabilities_len, 0);
792 memset(r->cached_capabilities, 0,
793 sizeof(r->cached_capabilities));
794 r->cached_capabilities_len = 0;
797 fprintf(stderr, "ERROR: restoring capabilities %s: %s\n",
798 path, strerror(-ret));
808 static int process_utimes(const char *path, struct timespec *at,
809 struct timespec *mt, struct timespec *ct,
813 struct btrfs_receive *r = user;
814 char *full_path = path_cat(r->full_subvol_path, path);
815 struct timespec tv[2];
818 fprintf(stderr, "utimes %s\n", path);
822 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
825 fprintf(stderr, "ERROR: utimes %s failed. %s\n",
826 path, strerror(-ret));
836 static struct btrfs_send_ops send_ops = {
837 .subvol = process_subvol,
838 .snapshot = process_snapshot,
839 .mkfile = process_mkfile,
840 .mkdir = process_mkdir,
841 .mknod = process_mknod,
842 .mkfifo = process_mkfifo,
843 .mksock = process_mksock,
844 .symlink = process_symlink,
845 .rename = process_rename,
846 .link = process_link,
847 .unlink = process_unlink,
848 .rmdir = process_rmdir,
849 .write = process_write,
850 .clone = process_clone,
851 .set_xattr = process_set_xattr,
852 .remove_xattr = process_remove_xattr,
853 .truncate = process_truncate,
854 .chmod = process_chmod,
855 .chown = process_chown,
856 .utimes = process_utimes,
859 static int do_receive(struct btrfs_receive *r, const char *tomnt,
860 char *realmnt, int r_fd, u64 max_errors)
863 char *dest_dir_full_path;
866 dest_dir_full_path = realpath(tomnt, NULL);
867 if (!dest_dir_full_path) {
869 fprintf(stderr, "ERROR: realpath(%s) failed. %s\n", tomnt,
873 r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
874 if (r->dest_dir_fd < 0) {
877 "ERROR: failed to open destination directory %s. %s\n",
878 dest_dir_full_path, strerror(-ret));
883 r->root_path = realmnt;
885 ret = find_mount_root(dest_dir_full_path, &r->root_path);
888 "ERROR: failed to determine mount point for %s: %s\n",
889 dest_dir_full_path, strerror(-ret));
895 "ERROR: %s doesn't belong to btrfs mount point\n",
901 r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
904 fprintf(stderr, "ERROR: failed to open %s. %s\n", r->root_path,
909 if (r->dest_dir_chroot) {
910 if (chroot(dest_dir_full_path)) {
913 "ERROR: failed to chroot to %s, %s\n",
921 "ERROR: failed to chdir to /, %s\n",
925 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
926 r->root_path = strdup("/");
927 r->dest_dir_path = r->root_path;
930 * find_mount_root returns a root_path that is a subpath of
931 * dest_dir_full_path. Now get the other part of root_path,
932 * which is the destination dir relative to root_path.
934 r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
935 while (r->dest_dir_path[0] == '/')
939 ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
944 if (r->cached_capabilities_len) {
946 fprintf(stderr, "clear cached capabilities\n");
947 memset(r->cached_capabilities, 0,
948 sizeof(r->cached_capabilities));
949 r->cached_capabilities_len = 0;
952 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
960 close_inode_for_write(r);
961 ret = finish_subvol(r);
968 if (r->write_fd != -1) {
975 r->write_path = NULL;
976 free(r->full_subvol_path);
977 r->full_subvol_path = NULL;
978 r->dest_dir_path = NULL;
979 free(dest_dir_full_path);
981 free(r->cur_subvol->path);
983 r->cur_subvol = NULL;
985 subvol_uuid_search_finit(&r->sus);
986 if (r->mnt_fd != -1) {
990 if (r->dest_dir_fd != -1) {
991 close(r->dest_dir_fd);
997 int cmd_receive(int argc, char **argv)
1000 char *fromfile = NULL;
1001 char *realmnt = NULL;
1002 struct btrfs_receive r;
1003 int receive_fd = fileno(stdin);
1007 memset(&r, 0, sizeof(r));
1011 r.dest_dir_chroot = 0;
1015 static const struct option long_opts[] = {
1016 { "max-errors", required_argument, NULL, 'E' },
1017 { "chroot", no_argument, NULL, 'C' },
1018 { NULL, 0, NULL, 0 }
1021 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1033 r.honor_end_cmd = 1;
1036 r.dest_dir_chroot = 1;
1039 max_errors = arg_strtou64(optarg);
1042 realmnt = strdup(optarg);
1044 fprintf(stderr, "ERROR: couldn't allocate realmnt.\n");
1050 fprintf(stderr, "ERROR: receive args invalid.\n");
1055 if (check_argc_exact(argc - optind, 1))
1056 usage(cmd_receive_usage);
1058 tomnt = argv[optind];
1061 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1062 if (receive_fd < 0) {
1063 fprintf(stderr, "ERROR: failed to open %s\n", fromfile);
1068 ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1073 const char * const cmd_receive_usage[] = {
1074 "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1075 "Receive subvolumes from stdin.",
1076 "Receives one or more subvolumes that were previously",
1077 "sent with btrfs send. The received subvolumes are stored",
1079 "btrfs receive will fail in case a receiving subvolume",
1080 "already exists. It will also fail in case a previously",
1081 "received subvolume was changed after it was received.",
1082 "After receiving a subvolume, it is immediately set to",
1084 "-v Enable verbose debug output. Each",
1085 " occurrence of this option increases the",
1086 " verbose level more.",
1087 "-f <infile> By default, btrfs receive uses stdin",
1088 " to receive the subvolumes. Use this",
1089 " option to specify a file to use instead.",
1090 "-e Terminate after receiving an <end cmd>",
1091 " in the data stream. Without this option,",
1092 " the receiver terminates only if an error",
1093 " is recognized or on EOF.",
1094 "-C|--chroot confine the process to <mount> using chroot",
1095 "--max-errors <N> Terminate as soon as N errors happened while",
1096 " processing commands from the send stream.",
1097 " Default value is 1. A value of 0 means no limit.",
1098 "-m <mountpoint> The root mount point of the destination fs.",
1099 " If you do not have /proc use this to tell us where ",
1100 " this file system is mounted.",