2 * Copyright (C) 2012 Alexander Block. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #include "kerncompat.h"
20 #include "androidcompat.h"
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
38 #include <sys/types.h>
39 #include <sys/xattr.h>
40 #include <uuid/uuid.h>
47 #include "btrfs-list.h"
50 #include "send-stream.h"
51 #include "send-utils.h"
52 #include "send-dump.h"
55 static int g_verbose
= 0;
63 char write_path
[PATH_MAX
];
66 char *dest_dir_path
; /* relative to root_path */
67 char full_subvol_path
[PATH_MAX
];
71 struct subvol_info cur_subvol
;
73 * Substitute for cur_subvol::path which is a pointer and we cannot
74 * change it to an array as it's a public API.
76 char cur_subvol_path
[PATH_MAX
];
78 struct subvol_uuid_search sus
;
83 * Buffer to store capabilities from security.capabilities xattr,
84 * usually 20 bytes, but make same room for potentially larger
85 * encodings. Must be set only once per file, denoted by length > 0.
87 char cached_capabilities
[64];
88 int cached_capabilities_len
;
91 static int finish_subvol(struct btrfs_receive
*rctx
)
95 struct btrfs_ioctl_received_subvol_args rs_args
;
96 char uuid_str
[BTRFS_UUID_UNPARSED_SIZE
];
99 if (rctx
->cur_subvol_path
[0] == 0)
102 subvol_fd
= openat(rctx
->mnt_fd
, rctx
->cur_subvol_path
,
103 O_RDONLY
| O_NOATIME
);
106 error("cannot open %s: %s",
107 rctx
->cur_subvol_path
, strerror(-ret
));
111 memset(&rs_args
, 0, sizeof(rs_args
));
112 memcpy(rs_args
.uuid
, rctx
->cur_subvol
.received_uuid
, BTRFS_UUID_SIZE
);
113 rs_args
.stransid
= rctx
->cur_subvol
.stransid
;
115 if (g_verbose
>= 1) {
116 uuid_unparse((u8
*)rs_args
.uuid
, uuid_str
);
117 fprintf(stderr
, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
118 "stransid=%llu\n", uuid_str
, rs_args
.stransid
);
121 ret
= ioctl(subvol_fd
, BTRFS_IOC_SET_RECEIVED_SUBVOL
, &rs_args
);
124 error("ioctl BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s",
128 rctx
->cur_subvol
.rtransid
= rs_args
.rtransid
;
130 ret
= ioctl(subvol_fd
, BTRFS_IOC_SUBVOL_GETFLAGS
, &flags
);
133 error("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed: %s",
138 flags
|= BTRFS_SUBVOL_RDONLY
;
140 ret
= ioctl(subvol_fd
, BTRFS_IOC_SUBVOL_SETFLAGS
, &flags
);
143 error("failed to make subvolume read only: %s",
151 if (rctx
->cur_subvol_path
[0]) {
152 rctx
->cur_subvol_path
[0] = 0;
159 static int process_subvol(const char *path
, const u8
*uuid
, u64 ctransid
,
163 struct btrfs_receive
*rctx
= user
;
164 struct btrfs_ioctl_vol_args args_v1
;
165 char uuid_str
[BTRFS_UUID_UNPARSED_SIZE
];
167 ret
= finish_subvol(rctx
);
171 if (rctx
->cur_subvol
.path
) {
172 error("subvol: another one already started, path ptr: %s",
173 rctx
->cur_subvol
.path
);
177 if (rctx
->cur_subvol_path
[0]) {
178 error("subvol: another one already started, path buf: %s",
179 rctx
->cur_subvol
.path
);
184 if (*rctx
->dest_dir_path
== 0) {
185 strncpy_null(rctx
->cur_subvol_path
, path
);
187 ret
= path_cat_out(rctx
->cur_subvol_path
, rctx
->dest_dir_path
,
190 error("subvol: path invalid: %s", path
);
194 ret
= path_cat3_out(rctx
->full_subvol_path
, rctx
->root_path
,
195 rctx
->dest_dir_path
, path
);
197 error("subvol: path invalid: %s", path
);
201 fprintf(stderr
, "At subvol %s\n", path
);
203 memcpy(rctx
->cur_subvol
.received_uuid
, uuid
, BTRFS_UUID_SIZE
);
204 rctx
->cur_subvol
.stransid
= ctransid
;
207 uuid_unparse((u8
*)rctx
->cur_subvol
.received_uuid
, uuid_str
);
208 fprintf(stderr
, "receiving subvol %s uuid=%s, stransid=%llu\n",
210 rctx
->cur_subvol
.stransid
);
213 memset(&args_v1
, 0, sizeof(args_v1
));
214 strncpy_null(args_v1
.name
, path
);
215 ret
= ioctl(rctx
->dest_dir_fd
, BTRFS_IOC_SUBVOL_CREATE
, &args_v1
);
218 error("creating subvolume %s failed: %s", path
, strerror(-ret
));
226 static int process_snapshot(const char *path
, const u8
*uuid
, u64 ctransid
,
227 const u8
*parent_uuid
, u64 parent_ctransid
,
231 struct btrfs_receive
*rctx
= user
;
232 char uuid_str
[BTRFS_UUID_UNPARSED_SIZE
];
233 struct btrfs_ioctl_vol_args_v2 args_v2
;
234 struct subvol_info
*parent_subvol
= NULL
;
236 ret
= finish_subvol(rctx
);
240 if (rctx
->cur_subvol
.path
) {
241 error("snapshot: another one already started, path ptr: %s",
242 rctx
->cur_subvol
.path
);
246 if (rctx
->cur_subvol_path
[0]) {
247 error("snapshot: another one already started, path buf: %s",
248 rctx
->cur_subvol
.path
);
253 if (*rctx
->dest_dir_path
== 0) {
254 strncpy_null(rctx
->cur_subvol_path
, path
);
256 ret
= path_cat_out(rctx
->cur_subvol_path
, rctx
->dest_dir_path
,
259 error("snapshot: path invalid: %s", path
);
263 ret
= path_cat3_out(rctx
->full_subvol_path
, rctx
->root_path
,
264 rctx
->dest_dir_path
, path
);
266 error("snapshot: path invalid: %s", path
);
270 fprintf(stdout
, "At snapshot %s\n", path
);
272 memcpy(rctx
->cur_subvol
.received_uuid
, uuid
, BTRFS_UUID_SIZE
);
273 rctx
->cur_subvol
.stransid
= ctransid
;
276 uuid_unparse((u8
*)rctx
->cur_subvol
.received_uuid
, uuid_str
);
277 fprintf(stderr
, "receiving snapshot %s uuid=%s, "
278 "ctransid=%llu ", path
, uuid_str
,
279 rctx
->cur_subvol
.stransid
);
280 uuid_unparse(parent_uuid
, uuid_str
);
281 fprintf(stderr
, "parent_uuid=%s, parent_ctransid=%llu\n",
282 uuid_str
, parent_ctransid
);
285 memset(&args_v2
, 0, sizeof(args_v2
));
286 strncpy_null(args_v2
.name
, path
);
288 parent_subvol
= subvol_uuid_search(&rctx
->sus
, 0, parent_uuid
,
289 parent_ctransid
, NULL
,
290 subvol_search_by_received_uuid
);
291 if (IS_ERR_OR_NULL(parent_subvol
)) {
292 parent_subvol
= subvol_uuid_search(&rctx
->sus
, 0, parent_uuid
,
293 parent_ctransid
, NULL
,
294 subvol_search_by_uuid
);
296 if (IS_ERR_OR_NULL(parent_subvol
)) {
300 ret
= PTR_ERR(parent_subvol
);
301 error("cannot find parent subvolume");
306 * The path is resolved from the root subvol, but we could be in some
307 * subvolume under the root subvolume, so try and adjust the path to be
308 * relative to our root path.
310 if (rctx
->full_root_path
) {
314 root_len
= strlen(rctx
->full_root_path
);
315 sub_len
= strlen(parent_subvol
->path
);
317 /* First make sure the parent subvol is actually in our path */
318 if (strstr(parent_subvol
->path
, rctx
->full_root_path
) != parent_subvol
->path
||
319 (sub_len
> root_len
&& parent_subvol
->path
[root_len
] != '/')) {
321 "parent subvol is not reachable from inside the root subvol");
326 if (sub_len
== root_len
) {
327 parent_subvol
->path
[0] = '.';
328 parent_subvol
->path
[1] = '\0';
331 * root path is foo/bar
332 * subvol path is foo/bar/baz
334 * we need to have baz be the path, so we need to move
335 * the bit after foo/bar/, so path + root_len + 1, and
336 * move the part we care about, so sub_len - root_len -
339 memmove(parent_subvol
->path
,
340 parent_subvol
->path
+ root_len
+ 1,
341 sub_len
- root_len
- 1);
342 parent_subvol
->path
[sub_len
- root_len
- 1] = '\0';
345 /*if (rs_args.ctransid > rs_args.rtransid) {
348 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
351 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
355 if (*parent_subvol
->path
== 0)
356 args_v2
.fd
= dup(rctx
->mnt_fd
);
358 args_v2
.fd
= openat(rctx
->mnt_fd
, parent_subvol
->path
,
359 O_RDONLY
| O_NOATIME
);
360 if (args_v2
.fd
< 0) {
363 error("cannot open %s: %s",
364 parent_subvol
->path
, strerror(-ret
));
367 "It seems that you have changed your default "
368 "subvolume or you specify other subvolume to\n"
369 "mount btrfs, try to remount this btrfs filesystem "
370 "with fs tree, and run btrfs receive again!\n");
374 ret
= ioctl(rctx
->dest_dir_fd
, BTRFS_IOC_SNAP_CREATE_V2
, &args_v2
);
378 error("creating snapshot %s -> %s failed: %s",
379 parent_subvol
->path
, path
, strerror(-ret
));
385 free(parent_subvol
->path
);
391 static int process_mkfile(const char *path
, void *user
)
394 struct btrfs_receive
*rctx
= user
;
395 char full_path
[PATH_MAX
];
397 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
399 error("mkfile: path invalid: %s", path
);
404 fprintf(stderr
, "mkfile %s\n", path
);
406 ret
= creat(full_path
, 0600);
409 error("mkfile %s failed: %s", path
, strerror(-ret
));
419 static int process_mkdir(const char *path
, void *user
)
422 struct btrfs_receive
*rctx
= user
;
423 char full_path
[PATH_MAX
];
425 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
427 error("mkdir: path invalid: %s", path
);
432 fprintf(stderr
, "mkdir %s\n", path
);
434 ret
= mkdir(full_path
, 0700);
437 error("mkdir %s failed: %s", path
, strerror(-ret
));
444 static int process_mknod(const char *path
, u64 mode
, u64 dev
, void *user
)
447 struct btrfs_receive
*rctx
= user
;
448 char full_path
[PATH_MAX
];
450 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
452 error("mknod: path invalid: %s", path
);
457 fprintf(stderr
, "mknod %s mode=%llu, dev=%llu\n",
460 ret
= mknod(full_path
, mode
& S_IFMT
, dev
);
463 error("mknod %s failed: %s", path
, strerror(-ret
));
470 static int process_mkfifo(const char *path
, void *user
)
473 struct btrfs_receive
*rctx
= user
;
474 char full_path
[PATH_MAX
];
476 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
478 error("mkfifo: path invalid: %s", path
);
483 fprintf(stderr
, "mkfifo %s\n", path
);
485 ret
= mkfifo(full_path
, 0600);
488 error("mkfifo %s failed: %s", path
, strerror(-ret
));
495 static int process_mksock(const char *path
, void *user
)
498 struct btrfs_receive
*rctx
= user
;
499 char full_path
[PATH_MAX
];
501 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
503 error("mksock: path invalid: %s", path
);
508 fprintf(stderr
, "mksock %s\n", path
);
510 ret
= mknod(full_path
, 0600 | S_IFSOCK
, 0);
513 error("mknod %s failed: %s", path
, strerror(-ret
));
520 static int process_symlink(const char *path
, const char *lnk
, void *user
)
523 struct btrfs_receive
*rctx
= user
;
524 char full_path
[PATH_MAX
];
526 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
528 error("symlink: path invalid: %s", path
);
533 fprintf(stderr
, "symlink %s -> %s\n", path
, lnk
);
535 ret
= symlink(lnk
, full_path
);
538 error("symlink %s -> %s failed: %s", path
,
539 lnk
, strerror(-ret
));
546 static int process_rename(const char *from
, const char *to
, void *user
)
549 struct btrfs_receive
*rctx
= user
;
550 char full_from
[PATH_MAX
];
551 char full_to
[PATH_MAX
];
553 ret
= path_cat_out(full_from
, rctx
->full_subvol_path
, from
);
555 error("rename: source path invalid: %s", from
);
559 ret
= path_cat_out(full_to
, rctx
->full_subvol_path
, to
);
561 error("rename: target path invalid: %s", to
);
566 fprintf(stderr
, "rename %s -> %s\n", from
, to
);
568 ret
= rename(full_from
, full_to
);
571 error("rename %s -> %s failed: %s", from
,
579 static int process_link(const char *path
, const char *lnk
, void *user
)
582 struct btrfs_receive
*rctx
= user
;
583 char full_path
[PATH_MAX
];
584 char full_link_path
[PATH_MAX
];
586 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
588 error("link: source path invalid: %s", full_path
);
592 ret
= path_cat_out(full_link_path
, rctx
->full_subvol_path
, lnk
);
594 error("link: target path invalid: %s", full_link_path
);
599 fprintf(stderr
, "link %s -> %s\n", path
, lnk
);
601 ret
= link(full_link_path
, full_path
);
604 error("link %s -> %s failed: %s", path
, lnk
, strerror(-ret
));
612 static int process_unlink(const char *path
, void *user
)
615 struct btrfs_receive
*rctx
= user
;
616 char full_path
[PATH_MAX
];
618 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
620 error("unlink: path invalid: %s", path
);
625 fprintf(stderr
, "unlink %s\n", path
);
627 ret
= unlink(full_path
);
630 error("unlink %s failed. %s", path
, strerror(-ret
));
637 static int process_rmdir(const char *path
, void *user
)
640 struct btrfs_receive
*rctx
= user
;
641 char full_path
[PATH_MAX
];
643 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
645 error("rmdir: path invalid: %s", path
);
650 fprintf(stderr
, "rmdir %s\n", path
);
652 ret
= rmdir(full_path
);
655 error("rmdir %s failed: %s", path
, strerror(-ret
));
662 static int open_inode_for_write(struct btrfs_receive
*rctx
, const char *path
)
666 if (rctx
->write_fd
!= -1) {
667 if (strcmp(rctx
->write_path
, path
) == 0)
669 close(rctx
->write_fd
);
673 rctx
->write_fd
= open(path
, O_RDWR
);
674 if (rctx
->write_fd
< 0) {
676 error("cannot open %s: %s", path
, strerror(-ret
));
679 strncpy_null(rctx
->write_path
, path
);
685 static void close_inode_for_write(struct btrfs_receive
*rctx
)
687 if(rctx
->write_fd
== -1)
690 close(rctx
->write_fd
);
692 rctx
->write_path
[0] = 0;
695 static int process_write(const char *path
, const void *data
, u64 offset
,
699 struct btrfs_receive
*rctx
= user
;
700 char full_path
[PATH_MAX
];
704 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
706 error("write: path invalid: %s", path
);
710 ret
= open_inode_for_write(rctx
, full_path
);
715 w
= pwrite(rctx
->write_fd
, (char*)data
+ pos
, len
- pos
,
719 error("writing to %s failed: %s",
720 path
, strerror(-ret
));
730 static int process_clone(const char *path
, u64 offset
, u64 len
,
731 const u8
*clone_uuid
, u64 clone_ctransid
,
732 const char *clone_path
, u64 clone_offset
,
736 struct btrfs_receive
*rctx
= user
;
737 struct btrfs_ioctl_clone_range_args clone_args
;
738 struct subvol_info
*si
= NULL
;
739 char full_path
[PATH_MAX
];
740 char *subvol_path
= NULL
;
741 char full_clone_path
[PATH_MAX
];
744 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
746 error("clone: source path invalid: %s", path
);
750 ret
= open_inode_for_write(rctx
, full_path
);
754 si
= subvol_uuid_search(&rctx
->sus
, 0, clone_uuid
, clone_ctransid
,
756 subvol_search_by_received_uuid
);
757 if (IS_ERR_OR_NULL(si
)) {
758 if (memcmp(clone_uuid
, rctx
->cur_subvol
.received_uuid
,
759 BTRFS_UUID_SIZE
) == 0) {
760 /* TODO check generation of extent */
761 subvol_path
= strdup(rctx
->cur_subvol_path
);
767 error("clone: did not find source subvol");
771 /*if (rs_args.ctransid > rs_args.rtransid) {
774 fprintf(stderr, "ERROR: subvolume %s was "
775 "modified after it was "
777 r->subvol_parent_name);
780 fprintf(stderr, "WARNING: subvolume %s was "
781 "modified after it was "
783 r->subvol_parent_name);
787 /* strip the subvolume that we are receiving to from the start of subvol_path */
788 if (rctx
->full_root_path
) {
789 size_t root_len
= strlen(rctx
->full_root_path
);
790 size_t sub_len
= strlen(si
->path
);
792 if (sub_len
> root_len
&&
793 strstr(si
->path
, rctx
->full_root_path
) == si
->path
&&
794 si
->path
[root_len
] == '/') {
795 subvol_path
= strdup(si
->path
+ root_len
+ 1);
797 error("clone: source subvol path %s unreachable from %s",
798 si
->path
, rctx
->full_root_path
);
802 subvol_path
= strdup(si
->path
);
806 ret
= path_cat_out(full_clone_path
, subvol_path
, clone_path
);
808 error("clone: target path invalid: %s", clone_path
);
812 clone_fd
= openat(rctx
->mnt_fd
, full_clone_path
, O_RDONLY
| O_NOATIME
);
815 error("cannot open %s: %s", full_clone_path
, strerror(-ret
));
819 clone_args
.src_fd
= clone_fd
;
820 clone_args
.src_offset
= clone_offset
;
821 clone_args
.src_length
= len
;
822 clone_args
.dest_offset
= offset
;
823 ret
= ioctl(rctx
->write_fd
, BTRFS_IOC_CLONE_RANGE
, &clone_args
);
826 error("failed to clone extents to %s\n%s",
827 path
, strerror(-ret
));
843 static int process_set_xattr(const char *path
, const char *name
,
844 const void *data
, int len
, void *user
)
847 struct btrfs_receive
*rctx
= user
;
848 char full_path
[PATH_MAX
];
850 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
852 error("set_xattr: path invalid: %s", path
);
856 if (strcmp("security.capability", name
) == 0) {
858 fprintf(stderr
, "set_xattr: cache capabilities\n");
859 if (rctx
->cached_capabilities_len
)
860 warning("capabilities set multiple times per file: %s",
862 if (len
> sizeof(rctx
->cached_capabilities
)) {
863 error("capabilities encoded to %d bytes, buffer too small",
868 rctx
->cached_capabilities_len
= len
;
869 memcpy(rctx
->cached_capabilities
, data
, len
);
872 if (g_verbose
>= 2) {
873 fprintf(stderr
, "set_xattr %s - name=%s data_len=%d "
874 "data=%.*s\n", path
, name
, len
,
878 ret
= lsetxattr(full_path
, name
, data
, len
, 0);
881 error("lsetxattr %s %s=%.*s failed: %s",
882 path
, name
, len
, (char*)data
, strerror(-ret
));
890 static int process_remove_xattr(const char *path
, const char *name
, void *user
)
893 struct btrfs_receive
*rctx
= user
;
894 char full_path
[PATH_MAX
];
896 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
898 error("remove_xattr: path invalid: %s", path
);
902 if (g_verbose
>= 2) {
903 fprintf(stderr
, "remove_xattr %s - name=%s\n",
907 ret
= lremovexattr(full_path
, name
);
910 error("lremovexattr %s %s failed: %s",
911 path
, name
, strerror(-ret
));
919 static int process_truncate(const char *path
, u64 size
, void *user
)
922 struct btrfs_receive
*rctx
= user
;
923 char full_path
[PATH_MAX
];
925 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
927 error("truncate: path invalid: %s", path
);
932 fprintf(stderr
, "truncate %s size=%llu\n", path
, size
);
934 ret
= truncate(full_path
, size
);
937 error("truncate %s failed: %s", path
, strerror(-ret
));
945 static int process_chmod(const char *path
, u64 mode
, void *user
)
948 struct btrfs_receive
*rctx
= user
;
949 char full_path
[PATH_MAX
];
951 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
953 error("chmod: path invalid: %s", path
);
958 fprintf(stderr
, "chmod %s - mode=0%o\n", path
, (int)mode
);
960 ret
= chmod(full_path
, mode
);
963 error("chmod %s failed: %s", path
, strerror(-ret
));
971 static int process_chown(const char *path
, u64 uid
, u64 gid
, void *user
)
974 struct btrfs_receive
*rctx
= user
;
975 char full_path
[PATH_MAX
];
977 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
979 error("chown: path invalid: %s", path
);
984 fprintf(stderr
, "chown %s - uid=%llu, gid=%llu\n", path
,
987 ret
= lchown(full_path
, uid
, gid
);
990 error("chown %s failed: %s", path
, strerror(-ret
));
994 if (rctx
->cached_capabilities_len
) {
996 fprintf(stderr
, "chown: restore capabilities\n");
997 ret
= lsetxattr(full_path
, "security.capability",
998 rctx
->cached_capabilities
,
999 rctx
->cached_capabilities_len
, 0);
1000 memset(rctx
->cached_capabilities
, 0,
1001 sizeof(rctx
->cached_capabilities
));
1002 rctx
->cached_capabilities_len
= 0;
1005 error("restoring capabilities %s: %s",
1006 path
, strerror(-ret
));
1015 static int process_utimes(const char *path
, struct timespec
*at
,
1016 struct timespec
*mt
, struct timespec
*ct
,
1020 struct btrfs_receive
*rctx
= user
;
1021 char full_path
[PATH_MAX
];
1022 struct timespec tv
[2];
1024 ret
= path_cat_out(full_path
, rctx
->full_subvol_path
, path
);
1026 error("utimes: path invalid: %s", path
);
1031 fprintf(stderr
, "utimes %s\n", path
);
1035 ret
= utimensat(AT_FDCWD
, full_path
, tv
, AT_SYMLINK_NOFOLLOW
);
1038 error("utimes %s failed: %s",
1039 path
, strerror(-ret
));
1047 static int process_update_extent(const char *path
, u64 offset
, u64 len
,
1051 fprintf(stderr
, "update_extent %s: offset=%llu, len=%llu\n",
1052 path
, (unsigned long long)offset
,
1053 (unsigned long long)len
);
1056 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1062 static struct btrfs_send_ops send_ops
= {
1063 .subvol
= process_subvol
,
1064 .snapshot
= process_snapshot
,
1065 .mkfile
= process_mkfile
,
1066 .mkdir
= process_mkdir
,
1067 .mknod
= process_mknod
,
1068 .mkfifo
= process_mkfifo
,
1069 .mksock
= process_mksock
,
1070 .symlink
= process_symlink
,
1071 .rename
= process_rename
,
1072 .link
= process_link
,
1073 .unlink
= process_unlink
,
1074 .rmdir
= process_rmdir
,
1075 .write
= process_write
,
1076 .clone
= process_clone
,
1077 .set_xattr
= process_set_xattr
,
1078 .remove_xattr
= process_remove_xattr
,
1079 .truncate
= process_truncate
,
1080 .chmod
= process_chmod
,
1081 .chown
= process_chown
,
1082 .utimes
= process_utimes
,
1083 .update_extent
= process_update_extent
,
1086 static int do_receive(struct btrfs_receive
*rctx
, const char *tomnt
,
1087 char *realmnt
, int r_fd
, u64 max_errors
)
1091 char *dest_dir_full_path
;
1092 char root_subvol_path
[PATH_MAX
];
1096 dest_dir_full_path
= realpath(tomnt
, NULL
);
1097 if (!dest_dir_full_path
) {
1099 error("realpath(%s) failed: %s", tomnt
, strerror(-ret
));
1102 rctx
->dest_dir_fd
= open(dest_dir_full_path
, O_RDONLY
| O_NOATIME
);
1103 if (rctx
->dest_dir_fd
< 0) {
1105 error("cannot open destination directory %s: %s",
1106 dest_dir_full_path
, strerror(-ret
));
1111 rctx
->root_path
= realmnt
;
1113 ret
= find_mount_root(dest_dir_full_path
, &rctx
->root_path
);
1115 error("failed to determine mount point for %s: %s",
1116 dest_dir_full_path
, strerror(-ret
));
1121 error("%s doesn't belong to btrfs mount point",
1122 dest_dir_full_path
);
1127 rctx
->mnt_fd
= open(rctx
->root_path
, O_RDONLY
| O_NOATIME
);
1128 if (rctx
->mnt_fd
< 0) {
1130 error("cannot open %s: %s", rctx
->root_path
, strerror(-ret
));
1135 * If we use -m or a default subvol we want to resolve the path to the
1136 * subvolume we're sitting in so that we can adjust the paths of any
1137 * subvols we want to receive in.
1139 ret
= btrfs_list_get_path_rootid(rctx
->mnt_fd
, &subvol_id
);
1143 root_subvol_path
[0] = 0;
1144 ret
= btrfs_subvolid_resolve(rctx
->mnt_fd
, root_subvol_path
,
1145 PATH_MAX
, subvol_id
);
1147 error("cannot resolve our subvol path");
1152 * Ok we're inside of a subvol off of the root subvol, we need to
1153 * actually set full_root_path.
1155 if (*root_subvol_path
)
1156 rctx
->full_root_path
= root_subvol_path
;
1158 if (rctx
->dest_dir_chroot
) {
1159 if (chroot(dest_dir_full_path
)) {
1161 error("failed to chroot to %s: %s",
1162 dest_dir_full_path
, strerror(-ret
));
1167 error("failed to chdir to / after chroot: %s",
1171 fprintf(stderr
, "Chroot to %s\n", dest_dir_full_path
);
1172 rctx
->root_path
= strdup("/");
1173 rctx
->dest_dir_path
= rctx
->root_path
;
1176 * find_mount_root returns a root_path that is a subpath of
1177 * dest_dir_full_path. Now get the other part of root_path,
1178 * which is the destination dir relative to root_path.
1180 rctx
->dest_dir_path
= dest_dir_full_path
+ strlen(rctx
->root_path
);
1181 while (rctx
->dest_dir_path
[0] == '/')
1182 rctx
->dest_dir_path
++;
1185 ret
= subvol_uuid_search_init(rctx
->mnt_fd
, &rctx
->sus
);
1190 if (rctx
->cached_capabilities_len
) {
1192 fprintf(stderr
, "clear cached capabilities\n");
1193 memset(rctx
->cached_capabilities
, 0,
1194 sizeof(rctx
->cached_capabilities
));
1195 rctx
->cached_capabilities_len
= 0;
1198 ret
= btrfs_read_and_process_send_stream(r_fd
, &send_ops
,
1200 rctx
->honor_end_cmd
,
1203 if (ret
!= -ENODATA
)
1206 /* Empty stream is invalid */
1207 if (iterations
== 0) {
1208 error("empty stream is not considered valid");
1218 close_inode_for_write(rctx
);
1219 ret
= finish_subvol(rctx
);
1228 if (rctx
->write_fd
!= -1) {
1229 close(rctx
->write_fd
);
1230 rctx
->write_fd
= -1;
1233 if (rctx
->root_path
!= realmnt
)
1234 free(rctx
->root_path
);
1235 rctx
->root_path
= NULL
;
1236 rctx
->dest_dir_path
= NULL
;
1237 free(dest_dir_full_path
);
1238 subvol_uuid_search_finit(&rctx
->sus
);
1239 if (rctx
->mnt_fd
!= -1) {
1240 close(rctx
->mnt_fd
);
1243 if (rctx
->dest_dir_fd
!= -1) {
1244 close(rctx
->dest_dir_fd
);
1245 rctx
->dest_dir_fd
= -1;
1251 int cmd_receive(int argc
, char **argv
)
1254 char fromfile
[PATH_MAX
];
1255 char realmnt
[PATH_MAX
];
1256 struct btrfs_receive rctx
;
1257 int receive_fd
= fileno(stdin
);
1262 memset(&rctx
, 0, sizeof(rctx
));
1265 rctx
.dest_dir_fd
= -1;
1266 rctx
.dest_dir_chroot
= 0;
1272 enum { GETOPT_VAL_DUMP
= 257 };
1273 static const struct option long_opts
[] = {
1274 { "max-errors", required_argument
, NULL
, 'E' },
1275 { "chroot", no_argument
, NULL
, 'C' },
1276 { "dump", no_argument
, NULL
, GETOPT_VAL_DUMP
},
1277 { NULL
, 0, NULL
, 0 }
1280 c
= getopt_long(argc
, argv
, "Cevf:m:E:", long_opts
, NULL
);
1289 if (arg_copy_path(fromfile
, optarg
, sizeof(fromfile
))) {
1290 error("input file path too long (%zu)",
1297 rctx
.honor_end_cmd
= 1;
1300 rctx
.dest_dir_chroot
= 1;
1303 max_errors
= arg_strtou64(optarg
);
1306 if (arg_copy_path(realmnt
, optarg
, sizeof(realmnt
))) {
1307 error("mount point path too long (%zu)",
1313 case GETOPT_VAL_DUMP
:
1318 error("receive args invalid");
1323 if (dump
&& check_argc_exact(argc
- optind
, 0))
1324 usage(cmd_receive_usage
);
1325 if (!dump
&& check_argc_exact(argc
- optind
, 1))
1326 usage(cmd_receive_usage
);
1328 tomnt
= argv
[optind
];
1331 receive_fd
= open(fromfile
, O_RDONLY
| O_NOATIME
);
1332 if (receive_fd
< 0) {
1333 error("cannot open %s: %m", fromfile
);
1339 struct btrfs_dump_send_args dump_args
;
1341 dump_args
.root_path
[0] = '.';
1342 dump_args
.root_path
[1] = '\0';
1343 dump_args
.full_subvol_path
[0] = '.';
1344 dump_args
.full_subvol_path
[1] = '\0';
1345 ret
= btrfs_read_and_process_send_stream(receive_fd
,
1346 &btrfs_print_send_ops
, &dump_args
, 0, 0);
1348 error("failed to dump the send stream: %s",
1351 ret
= do_receive(&rctx
, tomnt
, realmnt
, receive_fd
, max_errors
);
1354 if (receive_fd
!= fileno(stdin
))
1361 const char * const cmd_receive_usage
[] = {
1362 "btrfs receive [options] <mount>\n"
1363 "btrfs receive --dump [options]",
1364 "Receive subvolumes from a stream",
1365 "Receives one or more subvolumes that were previously",
1366 "sent with btrfs send. The received subvolumes are stored",
1368 "The receive will fail in case the receiving subvolume",
1369 "already exists. It will also fail in case a previously",
1370 "received subvolume has been changed after it was received.",
1371 "After receiving a subvolume, it is immediately set to",
1374 "-v increase verbosity about performed actions",
1375 "-f FILE read the stream from FILE instead of stdin",
1376 "-e terminate after receiving an <end cmd> marker in the stream.",
1377 " Without this option the receiver side terminates only in case",
1378 " of an error on end of file.",
1379 "-C|--chroot confine the process to <mount> using chroot",
1380 "-E|--max-errors NERR",
1381 " terminate as soon as NERR errors occur while",
1382 " stream processing commands from the stream.",
1383 " Default value is 1. A value of 0 means no limit.",
1384 "-m ROOTMOUNT the root mount point of the destination filesystem.",
1385 " If /proc is not accessible, use this to tell us where",
1386 " this file system is mounted.",
1387 "--dump dump stream metadata, one line per operation,",
1388 " does not require the MOUNT parameter",