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 fprintf(stderr
, "ERROR: open %s failed. %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 fprintf(stderr
, "ERROR: BTRFS_IOC_SET_RECEIVED_SUBVOL failed. %s\n",
126 r
->cur_subvol
.rtransid
= rs_args
.rtransid
;
128 ret
= ioctl(subvol_fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
);
131 fprintf(stderr
, "ERROR: BTRFS_IOC_SUBVOL_GETFLAGS failed. %s\n",
136 flags
|= BTRFS_SUBVOL_RDONLY
;
138 ret
= ioctl(subvol_fd
, BTRFS_IOC_SUBVOL_SETFLAGS
, &flags
);
141 fprintf(stderr
, "ERROR: failed to make subvolume read only. "
142 "%s\n", strerror(-ret
));
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 (strlen(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 fprintf(stderr
, "ERROR: subvol: path invalid: %s\n",
182 ret
= path_cat3_out(r
->full_subvol_path
, r
->root_path
,
183 r
->dest_dir_path
, path
);
185 fprintf(stderr
, "ERROR: subvol: path invalid: %s\n", path
);
189 fprintf(stderr
, "At subvol %s\n", path
);
191 memcpy(r
->cur_subvol
.received_uuid
, uuid
, BTRFS_UUID_SIZE
);
192 r
->cur_subvol
.stransid
= ctransid
;
195 uuid_unparse((u8
*)r
->cur_subvol
.received_uuid
, uuid_str
);
196 fprintf(stderr
, "receiving subvol %s uuid=%s, stransid=%llu\n",
198 r
->cur_subvol
.stransid
);
201 memset(&args_v1
, 0, sizeof(args_v1
));
202 strncpy_null(args_v1
.name
, path
);
203 ret
= ioctl(r
->dest_dir_fd
, BTRFS_IOC_SUBVOL_CREATE
, &args_v1
);
206 fprintf(stderr
, "ERROR: creating subvolume %s failed. "
207 "%s\n", path
, strerror(-ret
));
215 static int process_snapshot(const char *path
, const u8
*uuid
, u64 ctransid
,
216 const u8
*parent_uuid
, u64 parent_ctransid
,
220 struct btrfs_receive
*r
= user
;
221 char uuid_str
[BTRFS_UUID_UNPARSED_SIZE
];
222 struct btrfs_ioctl_vol_args_v2 args_v2
;
223 struct subvol_info
*parent_subvol
= NULL
;
225 ret
= finish_subvol(r
);
229 BUG_ON(r
->cur_subvol
.path
);
230 BUG_ON(r
->cur_subvol_path
[0]);
232 if (strlen(r
->dest_dir_path
) == 0) {
233 strncpy_null(r
->cur_subvol_path
, path
);
235 ret
= path_cat_out(r
->cur_subvol_path
, r
->dest_dir_path
, path
);
237 fprintf(stderr
, "ERROR: snapshot: path invalid: %s\n",
242 ret
= path_cat3_out(r
->full_subvol_path
, r
->root_path
,
243 r
->dest_dir_path
, path
);
245 fprintf(stderr
, "ERROR: snapshot: path invalid: %s\n", path
);
249 fprintf(stdout
, "At snapshot %s\n", path
);
251 memcpy(r
->cur_subvol
.received_uuid
, uuid
, BTRFS_UUID_SIZE
);
252 r
->cur_subvol
.stransid
= ctransid
;
255 uuid_unparse((u8
*)r
->cur_subvol
.received_uuid
, uuid_str
);
256 fprintf(stderr
, "receiving snapshot %s uuid=%s, "
257 "ctransid=%llu ", path
, uuid_str
,
258 r
->cur_subvol
.stransid
);
259 uuid_unparse(parent_uuid
, uuid_str
);
260 fprintf(stderr
, "parent_uuid=%s, parent_ctransid=%llu\n",
261 uuid_str
, parent_ctransid
);
264 memset(&args_v2
, 0, sizeof(args_v2
));
265 strncpy_null(args_v2
.name
, path
);
267 parent_subvol
= subvol_uuid_search(&r
->sus
, 0, parent_uuid
,
268 parent_ctransid
, NULL
, subvol_search_by_received_uuid
);
269 if (!parent_subvol
) {
270 parent_subvol
= subvol_uuid_search(&r
->sus
, 0, parent_uuid
,
271 parent_ctransid
, NULL
, subvol_search_by_uuid
);
273 if (!parent_subvol
) {
275 fprintf(stderr
, "ERROR: could not find parent subvolume\n");
280 * The path is resolved from the root subvol, but we could be in some
281 * subvolume under the root subvolume, so try and adjust the path to be
282 * relative to our root path.
284 if (r
->full_root_path
) {
288 root_len
= strlen(r
->full_root_path
);
289 sub_len
= strlen(parent_subvol
->path
);
291 /* First make sure the parent subvol is actually in our path */
292 if (sub_len
< root_len
||
293 strstr(parent_subvol
->path
, r
->full_root_path
) == NULL
) {
294 fprintf(stderr
, "ERROR: parent subvol is not reachable"
295 " from inside the root subvol.\n");
300 if (sub_len
== root_len
) {
301 parent_subvol
->path
[0] = '/';
302 parent_subvol
->path
[1] = '\0';
305 * root path is foo/bar
306 * subvol path is foo/bar/baz
308 * we need to have baz be the path, so we need to move
309 * the bit after foo/bar/, so path + root_len + 1, and
310 * move the part we care about, so sub_len - root_len -
313 memmove(parent_subvol
->path
,
314 parent_subvol
->path
+ root_len
+ 1,
315 sub_len
- root_len
- 1);
316 parent_subvol
->path
[sub_len
- root_len
- 1] = '\0';
319 /*if (rs_args.ctransid > rs_args.rtransid) {
322 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
325 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
329 if (strlen(parent_subvol
->path
) == 0)
330 args_v2
.fd
= dup(r
->mnt_fd
);
332 args_v2
.fd
= openat(r
->mnt_fd
, parent_subvol
->path
,
333 O_RDONLY
| O_NOATIME
);
334 if (args_v2
.fd
< 0) {
337 fprintf(stderr
, "ERROR: open %s failed. %s\n",
338 parent_subvol
->path
, strerror(-ret
));
341 "It seems that you have changed your default "
342 "subvolume or you specify other subvolume to\n"
343 "mount btrfs, try to remount this btrfs filesystem "
344 "with fs tree, and run btrfs receive again!\n");
348 ret
= ioctl(r
->dest_dir_fd
, BTRFS_IOC_SNAP_CREATE_V2
, &args_v2
);
352 fprintf(stderr
, "ERROR: creating snapshot %s -> %s "
353 "failed. %s\n", parent_subvol
->path
,
354 path
, strerror(-ret
));
360 free(parent_subvol
->path
);
366 static int process_mkfile(const char *path
, void *user
)
369 struct btrfs_receive
*r
= user
;
370 char full_path
[PATH_MAX
];
372 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
374 fprintf(stderr
, "ERROR: mkfile: path invalid: %s\n", path
);
379 fprintf(stderr
, "mkfile %s\n", path
);
381 ret
= creat(full_path
, 0600);
384 fprintf(stderr
, "ERROR: mkfile %s failed. %s\n", path
,
395 static int process_mkdir(const char *path
, void *user
)
398 struct btrfs_receive
*r
= user
;
399 char full_path
[PATH_MAX
];
401 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
403 fprintf(stderr
, "ERROR: mkdir: path invalid: %s\n", path
);
408 fprintf(stderr
, "mkdir %s\n", path
);
410 ret
= mkdir(full_path
, 0700);
413 fprintf(stderr
, "ERROR: mkdir %s failed. %s\n", path
,
421 static int process_mknod(const char *path
, u64 mode
, u64 dev
, void *user
)
424 struct btrfs_receive
*r
= user
;
425 char full_path
[PATH_MAX
];
427 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
429 fprintf(stderr
, "ERROR: mknod: path invalid: %s\n", path
);
434 fprintf(stderr
, "mknod %s mode=%llu, dev=%llu\n",
437 ret
= mknod(full_path
, mode
& S_IFMT
, dev
);
440 fprintf(stderr
, "ERROR: mknod %s failed. %s\n", path
,
448 static int process_mkfifo(const char *path
, void *user
)
451 struct btrfs_receive
*r
= user
;
452 char full_path
[PATH_MAX
];
454 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
456 fprintf(stderr
, "ERROR: mkfifo: path invalid: %s\n", path
);
461 fprintf(stderr
, "mkfifo %s\n", path
);
463 ret
= mkfifo(full_path
, 0600);
466 fprintf(stderr
, "ERROR: mkfifo %s failed. %s\n", path
,
474 static int process_mksock(const char *path
, void *user
)
477 struct btrfs_receive
*r
= user
;
478 char full_path
[PATH_MAX
];
480 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
482 fprintf(stderr
, "ERROR: mksock: path invalid: %s\n", path
);
487 fprintf(stderr
, "mksock %s\n", path
);
489 ret
= mknod(full_path
, 0600 | S_IFSOCK
, 0);
492 fprintf(stderr
, "ERROR: mknod %s failed. %s\n", path
,
500 static int process_symlink(const char *path
, const char *lnk
, void *user
)
503 struct btrfs_receive
*r
= user
;
504 char full_path
[PATH_MAX
];
506 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
508 fprintf(stderr
, "ERROR: symlink: path invalid: %s\n", path
);
513 fprintf(stderr
, "symlink %s -> %s\n", path
, lnk
);
515 ret
= symlink(lnk
, full_path
);
518 fprintf(stderr
, "ERROR: symlink %s -> %s failed. %s\n", path
,
519 lnk
, strerror(-ret
));
526 static int process_rename(const char *from
, const char *to
, void *user
)
529 struct btrfs_receive
*r
= user
;
530 char full_from
[PATH_MAX
];
531 char full_to
[PATH_MAX
];
533 ret
= path_cat_out(full_from
, r
->full_subvol_path
, from
);
535 fprintf(stderr
, "ERROR: rename: source path invalid: %s\n",
540 ret
= path_cat_out(full_to
, r
->full_subvol_path
, to
);
542 fprintf(stderr
, "ERROR: rename: target path invalid: %s\n",
548 fprintf(stderr
, "rename %s -> %s\n", from
, to
);
550 ret
= rename(full_from
, full_to
);
553 fprintf(stderr
, "ERROR: rename %s -> %s failed. %s\n", from
,
561 static int process_link(const char *path
, const char *lnk
, void *user
)
564 struct btrfs_receive
*r
= user
;
565 char full_path
[PATH_MAX
];
566 char full_link_path
[PATH_MAX
];
568 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
570 fprintf(stderr
, "ERROR: link: source path invalid: %s\n",
575 ret
= path_cat_out(full_link_path
, r
->full_subvol_path
, lnk
);
577 fprintf(stderr
, "ERROR: link: target path invalid: %s\n",
583 fprintf(stderr
, "link %s -> %s\n", path
, lnk
);
585 ret
= link(full_link_path
, full_path
);
588 fprintf(stderr
, "ERROR: link %s -> %s failed. %s\n", path
,
589 lnk
, strerror(-ret
));
597 static int process_unlink(const char *path
, void *user
)
600 struct btrfs_receive
*r
= user
;
601 char full_path
[PATH_MAX
];
603 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
605 fprintf(stderr
, "ERROR: unlink: path invalid: %s\n", path
);
610 fprintf(stderr
, "unlink %s\n", path
);
612 ret
= unlink(full_path
);
615 fprintf(stderr
, "ERROR: unlink %s failed. %s\n", path
,
623 static int process_rmdir(const char *path
, void *user
)
626 struct btrfs_receive
*r
= user
;
627 char full_path
[PATH_MAX
];
629 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
631 fprintf(stderr
, "ERROR: rmdir: path invalid: %s\n", path
);
636 fprintf(stderr
, "rmdir %s\n", path
);
638 ret
= rmdir(full_path
);
641 fprintf(stderr
, "ERROR: rmdir %s failed. %s\n", path
,
649 static int open_inode_for_write(struct btrfs_receive
*r
, const char *path
)
653 if (r
->write_fd
!= -1) {
654 if (strcmp(r
->write_path
, path
) == 0)
660 r
->write_fd
= open(path
, O_RDWR
);
661 if (r
->write_fd
< 0) {
663 fprintf(stderr
, "ERROR: open %s failed. %s\n", path
,
667 strncpy_null(r
->write_path
, path
);
673 static void close_inode_for_write(struct btrfs_receive
*r
)
675 if(r
->write_fd
== -1)
680 r
->write_path
[0] = 0;
683 static int process_write(const char *path
, const void *data
, u64 offset
,
687 struct btrfs_receive
*r
= user
;
688 char full_path
[PATH_MAX
];
692 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
694 fprintf(stderr
, "ERROR: write: path invalid: %s\n", path
);
698 ret
= open_inode_for_write(r
, full_path
);
703 w
= pwrite(r
->write_fd
, (char*)data
+ pos
, len
- pos
,
707 fprintf(stderr
, "ERROR: writing to %s failed. %s\n",
708 path
, strerror(-ret
));
718 static int process_clone(const char *path
, u64 offset
, u64 len
,
719 const u8
*clone_uuid
, u64 clone_ctransid
,
720 const char *clone_path
, u64 clone_offset
,
724 struct btrfs_receive
*r
= user
;
725 struct btrfs_ioctl_clone_range_args clone_args
;
726 struct subvol_info
*si
= NULL
;
727 char full_path
[PATH_MAX
];
728 char *subvol_path
= NULL
;
729 char full_clone_path
[PATH_MAX
];
732 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
734 fprintf(stderr
, "ERROR: clone: source path invalid: %s\n",
739 ret
= open_inode_for_write(r
, full_path
);
743 si
= subvol_uuid_search(&r
->sus
, 0, clone_uuid
, clone_ctransid
, NULL
,
744 subvol_search_by_received_uuid
);
746 if (memcmp(clone_uuid
, r
->cur_subvol
.received_uuid
,
747 BTRFS_UUID_SIZE
) == 0) {
748 /* TODO check generation of extent */
749 subvol_path
= strdup(r
->cur_subvol_path
);
752 fprintf(stderr
, "ERROR: did not find source subvol.\n");
756 /*if (rs_args.ctransid > rs_args.rtransid) {
759 fprintf(stderr, "ERROR: subvolume %s was "
760 "modified after it was "
762 r->subvol_parent_name);
765 fprintf(stderr, "WARNING: subvolume %s was "
766 "modified after it was "
768 r->subvol_parent_name);
771 subvol_path
= strdup(si
->path
);
774 ret
= path_cat_out(full_clone_path
, subvol_path
, clone_path
);
776 fprintf(stderr
, "ERROR: clone: target path invalid: %s\n",
781 clone_fd
= openat(r
->mnt_fd
, full_clone_path
, O_RDONLY
| O_NOATIME
);
784 fprintf(stderr
, "ERROR: failed to open %s. %s\n",
785 full_clone_path
, strerror(-ret
));
789 clone_args
.src_fd
= clone_fd
;
790 clone_args
.src_offset
= clone_offset
;
791 clone_args
.src_length
= len
;
792 clone_args
.dest_offset
= offset
;
793 ret
= ioctl(r
->write_fd
, BTRFS_IOC_CLONE_RANGE
, &clone_args
);
796 fprintf(stderr
, "ERROR: failed to clone extents to %s\n%s\n",
797 path
, strerror(-ret
));
813 static int process_set_xattr(const char *path
, const char *name
,
814 const void *data
, int len
, void *user
)
817 struct btrfs_receive
*r
= user
;
818 char full_path
[PATH_MAX
];
820 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
822 fprintf(stderr
, "ERROR: set_xattr: path invalid: %s\n", path
);
826 if (strcmp("security.capability", name
) == 0) {
828 fprintf(stderr
, "set_xattr: cache capabilities\n");
829 if (r
->cached_capabilities_len
)
831 "WARNING: capabilities set multiple times per file: %s\n",
833 if (len
> sizeof(r
->cached_capabilities
)) {
835 "ERROR: capabilities encoded to %d bytes, buffer too small\n",
840 r
->cached_capabilities_len
= len
;
841 memcpy(r
->cached_capabilities
, data
, len
);
844 if (g_verbose
>= 2) {
845 fprintf(stderr
, "set_xattr %s - name=%s data_len=%d "
846 "data=%.*s\n", path
, name
, len
,
850 ret
= lsetxattr(full_path
, name
, data
, len
, 0);
853 fprintf(stderr
, "ERROR: lsetxattr %s %s=%.*s failed. %s\n",
854 path
, name
, len
, (char*)data
, strerror(-ret
));
862 static int process_remove_xattr(const char *path
, const char *name
, void *user
)
865 struct btrfs_receive
*r
= user
;
866 char full_path
[PATH_MAX
];
868 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
870 fprintf(stderr
, "ERROR: remove_xattr: path invalid: %s\n",
875 if (g_verbose
>= 2) {
876 fprintf(stderr
, "remove_xattr %s - name=%s\n",
880 ret
= lremovexattr(full_path
, name
);
883 fprintf(stderr
, "ERROR: lremovexattr %s %s failed. %s\n",
884 path
, name
, strerror(-ret
));
892 static int process_truncate(const char *path
, u64 size
, void *user
)
895 struct btrfs_receive
*r
= user
;
896 char full_path
[PATH_MAX
];
898 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
900 fprintf(stderr
, "ERROR: truncate: path invalid: %s\n", path
);
905 fprintf(stderr
, "truncate %s size=%llu\n", path
, size
);
907 ret
= truncate(full_path
, size
);
910 fprintf(stderr
, "ERROR: truncate %s failed. %s\n",
911 path
, strerror(-ret
));
919 static int process_chmod(const char *path
, u64 mode
, void *user
)
922 struct btrfs_receive
*r
= user
;
923 char full_path
[PATH_MAX
];
925 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
927 fprintf(stderr
, "ERROR: chmod: path invalid: %s\n", path
);
932 fprintf(stderr
, "chmod %s - mode=0%o\n", path
, (int)mode
);
934 ret
= chmod(full_path
, mode
);
937 fprintf(stderr
, "ERROR: chmod %s failed. %s\n",
938 path
, strerror(-ret
));
946 static int process_chown(const char *path
, u64 uid
, u64 gid
, void *user
)
949 struct btrfs_receive
*r
= user
;
950 char full_path
[PATH_MAX
];
952 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
954 fprintf(stderr
, "ERROR: chown: path invalid: %s\n", path
);
959 fprintf(stderr
, "chown %s - uid=%llu, gid=%llu\n", path
,
962 ret
= lchown(full_path
, uid
, gid
);
965 fprintf(stderr
, "ERROR: chown %s failed. %s\n",
966 path
, strerror(-ret
));
970 if (r
->cached_capabilities_len
) {
972 fprintf(stderr
, "chown: restore capabilities\n");
973 ret
= lsetxattr(full_path
, "security.capability",
974 r
->cached_capabilities
,
975 r
->cached_capabilities_len
, 0);
976 memset(r
->cached_capabilities
, 0,
977 sizeof(r
->cached_capabilities
));
978 r
->cached_capabilities_len
= 0;
981 fprintf(stderr
, "ERROR: restoring capabilities %s: %s\n",
982 path
, strerror(-ret
));
991 static int process_utimes(const char *path
, struct timespec
*at
,
992 struct timespec
*mt
, struct timespec
*ct
,
996 struct btrfs_receive
*r
= user
;
997 char full_path
[PATH_MAX
];
998 struct timespec tv
[2];
1000 ret
= path_cat_out(full_path
, r
->full_subvol_path
, path
);
1002 fprintf(stderr
, "ERROR: utimes: path invalid: %s\n", path
);
1007 fprintf(stderr
, "utimes %s\n", path
);
1011 ret
= utimensat(AT_FDCWD
, full_path
, tv
, AT_SYMLINK_NOFOLLOW
);
1014 fprintf(stderr
, "ERROR: utimes %s failed. %s\n",
1015 path
, strerror(-ret
));
1023 static int process_update_extent(const char *path
, u64 offset
, u64 len
,
1027 fprintf(stderr
, "update_extent %s: offset=%llu, len=%llu\n",
1028 path
, (unsigned long long)offset
,
1029 (unsigned long long)len
);
1032 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1038 static struct btrfs_send_ops send_ops
= {
1039 .subvol
= process_subvol
,
1040 .snapshot
= process_snapshot
,
1041 .mkfile
= process_mkfile
,
1042 .mkdir
= process_mkdir
,
1043 .mknod
= process_mknod
,
1044 .mkfifo
= process_mkfifo
,
1045 .mksock
= process_mksock
,
1046 .symlink
= process_symlink
,
1047 .rename
= process_rename
,
1048 .link
= process_link
,
1049 .unlink
= process_unlink
,
1050 .rmdir
= process_rmdir
,
1051 .write
= process_write
,
1052 .clone
= process_clone
,
1053 .set_xattr
= process_set_xattr
,
1054 .remove_xattr
= process_remove_xattr
,
1055 .truncate
= process_truncate
,
1056 .chmod
= process_chmod
,
1057 .chown
= process_chown
,
1058 .utimes
= process_utimes
,
1059 .update_extent
= process_update_extent
,
1062 static int do_receive(struct btrfs_receive
*r
, const char *tomnt
,
1063 char *realmnt
, int r_fd
, u64 max_errors
)
1067 char *dest_dir_full_path
;
1068 char root_subvol_path
[PATH_MAX
];
1071 dest_dir_full_path
= realpath(tomnt
, NULL
);
1072 if (!dest_dir_full_path
) {
1074 fprintf(stderr
, "ERROR: realpath(%s) failed. %s\n", tomnt
,
1078 r
->dest_dir_fd
= open(dest_dir_full_path
, O_RDONLY
| O_NOATIME
);
1079 if (r
->dest_dir_fd
< 0) {
1082 "ERROR: failed to open destination directory %s. %s\n",
1083 dest_dir_full_path
, strerror(-ret
));
1088 r
->root_path
= realmnt
;
1090 ret
= find_mount_root(dest_dir_full_path
, &r
->root_path
);
1093 "ERROR: failed to determine mount point for %s: %s\n",
1094 dest_dir_full_path
, strerror(-ret
));
1100 "ERROR: %s doesn't belong to btrfs mount point\n",
1101 dest_dir_full_path
);
1106 r
->mnt_fd
= open(r
->root_path
, O_RDONLY
| O_NOATIME
);
1107 if (r
->mnt_fd
< 0) {
1109 fprintf(stderr
, "ERROR: failed to open %s. %s\n", r
->root_path
,
1115 * If we use -m or a default subvol we want to resolve the path to the
1116 * subvolume we're sitting in so that we can adjust the paths of any
1117 * subvols we want to receive in.
1119 ret
= btrfs_list_get_path_rootid(r
->mnt_fd
, &subvol_id
);
1121 fprintf(stderr
, "ERROR: couldn't resolve our subvolid %d\n",
1126 root_subvol_path
[0] = 0;
1127 ret
= btrfs_subvolid_resolve(r
->mnt_fd
, root_subvol_path
,
1128 PATH_MAX
, subvol_id
);
1130 fprintf(stderr
, "ERROR: couldn't resolve our subvol path\n");
1135 * Ok we're inside of a subvol off of the root subvol, we need to
1136 * actually set full_root_path.
1138 if (strlen(root_subvol_path
))
1139 r
->full_root_path
= root_subvol_path
;
1141 if (r
->dest_dir_chroot
) {
1142 if (chroot(dest_dir_full_path
)) {
1145 "ERROR: failed to chroot to %s, %s\n",
1153 "ERROR: failed to chdir to /, %s\n",
1157 fprintf(stderr
, "Chroot to %s\n", dest_dir_full_path
);
1158 r
->root_path
= strdup("/");
1159 r
->dest_dir_path
= r
->root_path
;
1162 * find_mount_root returns a root_path that is a subpath of
1163 * dest_dir_full_path. Now get the other part of root_path,
1164 * which is the destination dir relative to root_path.
1166 r
->dest_dir_path
= dest_dir_full_path
+ strlen(r
->root_path
);
1167 while (r
->dest_dir_path
[0] == '/')
1171 ret
= subvol_uuid_search_init(r
->mnt_fd
, &r
->sus
);
1176 if (r
->cached_capabilities_len
) {
1178 fprintf(stderr
, "clear cached capabilities\n");
1179 memset(r
->cached_capabilities
, 0,
1180 sizeof(r
->cached_capabilities
));
1181 r
->cached_capabilities_len
= 0;
1184 ret
= btrfs_read_and_process_send_stream(r_fd
, &send_ops
, r
,
1192 close_inode_for_write(r
);
1193 ret
= finish_subvol(r
);
1200 if (r
->write_fd
!= -1) {
1205 r
->root_path
= NULL
;
1206 r
->dest_dir_path
= NULL
;
1207 free(dest_dir_full_path
);
1208 subvol_uuid_search_finit(&r
->sus
);
1209 if (r
->mnt_fd
!= -1) {
1213 if (r
->dest_dir_fd
!= -1) {
1214 close(r
->dest_dir_fd
);
1215 r
->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 r
;
1227 int receive_fd
= fileno(stdin
);
1231 memset(&r
, 0, sizeof(r
));
1235 r
.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
))) {
1258 "ERROR: input file path too long (%zu)\n",
1265 r
.honor_end_cmd
= 1;
1268 r
.dest_dir_chroot
= 1;
1271 max_errors
= arg_strtou64(optarg
);
1274 if (arg_copy_path(realmnt
, optarg
, sizeof(realmnt
))) {
1276 "ERROR: mount point path too long (%zu)\n",
1284 fprintf(stderr
, "ERROR: receive args invalid.\n");
1289 if (check_argc_exact(argc
- optind
, 1))
1290 usage(cmd_receive_usage
);
1292 tomnt
= argv
[optind
];
1295 receive_fd
= open(fromfile
, O_RDONLY
| O_NOATIME
);
1296 if (receive_fd
< 0) {
1297 fprintf(stderr
, "ERROR: failed to open %s\n", fromfile
);
1302 ret
= do_receive(&r
, tomnt
, realmnt
, receive_fd
, max_errors
);
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.",