btrfs-progs: check: Output verbose error when fsck found a bug in any tree
[btrfs-progs-unstable/devel.git] / cmds-receive.c
blobdf86c03fc9f3c9b116afc10007ae55f4388f8c12
1 /*
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"
22 #include <unistd.h>
23 #include <stdint.h>
24 #include <dirent.h>
25 #include <fcntl.h>
26 #include <pthread.h>
27 #include <math.h>
28 #include <ftw.h>
29 #include <sys/wait.h>
30 #include <assert.h>
31 #include <getopt.h>
32 #include <limits.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <sys/xattr.h>
40 #include <uuid/uuid.h>
42 #include "ctree.h"
43 #include "ioctl.h"
44 #include "commands.h"
45 #include "utils.h"
46 #include "list.h"
47 #include "btrfs-list.h"
49 #include "send.h"
50 #include "send-stream.h"
51 #include "send-utils.h"
52 #include "send-dump.h"
53 #include "help.h"
55 static int g_verbose = 0;
57 struct btrfs_receive
59 int mnt_fd;
60 int dest_dir_fd;
62 int write_fd;
63 char write_path[PATH_MAX];
65 char *root_path;
66 char *dest_dir_path; /* relative to root_path */
67 char full_subvol_path[PATH_MAX];
68 char *full_root_path;
69 int dest_dir_chroot;
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;
80 int honor_end_cmd;
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)
93 int ret;
94 int subvol_fd = -1;
95 struct btrfs_ioctl_received_subvol_args rs_args;
96 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
97 u64 flags;
99 if (rctx->cur_subvol_path[0] == 0)
100 return 0;
102 subvol_fd = openat(rctx->mnt_fd, rctx->cur_subvol_path,
103 O_RDONLY | O_NOATIME);
104 if (subvol_fd < 0) {
105 ret = -errno;
106 error("cannot open %s: %s",
107 rctx->cur_subvol_path, strerror(-ret));
108 goto out;
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);
122 if (ret < 0) {
123 ret = -errno;
124 error("ioctl BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s",
125 strerror(-ret));
126 goto out;
128 rctx->cur_subvol.rtransid = rs_args.rtransid;
130 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
131 if (ret < 0) {
132 ret = -errno;
133 error("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed: %s",
134 strerror(-ret));
135 goto out;
138 flags |= BTRFS_SUBVOL_RDONLY;
140 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
141 if (ret < 0) {
142 ret = -errno;
143 error("failed to make subvolume read only: %s",
144 strerror(-ret));
145 goto out;
148 ret = 0;
150 out:
151 if (rctx->cur_subvol_path[0]) {
152 rctx->cur_subvol_path[0] = 0;
154 if (subvol_fd != -1)
155 close(subvol_fd);
156 return ret;
159 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
160 void *user)
162 int ret;
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);
168 if (ret < 0)
169 goto out;
171 if (rctx->cur_subvol.path) {
172 error("subvol: another one already started, path ptr: %s",
173 rctx->cur_subvol.path);
174 ret = -EINVAL;
175 goto out;
177 if (rctx->cur_subvol_path[0]) {
178 error("subvol: another one already started, path buf: %s",
179 rctx->cur_subvol.path);
180 ret = -EINVAL;
181 goto out;
184 if (*rctx->dest_dir_path == 0) {
185 strncpy_null(rctx->cur_subvol_path, path);
186 } else {
187 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
188 path);
189 if (ret < 0) {
190 error("subvol: path invalid: %s", path);
191 goto out;
194 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
195 rctx->dest_dir_path, path);
196 if (ret < 0) {
197 error("subvol: path invalid: %s", path);
198 goto out;
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;
206 if (g_verbose) {
207 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
208 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
209 path, uuid_str,
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);
216 if (ret < 0) {
217 ret = -errno;
218 error("creating subvolume %s failed: %s", path, strerror(-ret));
219 goto out;
222 out:
223 return ret;
226 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
227 const u8 *parent_uuid, u64 parent_ctransid,
228 void *user)
230 int ret;
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);
237 if (ret < 0)
238 goto out;
240 if (rctx->cur_subvol.path) {
241 error("snapshot: another one already started, path ptr: %s",
242 rctx->cur_subvol.path);
243 ret = -EINVAL;
244 goto out;
246 if (rctx->cur_subvol_path[0]) {
247 error("snapshot: another one already started, path buf: %s",
248 rctx->cur_subvol.path);
249 ret = -EINVAL;
250 goto out;
253 if (*rctx->dest_dir_path == 0) {
254 strncpy_null(rctx->cur_subvol_path, path);
255 } else {
256 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
257 path);
258 if (ret < 0) {
259 error("snapshot: path invalid: %s", path);
260 goto out;
263 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
264 rctx->dest_dir_path, path);
265 if (ret < 0) {
266 error("snapshot: path invalid: %s", path);
267 goto out;
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;
275 if (g_verbose) {
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)) {
297 if (!parent_subvol)
298 ret = -ENOENT;
299 else
300 ret = PTR_ERR(parent_subvol);
301 error("cannot find parent subvolume");
302 goto out;
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) {
311 size_t root_len;
312 size_t sub_len;
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 (sub_len < root_len ||
319 strstr(parent_subvol->path, rctx->full_root_path) == NULL) {
320 error(
321 "parent subvol is not reachable from inside the root subvol");
322 ret = -ENOENT;
323 goto out;
326 if (sub_len == root_len) {
327 parent_subvol->path[0] = '/';
328 parent_subvol->path[1] = '\0';
329 } else {
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 -
337 * 1.
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) {
346 if (!r->force) {
347 ret = -EINVAL;
348 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
349 goto out;
350 } else {
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);
357 else
358 args_v2.fd = openat(rctx->mnt_fd, parent_subvol->path,
359 O_RDONLY | O_NOATIME);
360 if (args_v2.fd < 0) {
361 ret = -errno;
362 if (errno != ENOENT)
363 error("cannot open %s: %s",
364 parent_subvol->path, strerror(-ret));
365 else
366 fprintf(stderr,
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");
371 goto out;
374 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
375 close(args_v2.fd);
376 if (ret < 0) {
377 ret = -errno;
378 error("creating snapshot %s -> %s failed: %s",
379 parent_subvol->path, path, strerror(-ret));
380 goto out;
383 out:
384 if (parent_subvol) {
385 free(parent_subvol->path);
386 free(parent_subvol);
388 return ret;
391 static int process_mkfile(const char *path, void *user)
393 int ret;
394 struct btrfs_receive *rctx = user;
395 char full_path[PATH_MAX];
397 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
398 if (ret < 0) {
399 error("mkfile: path invalid: %s", path);
400 goto out;
403 if (g_verbose >= 2)
404 fprintf(stderr, "mkfile %s\n", path);
406 ret = creat(full_path, 0600);
407 if (ret < 0) {
408 ret = -errno;
409 error("mkfile %s failed: %s", path, strerror(-ret));
410 goto out;
412 close(ret);
413 ret = 0;
415 out:
416 return ret;
419 static int process_mkdir(const char *path, void *user)
421 int ret;
422 struct btrfs_receive *rctx = user;
423 char full_path[PATH_MAX];
425 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
426 if (ret < 0) {
427 error("mkdir: path invalid: %s", path);
428 goto out;
431 if (g_verbose >= 2)
432 fprintf(stderr, "mkdir %s\n", path);
434 ret = mkdir(full_path, 0700);
435 if (ret < 0) {
436 ret = -errno;
437 error("mkdir %s failed: %s", path, strerror(-ret));
440 out:
441 return ret;
444 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
446 int ret;
447 struct btrfs_receive *rctx = user;
448 char full_path[PATH_MAX];
450 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
451 if (ret < 0) {
452 error("mknod: path invalid: %s", path);
453 goto out;
456 if (g_verbose >= 2)
457 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
458 path, mode, dev);
460 ret = mknod(full_path, mode & S_IFMT, dev);
461 if (ret < 0) {
462 ret = -errno;
463 error("mknod %s failed: %s", path, strerror(-ret));
466 out:
467 return ret;
470 static int process_mkfifo(const char *path, void *user)
472 int ret;
473 struct btrfs_receive *rctx = user;
474 char full_path[PATH_MAX];
476 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
477 if (ret < 0) {
478 error("mkfifo: path invalid: %s", path);
479 goto out;
482 if (g_verbose >= 2)
483 fprintf(stderr, "mkfifo %s\n", path);
485 ret = mkfifo(full_path, 0600);
486 if (ret < 0) {
487 ret = -errno;
488 error("mkfifo %s failed: %s", path, strerror(-ret));
491 out:
492 return ret;
495 static int process_mksock(const char *path, void *user)
497 int ret;
498 struct btrfs_receive *rctx = user;
499 char full_path[PATH_MAX];
501 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
502 if (ret < 0) {
503 error("mksock: path invalid: %s", path);
504 goto out;
507 if (g_verbose >= 2)
508 fprintf(stderr, "mksock %s\n", path);
510 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
511 if (ret < 0) {
512 ret = -errno;
513 error("mknod %s failed: %s", path, strerror(-ret));
516 out:
517 return ret;
520 static int process_symlink(const char *path, const char *lnk, void *user)
522 int ret;
523 struct btrfs_receive *rctx = user;
524 char full_path[PATH_MAX];
526 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
527 if (ret < 0) {
528 error("symlink: path invalid: %s", path);
529 goto out;
532 if (g_verbose >= 2)
533 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
535 ret = symlink(lnk, full_path);
536 if (ret < 0) {
537 ret = -errno;
538 error("symlink %s -> %s failed: %s", path,
539 lnk, strerror(-ret));
542 out:
543 return ret;
546 static int process_rename(const char *from, const char *to, void *user)
548 int ret;
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);
554 if (ret < 0) {
555 error("rename: source path invalid: %s", from);
556 goto out;
559 ret = path_cat_out(full_to, rctx->full_subvol_path, to);
560 if (ret < 0) {
561 error("rename: target path invalid: %s", to);
562 goto out;
565 if (g_verbose >= 2)
566 fprintf(stderr, "rename %s -> %s\n", from, to);
568 ret = rename(full_from, full_to);
569 if (ret < 0) {
570 ret = -errno;
571 error("rename %s -> %s failed: %s", from,
572 to, strerror(-ret));
575 out:
576 return ret;
579 static int process_link(const char *path, const char *lnk, void *user)
581 int ret;
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);
587 if (ret < 0) {
588 error("link: source path invalid: %s", full_path);
589 goto out;
592 ret = path_cat_out(full_link_path, rctx->full_subvol_path, lnk);
593 if (ret < 0) {
594 error("link: target path invalid: %s", full_link_path);
595 goto out;
598 if (g_verbose >= 2)
599 fprintf(stderr, "link %s -> %s\n", path, lnk);
601 ret = link(full_link_path, full_path);
602 if (ret < 0) {
603 ret = -errno;
604 error("link %s -> %s failed: %s", path, lnk, strerror(-ret));
607 out:
608 return ret;
612 static int process_unlink(const char *path, void *user)
614 int ret;
615 struct btrfs_receive *rctx = user;
616 char full_path[PATH_MAX];
618 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
619 if (ret < 0) {
620 error("unlink: path invalid: %s", path);
621 goto out;
624 if (g_verbose >= 2)
625 fprintf(stderr, "unlink %s\n", path);
627 ret = unlink(full_path);
628 if (ret < 0) {
629 ret = -errno;
630 error("unlink %s failed. %s", path, strerror(-ret));
633 out:
634 return ret;
637 static int process_rmdir(const char *path, void *user)
639 int ret;
640 struct btrfs_receive *rctx = user;
641 char full_path[PATH_MAX];
643 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
644 if (ret < 0) {
645 error("rmdir: path invalid: %s", path);
646 goto out;
649 if (g_verbose >= 2)
650 fprintf(stderr, "rmdir %s\n", path);
652 ret = rmdir(full_path);
653 if (ret < 0) {
654 ret = -errno;
655 error("rmdir %s failed: %s", path, strerror(-ret));
658 out:
659 return ret;
662 static int open_inode_for_write(struct btrfs_receive *rctx, const char *path)
664 int ret = 0;
666 if (rctx->write_fd != -1) {
667 if (strcmp(rctx->write_path, path) == 0)
668 goto out;
669 close(rctx->write_fd);
670 rctx->write_fd = -1;
673 rctx->write_fd = open(path, O_RDWR);
674 if (rctx->write_fd < 0) {
675 ret = -errno;
676 error("cannot open %s: %s", path, strerror(-ret));
677 goto out;
679 strncpy_null(rctx->write_path, path);
681 out:
682 return ret;
685 static void close_inode_for_write(struct btrfs_receive *rctx)
687 if(rctx->write_fd == -1)
688 return;
690 close(rctx->write_fd);
691 rctx->write_fd = -1;
692 rctx->write_path[0] = 0;
695 static int process_write(const char *path, const void *data, u64 offset,
696 u64 len, void *user)
698 int ret = 0;
699 struct btrfs_receive *rctx = user;
700 char full_path[PATH_MAX];
701 u64 pos = 0;
702 int w;
704 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
705 if (ret < 0) {
706 error("write: path invalid: %s", path);
707 goto out;
710 ret = open_inode_for_write(rctx, full_path);
711 if (ret < 0)
712 goto out;
714 while (pos < len) {
715 w = pwrite(rctx->write_fd, (char*)data + pos, len - pos,
716 offset + pos);
717 if (w < 0) {
718 ret = -errno;
719 error("writing to %s failed: %s",
720 path, strerror(-ret));
721 goto out;
723 pos += w;
726 out:
727 return 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,
733 void *user)
735 int ret;
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];
742 int clone_fd = -1;
744 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
745 if (ret < 0) {
746 error("clone: source path invalid: %s", path);
747 goto out;
750 ret = open_inode_for_write(rctx, full_path);
751 if (ret < 0)
752 goto out;
754 si = subvol_uuid_search(&rctx->sus, 0, clone_uuid, clone_ctransid,
755 NULL,
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);
762 } else {
763 if (!si)
764 ret = -ENOENT;
765 else
766 ret = PTR_ERR(si);
767 error("clone: did not find source subvol");
768 goto out;
770 } else {
771 /*if (rs_args.ctransid > rs_args.rtransid) {
772 if (!r->force) {
773 ret = -EINVAL;
774 fprintf(stderr, "ERROR: subvolume %s was "
775 "modified after it was "
776 "received.\n",
777 r->subvol_parent_name);
778 goto out;
779 } else {
780 fprintf(stderr, "WARNING: subvolume %s was "
781 "modified after it was "
782 "received.\n",
783 r->subvol_parent_name);
786 subvol_path = strdup(si->path);
789 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
790 if (ret < 0) {
791 error("clone: target path invalid: %s", clone_path);
792 goto out;
795 clone_fd = openat(rctx->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
796 if (clone_fd < 0) {
797 ret = -errno;
798 error("cannot open %s: %s", full_clone_path, strerror(-ret));
799 goto out;
802 clone_args.src_fd = clone_fd;
803 clone_args.src_offset = clone_offset;
804 clone_args.src_length = len;
805 clone_args.dest_offset = offset;
806 ret = ioctl(rctx->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
807 if (ret < 0) {
808 ret = -errno;
809 error("failed to clone extents to %s\n%s",
810 path, strerror(-ret));
811 goto out;
814 out:
815 if (si) {
816 free(si->path);
817 free(si);
819 free(subvol_path);
820 if (clone_fd != -1)
821 close(clone_fd);
822 return ret;
826 static int process_set_xattr(const char *path, const char *name,
827 const void *data, int len, void *user)
829 int ret = 0;
830 struct btrfs_receive *rctx = user;
831 char full_path[PATH_MAX];
833 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
834 if (ret < 0) {
835 error("set_xattr: path invalid: %s", path);
836 goto out;
839 if (strcmp("security.capability", name) == 0) {
840 if (g_verbose >= 3)
841 fprintf(stderr, "set_xattr: cache capabilities\n");
842 if (rctx->cached_capabilities_len)
843 warning("capabilities set multiple times per file: %s",
844 full_path);
845 if (len > sizeof(rctx->cached_capabilities)) {
846 error("capabilities encoded to %d bytes, buffer too small",
847 len);
848 ret = -E2BIG;
849 goto out;
851 rctx->cached_capabilities_len = len;
852 memcpy(rctx->cached_capabilities, data, len);
855 if (g_verbose >= 2) {
856 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
857 "data=%.*s\n", path, name, len,
858 len, (char*)data);
861 ret = lsetxattr(full_path, name, data, len, 0);
862 if (ret < 0) {
863 ret = -errno;
864 error("lsetxattr %s %s=%.*s failed: %s",
865 path, name, len, (char*)data, strerror(-ret));
866 goto out;
869 out:
870 return ret;
873 static int process_remove_xattr(const char *path, const char *name, void *user)
875 int ret = 0;
876 struct btrfs_receive *rctx = user;
877 char full_path[PATH_MAX];
879 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
880 if (ret < 0) {
881 error("remove_xattr: path invalid: %s", path);
882 goto out;
885 if (g_verbose >= 2) {
886 fprintf(stderr, "remove_xattr %s - name=%s\n",
887 path, name);
890 ret = lremovexattr(full_path, name);
891 if (ret < 0) {
892 ret = -errno;
893 error("lremovexattr %s %s failed: %s",
894 path, name, strerror(-ret));
895 goto out;
898 out:
899 return ret;
902 static int process_truncate(const char *path, u64 size, void *user)
904 int ret = 0;
905 struct btrfs_receive *rctx = user;
906 char full_path[PATH_MAX];
908 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
909 if (ret < 0) {
910 error("truncate: path invalid: %s", path);
911 goto out;
914 if (g_verbose >= 2)
915 fprintf(stderr, "truncate %s size=%llu\n", path, size);
917 ret = truncate(full_path, size);
918 if (ret < 0) {
919 ret = -errno;
920 error("truncate %s failed: %s", path, strerror(-ret));
921 goto out;
924 out:
925 return ret;
928 static int process_chmod(const char *path, u64 mode, void *user)
930 int ret = 0;
931 struct btrfs_receive *rctx = user;
932 char full_path[PATH_MAX];
934 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
935 if (ret < 0) {
936 error("chmod: path invalid: %s", path);
937 goto out;
940 if (g_verbose >= 2)
941 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
943 ret = chmod(full_path, mode);
944 if (ret < 0) {
945 ret = -errno;
946 error("chmod %s failed: %s", path, strerror(-ret));
947 goto out;
950 out:
951 return ret;
954 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
956 int ret = 0;
957 struct btrfs_receive *rctx = user;
958 char full_path[PATH_MAX];
960 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
961 if (ret < 0) {
962 error("chown: path invalid: %s", path);
963 goto out;
966 if (g_verbose >= 2)
967 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
968 uid, gid);
970 ret = lchown(full_path, uid, gid);
971 if (ret < 0) {
972 ret = -errno;
973 error("chown %s failed: %s", path, strerror(-ret));
974 goto out;
977 if (rctx->cached_capabilities_len) {
978 if (g_verbose >= 2)
979 fprintf(stderr, "chown: restore capabilities\n");
980 ret = lsetxattr(full_path, "security.capability",
981 rctx->cached_capabilities,
982 rctx->cached_capabilities_len, 0);
983 memset(rctx->cached_capabilities, 0,
984 sizeof(rctx->cached_capabilities));
985 rctx->cached_capabilities_len = 0;
986 if (ret < 0) {
987 ret = -errno;
988 error("restoring capabilities %s: %s",
989 path, strerror(-ret));
990 goto out;
994 out:
995 return ret;
998 static int process_utimes(const char *path, struct timespec *at,
999 struct timespec *mt, struct timespec *ct,
1000 void *user)
1002 int ret = 0;
1003 struct btrfs_receive *rctx = user;
1004 char full_path[PATH_MAX];
1005 struct timespec tv[2];
1007 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
1008 if (ret < 0) {
1009 error("utimes: path invalid: %s", path);
1010 goto out;
1013 if (g_verbose >= 2)
1014 fprintf(stderr, "utimes %s\n", path);
1016 tv[0] = *at;
1017 tv[1] = *mt;
1018 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1019 if (ret < 0) {
1020 ret = -errno;
1021 error("utimes %s failed: %s",
1022 path, strerror(-ret));
1023 goto out;
1026 out:
1027 return ret;
1030 static int process_update_extent(const char *path, u64 offset, u64 len,
1031 void *user)
1033 if (g_verbose >= 2)
1034 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1035 path, (unsigned long long)offset,
1036 (unsigned long long)len);
1039 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1042 return 0;
1045 static struct btrfs_send_ops send_ops = {
1046 .subvol = process_subvol,
1047 .snapshot = process_snapshot,
1048 .mkfile = process_mkfile,
1049 .mkdir = process_mkdir,
1050 .mknod = process_mknod,
1051 .mkfifo = process_mkfifo,
1052 .mksock = process_mksock,
1053 .symlink = process_symlink,
1054 .rename = process_rename,
1055 .link = process_link,
1056 .unlink = process_unlink,
1057 .rmdir = process_rmdir,
1058 .write = process_write,
1059 .clone = process_clone,
1060 .set_xattr = process_set_xattr,
1061 .remove_xattr = process_remove_xattr,
1062 .truncate = process_truncate,
1063 .chmod = process_chmod,
1064 .chown = process_chown,
1065 .utimes = process_utimes,
1066 .update_extent = process_update_extent,
1069 static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
1070 char *realmnt, int r_fd, u64 max_errors)
1072 u64 subvol_id;
1073 int ret;
1074 char *dest_dir_full_path;
1075 char root_subvol_path[PATH_MAX];
1076 int end = 0;
1077 int count;
1079 dest_dir_full_path = realpath(tomnt, NULL);
1080 if (!dest_dir_full_path) {
1081 ret = -errno;
1082 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1083 goto out;
1085 rctx->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1086 if (rctx->dest_dir_fd < 0) {
1087 ret = -errno;
1088 error("cannot open destination directory %s: %s",
1089 dest_dir_full_path, strerror(-ret));
1090 goto out;
1093 if (realmnt[0]) {
1094 rctx->root_path = realmnt;
1095 } else {
1096 ret = find_mount_root(dest_dir_full_path, &rctx->root_path);
1097 if (ret < 0) {
1098 error("failed to determine mount point for %s: %s",
1099 dest_dir_full_path, strerror(-ret));
1100 ret = -EINVAL;
1101 goto out;
1103 if (ret > 0) {
1104 error("%s doesn't belong to btrfs mount point",
1105 dest_dir_full_path);
1106 ret = -EINVAL;
1107 goto out;
1110 rctx->mnt_fd = open(rctx->root_path, O_RDONLY | O_NOATIME);
1111 if (rctx->mnt_fd < 0) {
1112 ret = -errno;
1113 error("cannot open %s: %s", rctx->root_path, strerror(-ret));
1114 goto out;
1118 * If we use -m or a default subvol we want to resolve the path to the
1119 * subvolume we're sitting in so that we can adjust the paths of any
1120 * subvols we want to receive in.
1122 ret = btrfs_list_get_path_rootid(rctx->mnt_fd, &subvol_id);
1123 if (ret)
1124 goto out;
1126 root_subvol_path[0] = 0;
1127 ret = btrfs_subvolid_resolve(rctx->mnt_fd, root_subvol_path,
1128 PATH_MAX, subvol_id);
1129 if (ret) {
1130 error("cannot resolve our subvol path");
1131 goto out;
1135 * Ok we're inside of a subvol off of the root subvol, we need to
1136 * actually set full_root_path.
1138 if (*root_subvol_path)
1139 rctx->full_root_path = root_subvol_path;
1141 if (rctx->dest_dir_chroot) {
1142 if (chroot(dest_dir_full_path)) {
1143 ret = -errno;
1144 error("failed to chroot to %s: %s",
1145 dest_dir_full_path, strerror(-ret));
1146 goto out;
1148 if (chdir("/")) {
1149 ret = -errno;
1150 error("failed to chdir to / after chroot: %s",
1151 strerror(-ret));
1152 goto out;
1154 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1155 rctx->root_path = strdup("/");
1156 rctx->dest_dir_path = rctx->root_path;
1157 } else {
1159 * find_mount_root returns a root_path that is a subpath of
1160 * dest_dir_full_path. Now get the other part of root_path,
1161 * which is the destination dir relative to root_path.
1163 rctx->dest_dir_path = dest_dir_full_path + strlen(rctx->root_path);
1164 while (rctx->dest_dir_path[0] == '/')
1165 rctx->dest_dir_path++;
1168 ret = subvol_uuid_search_init(rctx->mnt_fd, &rctx->sus);
1169 if (ret < 0)
1170 goto out;
1172 count = 0;
1173 while (!end) {
1174 if (rctx->cached_capabilities_len) {
1175 if (g_verbose >= 3)
1176 fprintf(stderr, "clear cached capabilities\n");
1177 memset(rctx->cached_capabilities, 0,
1178 sizeof(rctx->cached_capabilities));
1179 rctx->cached_capabilities_len = 0;
1182 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops,
1183 rctx,
1184 rctx->honor_end_cmd,
1185 max_errors);
1186 if (ret < 0)
1187 goto out;
1188 /* Empty stream is invalid */
1189 if (ret && count == 0) {
1190 error("empty stream is not considered valid");
1191 ret = -EINVAL;
1192 goto out;
1194 count++;
1195 if (ret)
1196 end = 1;
1198 close_inode_for_write(rctx);
1199 ret = finish_subvol(rctx);
1200 if (ret < 0)
1201 goto out;
1203 ret = 0;
1205 out:
1206 if (rctx->write_fd != -1) {
1207 close(rctx->write_fd);
1208 rctx->write_fd = -1;
1211 if (rctx->root_path != realmnt)
1212 free(rctx->root_path);
1213 rctx->root_path = NULL;
1214 rctx->dest_dir_path = NULL;
1215 free(dest_dir_full_path);
1216 subvol_uuid_search_finit(&rctx->sus);
1217 if (rctx->mnt_fd != -1) {
1218 close(rctx->mnt_fd);
1219 rctx->mnt_fd = -1;
1221 if (rctx->dest_dir_fd != -1) {
1222 close(rctx->dest_dir_fd);
1223 rctx->dest_dir_fd = -1;
1226 return ret;
1229 int cmd_receive(int argc, char **argv)
1231 char *tomnt = NULL;
1232 char fromfile[PATH_MAX];
1233 char realmnt[PATH_MAX];
1234 struct btrfs_receive rctx;
1235 int receive_fd = fileno(stdin);
1236 u64 max_errors = 1;
1237 int dump = 0;
1238 int ret = 0;
1240 memset(&rctx, 0, sizeof(rctx));
1241 rctx.mnt_fd = -1;
1242 rctx.write_fd = -1;
1243 rctx.dest_dir_fd = -1;
1244 rctx.dest_dir_chroot = 0;
1245 realmnt[0] = 0;
1246 fromfile[0] = 0;
1248 while (1) {
1249 int c;
1250 enum { GETOPT_VAL_DUMP = 257 };
1251 static const struct option long_opts[] = {
1252 { "max-errors", required_argument, NULL, 'E' },
1253 { "chroot", no_argument, NULL, 'C' },
1254 { "dump", no_argument, NULL, GETOPT_VAL_DUMP },
1255 { NULL, 0, NULL, 0 }
1258 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1259 if (c < 0)
1260 break;
1262 switch (c) {
1263 case 'v':
1264 g_verbose++;
1265 break;
1266 case 'f':
1267 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1268 error("input file path too long (%zu)",
1269 strlen(optarg));
1270 ret = 1;
1271 goto out;
1273 break;
1274 case 'e':
1275 rctx.honor_end_cmd = 1;
1276 break;
1277 case 'C':
1278 rctx.dest_dir_chroot = 1;
1279 break;
1280 case 'E':
1281 max_errors = arg_strtou64(optarg);
1282 break;
1283 case 'm':
1284 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1285 error("mount point path too long (%zu)",
1286 strlen(optarg));
1287 ret = 1;
1288 goto out;
1290 break;
1291 case GETOPT_VAL_DUMP:
1292 dump = 1;
1293 break;
1294 case '?':
1295 default:
1296 error("receive args invalid");
1297 return 1;
1301 if (dump && check_argc_exact(argc - optind, 0))
1302 usage(cmd_receive_usage);
1303 if (!dump && check_argc_exact(argc - optind, 1))
1304 usage(cmd_receive_usage);
1306 tomnt = argv[optind];
1308 if (fromfile[0]) {
1309 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1310 if (receive_fd < 0) {
1311 error("cannot open %s: %s", fromfile, strerror(errno));
1312 goto out;
1316 if (dump) {
1317 struct btrfs_dump_send_args dump_args;
1319 dump_args.root_path[0] = '.';
1320 dump_args.root_path[1] = '\0';
1321 dump_args.full_subvol_path[0] = '.';
1322 dump_args.full_subvol_path[1] = '\0';
1323 ret = btrfs_read_and_process_send_stream(receive_fd,
1324 &btrfs_print_send_ops, &dump_args, 0, 0);
1325 if (ret < 0)
1326 error("failed to dump the send stream: %s",
1327 strerror(-ret));
1328 } else {
1329 ret = do_receive(&rctx, tomnt, realmnt, receive_fd, max_errors);
1332 if (receive_fd != fileno(stdin))
1333 close(receive_fd);
1334 out:
1336 return !!ret;
1339 const char * const cmd_receive_usage[] = {
1340 "btrfs receive [options] <mount>\n"
1341 "btrfs receive --dump [options]",
1342 "Receive subvolumes from a stream",
1343 "Receives one or more subvolumes that were previously",
1344 "sent with btrfs send. The received subvolumes are stored",
1345 "into MOUNT.",
1346 "The receive will fail in case the receiving subvolume",
1347 "already exists. It will also fail in case a previously",
1348 "received subvolume has been changed after it was received.",
1349 "After receiving a subvolume, it is immediately set to",
1350 "read-only.",
1352 "-v increase verbosity about performed actions",
1353 "-f FILE read the stream from FILE instead of stdin",
1354 "-e terminate after receiving an <end cmd> marker in the stream.",
1355 " Without this option the receiver side terminates only in case",
1356 " of an error on end of file.",
1357 "-C|--chroot confine the process to <mount> using chroot",
1358 "-E|--max-errors NERR",
1359 " terminate as soon as NERR errors occur while",
1360 " stream processing commands from the stream.",
1361 " Default value is 1. A value of 0 means no limit.",
1362 "-m ROOTMOUNT the root mount point of the destination filesystem.",
1363 " If /proc is not accessible, use this to tell us where",
1364 " this file system is mounted.",
1365 "--dump dump stream metadata, one line per operation,",
1366 " does not require the MOUNT parameter",
1367 NULL