Btrfs progs v4.9.1
[btrfs-progs-unstable/devel.git] / cmds-receive.c
blob166d37dcdb8b1a04e4d767834f67ebd759484d55
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"
54 static int g_verbose = 0;
56 struct btrfs_receive
58 int mnt_fd;
59 int dest_dir_fd;
61 int write_fd;
62 char write_path[PATH_MAX];
64 char *root_path;
65 char *dest_dir_path; /* relative to root_path */
66 char full_subvol_path[PATH_MAX];
67 char *full_root_path;
68 int dest_dir_chroot;
70 struct subvol_info cur_subvol;
72 * Substitute for cur_subvol::path which is a pointer and we cannot
73 * change it to an array as it's a public API.
75 char cur_subvol_path[PATH_MAX];
77 struct subvol_uuid_search sus;
79 int honor_end_cmd;
82 * Buffer to store capabilities from security.capabilities xattr,
83 * usually 20 bytes, but make same room for potentially larger
84 * encodings. Must be set only once per file, denoted by length > 0.
86 char cached_capabilities[64];
87 int cached_capabilities_len;
90 static int finish_subvol(struct btrfs_receive *rctx)
92 int ret;
93 int subvol_fd = -1;
94 struct btrfs_ioctl_received_subvol_args rs_args;
95 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
96 u64 flags;
98 if (rctx->cur_subvol_path[0] == 0)
99 return 0;
101 subvol_fd = openat(rctx->mnt_fd, rctx->cur_subvol_path,
102 O_RDONLY | O_NOATIME);
103 if (subvol_fd < 0) {
104 ret = -errno;
105 error("cannot open %s: %s",
106 rctx->cur_subvol_path, strerror(-ret));
107 goto out;
110 memset(&rs_args, 0, sizeof(rs_args));
111 memcpy(rs_args.uuid, rctx->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
112 rs_args.stransid = rctx->cur_subvol.stransid;
114 if (g_verbose >= 1) {
115 uuid_unparse((u8*)rs_args.uuid, uuid_str);
116 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
117 "stransid=%llu\n", uuid_str, rs_args.stransid);
120 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
121 if (ret < 0) {
122 ret = -errno;
123 error("ioctl BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s",
124 strerror(-ret));
125 goto out;
127 rctx->cur_subvol.rtransid = rs_args.rtransid;
129 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
130 if (ret < 0) {
131 ret = -errno;
132 error("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed: %s",
133 strerror(-ret));
134 goto out;
137 flags |= BTRFS_SUBVOL_RDONLY;
139 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
140 if (ret < 0) {
141 ret = -errno;
142 error("failed to make subvolume read only: %s",
143 strerror(-ret));
144 goto out;
147 ret = 0;
149 out:
150 if (rctx->cur_subvol_path[0]) {
151 rctx->cur_subvol_path[0] = 0;
153 if (subvol_fd != -1)
154 close(subvol_fd);
155 return ret;
158 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
159 void *user)
161 int ret;
162 struct btrfs_receive *rctx = user;
163 struct btrfs_ioctl_vol_args args_v1;
164 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
166 ret = finish_subvol(rctx);
167 if (ret < 0)
168 goto out;
170 if (rctx->cur_subvol.path) {
171 error("subvol: another one already started, path ptr: %s",
172 rctx->cur_subvol.path);
173 ret = -EINVAL;
174 goto out;
176 if (rctx->cur_subvol_path[0]) {
177 error("subvol: another one already started, path buf: %s",
178 rctx->cur_subvol.path);
179 ret = -EINVAL;
180 goto out;
183 if (*rctx->dest_dir_path == 0) {
184 strncpy_null(rctx->cur_subvol_path, path);
185 } else {
186 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
187 path);
188 if (ret < 0) {
189 error("subvol: path invalid: %s", path);
190 goto out;
193 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
194 rctx->dest_dir_path, path);
195 if (ret < 0) {
196 error("subvol: path invalid: %s", path);
197 goto out;
200 fprintf(stderr, "At subvol %s\n", path);
202 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
203 rctx->cur_subvol.stransid = ctransid;
205 if (g_verbose) {
206 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
207 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
208 path, uuid_str,
209 rctx->cur_subvol.stransid);
212 memset(&args_v1, 0, sizeof(args_v1));
213 strncpy_null(args_v1.name, path);
214 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
215 if (ret < 0) {
216 ret = -errno;
217 error("creating subvolume %s failed: %s", path, strerror(-ret));
218 goto out;
221 out:
222 return ret;
225 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
226 const u8 *parent_uuid, u64 parent_ctransid,
227 void *user)
229 int ret;
230 struct btrfs_receive *rctx = user;
231 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
232 struct btrfs_ioctl_vol_args_v2 args_v2;
233 struct subvol_info *parent_subvol = NULL;
235 ret = finish_subvol(rctx);
236 if (ret < 0)
237 goto out;
239 if (rctx->cur_subvol.path) {
240 error("snapshot: another one already started, path ptr: %s",
241 rctx->cur_subvol.path);
242 ret = -EINVAL;
243 goto out;
245 if (rctx->cur_subvol_path[0]) {
246 error("snapshot: another one already started, path buf: %s",
247 rctx->cur_subvol.path);
248 ret = -EINVAL;
249 goto out;
252 if (*rctx->dest_dir_path == 0) {
253 strncpy_null(rctx->cur_subvol_path, path);
254 } else {
255 ret = path_cat_out(rctx->cur_subvol_path, rctx->dest_dir_path,
256 path);
257 if (ret < 0) {
258 error("snapshot: path invalid: %s", path);
259 goto out;
262 ret = path_cat3_out(rctx->full_subvol_path, rctx->root_path,
263 rctx->dest_dir_path, path);
264 if (ret < 0) {
265 error("snapshot: path invalid: %s", path);
266 goto out;
269 fprintf(stdout, "At snapshot %s\n", path);
271 memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
272 rctx->cur_subvol.stransid = ctransid;
274 if (g_verbose) {
275 uuid_unparse((u8*)rctx->cur_subvol.received_uuid, uuid_str);
276 fprintf(stderr, "receiving snapshot %s uuid=%s, "
277 "ctransid=%llu ", path, uuid_str,
278 rctx->cur_subvol.stransid);
279 uuid_unparse(parent_uuid, uuid_str);
280 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
281 uuid_str, parent_ctransid);
284 memset(&args_v2, 0, sizeof(args_v2));
285 strncpy_null(args_v2.name, path);
287 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
288 parent_ctransid, NULL,
289 subvol_search_by_received_uuid);
290 if (IS_ERR_OR_NULL(parent_subvol)) {
291 parent_subvol = subvol_uuid_search(&rctx->sus, 0, parent_uuid,
292 parent_ctransid, NULL,
293 subvol_search_by_uuid);
295 if (IS_ERR_OR_NULL(parent_subvol)) {
296 if (!parent_subvol)
297 ret = -ENOENT;
298 else
299 ret = PTR_ERR(parent_subvol);
300 error("cannot find parent subvolume");
301 goto out;
305 * The path is resolved from the root subvol, but we could be in some
306 * subvolume under the root subvolume, so try and adjust the path to be
307 * relative to our root path.
309 if (rctx->full_root_path) {
310 size_t root_len;
311 size_t sub_len;
313 root_len = strlen(rctx->full_root_path);
314 sub_len = strlen(parent_subvol->path);
316 /* First make sure the parent subvol is actually in our path */
317 if (sub_len < root_len ||
318 strstr(parent_subvol->path, rctx->full_root_path) == NULL) {
319 error(
320 "parent subvol is not reachable from inside the root subvol");
321 ret = -ENOENT;
322 goto out;
325 if (sub_len == root_len) {
326 parent_subvol->path[0] = '/';
327 parent_subvol->path[1] = '\0';
328 } else {
330 * root path is foo/bar
331 * subvol path is foo/bar/baz
333 * we need to have baz be the path, so we need to move
334 * the bit after foo/bar/, so path + root_len + 1, and
335 * move the part we care about, so sub_len - root_len -
336 * 1.
338 memmove(parent_subvol->path,
339 parent_subvol->path + root_len + 1,
340 sub_len - root_len - 1);
341 parent_subvol->path[sub_len - root_len - 1] = '\0';
344 /*if (rs_args.ctransid > rs_args.rtransid) {
345 if (!r->force) {
346 ret = -EINVAL;
347 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
348 goto out;
349 } else {
350 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
354 if (*parent_subvol->path == 0)
355 args_v2.fd = dup(rctx->mnt_fd);
356 else
357 args_v2.fd = openat(rctx->mnt_fd, parent_subvol->path,
358 O_RDONLY | O_NOATIME);
359 if (args_v2.fd < 0) {
360 ret = -errno;
361 if (errno != ENOENT)
362 error("cannot open %s: %s",
363 parent_subvol->path, strerror(-ret));
364 else
365 fprintf(stderr,
366 "It seems that you have changed your default "
367 "subvolume or you specify other subvolume to\n"
368 "mount btrfs, try to remount this btrfs filesystem "
369 "with fs tree, and run btrfs receive again!\n");
370 goto out;
373 ret = ioctl(rctx->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
374 close(args_v2.fd);
375 if (ret < 0) {
376 ret = -errno;
377 error("creating snapshot %s -> %s failed: %s",
378 parent_subvol->path, path, strerror(-ret));
379 goto out;
382 out:
383 if (parent_subvol) {
384 free(parent_subvol->path);
385 free(parent_subvol);
387 return ret;
390 static int process_mkfile(const char *path, void *user)
392 int ret;
393 struct btrfs_receive *rctx = user;
394 char full_path[PATH_MAX];
396 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
397 if (ret < 0) {
398 error("mkfile: path invalid: %s", path);
399 goto out;
402 if (g_verbose >= 2)
403 fprintf(stderr, "mkfile %s\n", path);
405 ret = creat(full_path, 0600);
406 if (ret < 0) {
407 ret = -errno;
408 error("mkfile %s failed: %s", path, strerror(-ret));
409 goto out;
411 close(ret);
412 ret = 0;
414 out:
415 return ret;
418 static int process_mkdir(const char *path, void *user)
420 int ret;
421 struct btrfs_receive *rctx = user;
422 char full_path[PATH_MAX];
424 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
425 if (ret < 0) {
426 error("mkdir: path invalid: %s", path);
427 goto out;
430 if (g_verbose >= 2)
431 fprintf(stderr, "mkdir %s\n", path);
433 ret = mkdir(full_path, 0700);
434 if (ret < 0) {
435 ret = -errno;
436 error("mkdir %s failed: %s", path, strerror(-ret));
439 out:
440 return ret;
443 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
445 int ret;
446 struct btrfs_receive *rctx = user;
447 char full_path[PATH_MAX];
449 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
450 if (ret < 0) {
451 error("mknod: path invalid: %s", path);
452 goto out;
455 if (g_verbose >= 2)
456 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
457 path, mode, dev);
459 ret = mknod(full_path, mode & S_IFMT, dev);
460 if (ret < 0) {
461 ret = -errno;
462 error("mknod %s failed: %s", path, strerror(-ret));
465 out:
466 return ret;
469 static int process_mkfifo(const char *path, void *user)
471 int ret;
472 struct btrfs_receive *rctx = user;
473 char full_path[PATH_MAX];
475 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
476 if (ret < 0) {
477 error("mkfifo: path invalid: %s", path);
478 goto out;
481 if (g_verbose >= 2)
482 fprintf(stderr, "mkfifo %s\n", path);
484 ret = mkfifo(full_path, 0600);
485 if (ret < 0) {
486 ret = -errno;
487 error("mkfifo %s failed: %s", path, strerror(-ret));
490 out:
491 return ret;
494 static int process_mksock(const char *path, void *user)
496 int ret;
497 struct btrfs_receive *rctx = user;
498 char full_path[PATH_MAX];
500 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
501 if (ret < 0) {
502 error("mksock: path invalid: %s", path);
503 goto out;
506 if (g_verbose >= 2)
507 fprintf(stderr, "mksock %s\n", path);
509 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
510 if (ret < 0) {
511 ret = -errno;
512 error("mknod %s failed: %s", path, strerror(-ret));
515 out:
516 return ret;
519 static int process_symlink(const char *path, const char *lnk, void *user)
521 int ret;
522 struct btrfs_receive *rctx = user;
523 char full_path[PATH_MAX];
525 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
526 if (ret < 0) {
527 error("symlink: path invalid: %s", path);
528 goto out;
531 if (g_verbose >= 2)
532 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
534 ret = symlink(lnk, full_path);
535 if (ret < 0) {
536 ret = -errno;
537 error("symlink %s -> %s failed: %s", path,
538 lnk, strerror(-ret));
541 out:
542 return ret;
545 static int process_rename(const char *from, const char *to, void *user)
547 int ret;
548 struct btrfs_receive *rctx = user;
549 char full_from[PATH_MAX];
550 char full_to[PATH_MAX];
552 ret = path_cat_out(full_from, rctx->full_subvol_path, from);
553 if (ret < 0) {
554 error("rename: source path invalid: %s", from);
555 goto out;
558 ret = path_cat_out(full_to, rctx->full_subvol_path, to);
559 if (ret < 0) {
560 error("rename: target path invalid: %s", to);
561 goto out;
564 if (g_verbose >= 2)
565 fprintf(stderr, "rename %s -> %s\n", from, to);
567 ret = rename(full_from, full_to);
568 if (ret < 0) {
569 ret = -errno;
570 error("rename %s -> %s failed: %s", from,
571 to, strerror(-ret));
574 out:
575 return ret;
578 static int process_link(const char *path, const char *lnk, void *user)
580 int ret;
581 struct btrfs_receive *rctx = user;
582 char full_path[PATH_MAX];
583 char full_link_path[PATH_MAX];
585 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
586 if (ret < 0) {
587 error("link: source path invalid: %s", full_path);
588 goto out;
591 ret = path_cat_out(full_link_path, rctx->full_subvol_path, lnk);
592 if (ret < 0) {
593 error("link: target path invalid: %s", full_link_path);
594 goto out;
597 if (g_verbose >= 2)
598 fprintf(stderr, "link %s -> %s\n", path, lnk);
600 ret = link(full_link_path, full_path);
601 if (ret < 0) {
602 ret = -errno;
603 error("link %s -> %s failed: %s", path, lnk, strerror(-ret));
606 out:
607 return ret;
611 static int process_unlink(const char *path, void *user)
613 int ret;
614 struct btrfs_receive *rctx = user;
615 char full_path[PATH_MAX];
617 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
618 if (ret < 0) {
619 error("unlink: path invalid: %s", path);
620 goto out;
623 if (g_verbose >= 2)
624 fprintf(stderr, "unlink %s\n", path);
626 ret = unlink(full_path);
627 if (ret < 0) {
628 ret = -errno;
629 error("unlink %s failed. %s", path, strerror(-ret));
632 out:
633 return ret;
636 static int process_rmdir(const char *path, void *user)
638 int ret;
639 struct btrfs_receive *rctx = user;
640 char full_path[PATH_MAX];
642 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
643 if (ret < 0) {
644 error("rmdir: path invalid: %s", path);
645 goto out;
648 if (g_verbose >= 2)
649 fprintf(stderr, "rmdir %s\n", path);
651 ret = rmdir(full_path);
652 if (ret < 0) {
653 ret = -errno;
654 error("rmdir %s failed: %s", path, strerror(-ret));
657 out:
658 return ret;
661 static int open_inode_for_write(struct btrfs_receive *rctx, const char *path)
663 int ret = 0;
665 if (rctx->write_fd != -1) {
666 if (strcmp(rctx->write_path, path) == 0)
667 goto out;
668 close(rctx->write_fd);
669 rctx->write_fd = -1;
672 rctx->write_fd = open(path, O_RDWR);
673 if (rctx->write_fd < 0) {
674 ret = -errno;
675 error("cannot open %s: %s", path, strerror(-ret));
676 goto out;
678 strncpy_null(rctx->write_path, path);
680 out:
681 return ret;
684 static void close_inode_for_write(struct btrfs_receive *rctx)
686 if(rctx->write_fd == -1)
687 return;
689 close(rctx->write_fd);
690 rctx->write_fd = -1;
691 rctx->write_path[0] = 0;
694 static int process_write(const char *path, const void *data, u64 offset,
695 u64 len, void *user)
697 int ret = 0;
698 struct btrfs_receive *rctx = user;
699 char full_path[PATH_MAX];
700 u64 pos = 0;
701 int w;
703 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
704 if (ret < 0) {
705 error("write: path invalid: %s", path);
706 goto out;
709 ret = open_inode_for_write(rctx, full_path);
710 if (ret < 0)
711 goto out;
713 while (pos < len) {
714 w = pwrite(rctx->write_fd, (char*)data + pos, len - pos,
715 offset + pos);
716 if (w < 0) {
717 ret = -errno;
718 error("writing to %s failed: %s",
719 path, strerror(-ret));
720 goto out;
722 pos += w;
725 out:
726 return ret;
729 static int process_clone(const char *path, u64 offset, u64 len,
730 const u8 *clone_uuid, u64 clone_ctransid,
731 const char *clone_path, u64 clone_offset,
732 void *user)
734 int ret;
735 struct btrfs_receive *rctx = user;
736 struct btrfs_ioctl_clone_range_args clone_args;
737 struct subvol_info *si = NULL;
738 char full_path[PATH_MAX];
739 char *subvol_path = NULL;
740 char full_clone_path[PATH_MAX];
741 int clone_fd = -1;
743 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
744 if (ret < 0) {
745 error("clone: source path invalid: %s", path);
746 goto out;
749 ret = open_inode_for_write(rctx, full_path);
750 if (ret < 0)
751 goto out;
753 si = subvol_uuid_search(&rctx->sus, 0, clone_uuid, clone_ctransid,
754 NULL,
755 subvol_search_by_received_uuid);
756 if (IS_ERR_OR_NULL(si)) {
757 if (memcmp(clone_uuid, rctx->cur_subvol.received_uuid,
758 BTRFS_UUID_SIZE) == 0) {
759 /* TODO check generation of extent */
760 subvol_path = strdup(rctx->cur_subvol_path);
761 } else {
762 if (!si)
763 ret = -ENOENT;
764 else
765 ret = PTR_ERR(si);
766 error("clone: did not find source subvol");
767 goto out;
769 } else {
770 /*if (rs_args.ctransid > rs_args.rtransid) {
771 if (!r->force) {
772 ret = -EINVAL;
773 fprintf(stderr, "ERROR: subvolume %s was "
774 "modified after it was "
775 "received.\n",
776 r->subvol_parent_name);
777 goto out;
778 } else {
779 fprintf(stderr, "WARNING: subvolume %s was "
780 "modified after it was "
781 "received.\n",
782 r->subvol_parent_name);
785 subvol_path = strdup(si->path);
788 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
789 if (ret < 0) {
790 error("clone: target path invalid: %s", clone_path);
791 goto out;
794 clone_fd = openat(rctx->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
795 if (clone_fd < 0) {
796 ret = -errno;
797 error("cannot open %s: %s", full_clone_path, strerror(-ret));
798 goto out;
801 clone_args.src_fd = clone_fd;
802 clone_args.src_offset = clone_offset;
803 clone_args.src_length = len;
804 clone_args.dest_offset = offset;
805 ret = ioctl(rctx->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
806 if (ret < 0) {
807 ret = -errno;
808 error("failed to clone extents to %s\n%s",
809 path, strerror(-ret));
810 goto out;
813 out:
814 if (si) {
815 free(si->path);
816 free(si);
818 free(subvol_path);
819 if (clone_fd != -1)
820 close(clone_fd);
821 return ret;
825 static int process_set_xattr(const char *path, const char *name,
826 const void *data, int len, void *user)
828 int ret = 0;
829 struct btrfs_receive *rctx = user;
830 char full_path[PATH_MAX];
832 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
833 if (ret < 0) {
834 error("set_xattr: path invalid: %s", path);
835 goto out;
838 if (strcmp("security.capability", name) == 0) {
839 if (g_verbose >= 3)
840 fprintf(stderr, "set_xattr: cache capabilities\n");
841 if (rctx->cached_capabilities_len)
842 warning("capabilities set multiple times per file: %s",
843 full_path);
844 if (len > sizeof(rctx->cached_capabilities)) {
845 error("capabilities encoded to %d bytes, buffer too small",
846 len);
847 ret = -E2BIG;
848 goto out;
850 rctx->cached_capabilities_len = len;
851 memcpy(rctx->cached_capabilities, data, len);
854 if (g_verbose >= 2) {
855 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
856 "data=%.*s\n", path, name, len,
857 len, (char*)data);
860 ret = lsetxattr(full_path, name, data, len, 0);
861 if (ret < 0) {
862 ret = -errno;
863 error("lsetxattr %s %s=%.*s failed: %s",
864 path, name, len, (char*)data, strerror(-ret));
865 goto out;
868 out:
869 return ret;
872 static int process_remove_xattr(const char *path, const char *name, void *user)
874 int ret = 0;
875 struct btrfs_receive *rctx = user;
876 char full_path[PATH_MAX];
878 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
879 if (ret < 0) {
880 error("remove_xattr: path invalid: %s", path);
881 goto out;
884 if (g_verbose >= 2) {
885 fprintf(stderr, "remove_xattr %s - name=%s\n",
886 path, name);
889 ret = lremovexattr(full_path, name);
890 if (ret < 0) {
891 ret = -errno;
892 error("lremovexattr %s %s failed: %s",
893 path, name, strerror(-ret));
894 goto out;
897 out:
898 return ret;
901 static int process_truncate(const char *path, u64 size, void *user)
903 int ret = 0;
904 struct btrfs_receive *rctx = user;
905 char full_path[PATH_MAX];
907 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
908 if (ret < 0) {
909 error("truncate: path invalid: %s", path);
910 goto out;
913 if (g_verbose >= 2)
914 fprintf(stderr, "truncate %s size=%llu\n", path, size);
916 ret = truncate(full_path, size);
917 if (ret < 0) {
918 ret = -errno;
919 error("truncate %s failed: %s", path, strerror(-ret));
920 goto out;
923 out:
924 return ret;
927 static int process_chmod(const char *path, u64 mode, void *user)
929 int ret = 0;
930 struct btrfs_receive *rctx = user;
931 char full_path[PATH_MAX];
933 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
934 if (ret < 0) {
935 error("chmod: path invalid: %s", path);
936 goto out;
939 if (g_verbose >= 2)
940 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
942 ret = chmod(full_path, mode);
943 if (ret < 0) {
944 ret = -errno;
945 error("chmod %s failed: %s", path, strerror(-ret));
946 goto out;
949 out:
950 return ret;
953 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
955 int ret = 0;
956 struct btrfs_receive *rctx = user;
957 char full_path[PATH_MAX];
959 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
960 if (ret < 0) {
961 error("chown: path invalid: %s", path);
962 goto out;
965 if (g_verbose >= 2)
966 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
967 uid, gid);
969 ret = lchown(full_path, uid, gid);
970 if (ret < 0) {
971 ret = -errno;
972 error("chown %s failed: %s", path, strerror(-ret));
973 goto out;
976 if (rctx->cached_capabilities_len) {
977 if (g_verbose >= 2)
978 fprintf(stderr, "chown: restore capabilities\n");
979 ret = lsetxattr(full_path, "security.capability",
980 rctx->cached_capabilities,
981 rctx->cached_capabilities_len, 0);
982 memset(rctx->cached_capabilities, 0,
983 sizeof(rctx->cached_capabilities));
984 rctx->cached_capabilities_len = 0;
985 if (ret < 0) {
986 ret = -errno;
987 error("restoring capabilities %s: %s",
988 path, strerror(-ret));
989 goto out;
993 out:
994 return ret;
997 static int process_utimes(const char *path, struct timespec *at,
998 struct timespec *mt, struct timespec *ct,
999 void *user)
1001 int ret = 0;
1002 struct btrfs_receive *rctx = user;
1003 char full_path[PATH_MAX];
1004 struct timespec tv[2];
1006 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
1007 if (ret < 0) {
1008 error("utimes: path invalid: %s", path);
1009 goto out;
1012 if (g_verbose >= 2)
1013 fprintf(stderr, "utimes %s\n", path);
1015 tv[0] = *at;
1016 tv[1] = *mt;
1017 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1018 if (ret < 0) {
1019 ret = -errno;
1020 error("utimes %s failed: %s",
1021 path, strerror(-ret));
1022 goto out;
1025 out:
1026 return ret;
1029 static int process_update_extent(const char *path, u64 offset, u64 len,
1030 void *user)
1032 if (g_verbose >= 2)
1033 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1034 path, (unsigned long long)offset,
1035 (unsigned long long)len);
1038 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1041 return 0;
1044 static struct btrfs_send_ops send_ops = {
1045 .subvol = process_subvol,
1046 .snapshot = process_snapshot,
1047 .mkfile = process_mkfile,
1048 .mkdir = process_mkdir,
1049 .mknod = process_mknod,
1050 .mkfifo = process_mkfifo,
1051 .mksock = process_mksock,
1052 .symlink = process_symlink,
1053 .rename = process_rename,
1054 .link = process_link,
1055 .unlink = process_unlink,
1056 .rmdir = process_rmdir,
1057 .write = process_write,
1058 .clone = process_clone,
1059 .set_xattr = process_set_xattr,
1060 .remove_xattr = process_remove_xattr,
1061 .truncate = process_truncate,
1062 .chmod = process_chmod,
1063 .chown = process_chown,
1064 .utimes = process_utimes,
1065 .update_extent = process_update_extent,
1068 static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
1069 char *realmnt, int r_fd, u64 max_errors)
1071 u64 subvol_id;
1072 int ret;
1073 char *dest_dir_full_path;
1074 char root_subvol_path[PATH_MAX];
1075 int end = 0;
1076 int count;
1078 dest_dir_full_path = realpath(tomnt, NULL);
1079 if (!dest_dir_full_path) {
1080 ret = -errno;
1081 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1082 goto out;
1084 rctx->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1085 if (rctx->dest_dir_fd < 0) {
1086 ret = -errno;
1087 error("cannot open destination directory %s: %s",
1088 dest_dir_full_path, strerror(-ret));
1089 goto out;
1092 if (realmnt[0]) {
1093 rctx->root_path = realmnt;
1094 } else {
1095 ret = find_mount_root(dest_dir_full_path, &rctx->root_path);
1096 if (ret < 0) {
1097 error("failed to determine mount point for %s: %s",
1098 dest_dir_full_path, strerror(-ret));
1099 ret = -EINVAL;
1100 goto out;
1102 if (ret > 0) {
1103 error("%s doesn't belong to btrfs mount point",
1104 dest_dir_full_path);
1105 ret = -EINVAL;
1106 goto out;
1109 rctx->mnt_fd = open(rctx->root_path, O_RDONLY | O_NOATIME);
1110 if (rctx->mnt_fd < 0) {
1111 ret = -errno;
1112 error("cannot open %s: %s", rctx->root_path, strerror(-ret));
1113 goto out;
1117 * If we use -m or a default subvol we want to resolve the path to the
1118 * subvolume we're sitting in so that we can adjust the paths of any
1119 * subvols we want to receive in.
1121 ret = btrfs_list_get_path_rootid(rctx->mnt_fd, &subvol_id);
1122 if (ret)
1123 goto out;
1125 root_subvol_path[0] = 0;
1126 ret = btrfs_subvolid_resolve(rctx->mnt_fd, root_subvol_path,
1127 PATH_MAX, subvol_id);
1128 if (ret) {
1129 error("cannot resolve our subvol path");
1130 goto out;
1134 * Ok we're inside of a subvol off of the root subvol, we need to
1135 * actually set full_root_path.
1137 if (*root_subvol_path)
1138 rctx->full_root_path = root_subvol_path;
1140 if (rctx->dest_dir_chroot) {
1141 if (chroot(dest_dir_full_path)) {
1142 ret = -errno;
1143 error("failed to chroot to %s: %s",
1144 dest_dir_full_path, strerror(-ret));
1145 goto out;
1147 if (chdir("/")) {
1148 ret = -errno;
1149 error("failed to chdir to / after chroot: %s",
1150 strerror(-ret));
1151 goto out;
1153 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1154 rctx->root_path = strdup("/");
1155 rctx->dest_dir_path = rctx->root_path;
1156 } else {
1158 * find_mount_root returns a root_path that is a subpath of
1159 * dest_dir_full_path. Now get the other part of root_path,
1160 * which is the destination dir relative to root_path.
1162 rctx->dest_dir_path = dest_dir_full_path + strlen(rctx->root_path);
1163 while (rctx->dest_dir_path[0] == '/')
1164 rctx->dest_dir_path++;
1167 ret = subvol_uuid_search_init(rctx->mnt_fd, &rctx->sus);
1168 if (ret < 0)
1169 goto out;
1171 count = 0;
1172 while (!end) {
1173 if (rctx->cached_capabilities_len) {
1174 if (g_verbose >= 3)
1175 fprintf(stderr, "clear cached capabilities\n");
1176 memset(rctx->cached_capabilities, 0,
1177 sizeof(rctx->cached_capabilities));
1178 rctx->cached_capabilities_len = 0;
1181 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops,
1182 rctx,
1183 rctx->honor_end_cmd,
1184 max_errors);
1185 if (ret < 0)
1186 goto out;
1187 /* Empty stream is invalid */
1188 if (ret && count == 0) {
1189 error("empty stream is not considered valid");
1190 ret = -EINVAL;
1191 goto out;
1193 count++;
1194 if (ret)
1195 end = 1;
1197 close_inode_for_write(rctx);
1198 ret = finish_subvol(rctx);
1199 if (ret < 0)
1200 goto out;
1202 ret = 0;
1204 out:
1205 if (rctx->write_fd != -1) {
1206 close(rctx->write_fd);
1207 rctx->write_fd = -1;
1210 if (rctx->root_path != realmnt)
1211 free(rctx->root_path);
1212 rctx->root_path = NULL;
1213 rctx->dest_dir_path = NULL;
1214 free(dest_dir_full_path);
1215 subvol_uuid_search_finit(&rctx->sus);
1216 if (rctx->mnt_fd != -1) {
1217 close(rctx->mnt_fd);
1218 rctx->mnt_fd = -1;
1220 if (rctx->dest_dir_fd != -1) {
1221 close(rctx->dest_dir_fd);
1222 rctx->dest_dir_fd = -1;
1225 return ret;
1228 int cmd_receive(int argc, char **argv)
1230 char *tomnt = NULL;
1231 char fromfile[PATH_MAX];
1232 char realmnt[PATH_MAX];
1233 struct btrfs_receive rctx;
1234 int receive_fd = fileno(stdin);
1235 u64 max_errors = 1;
1236 int dump = 0;
1237 int ret = 0;
1239 memset(&rctx, 0, sizeof(rctx));
1240 rctx.mnt_fd = -1;
1241 rctx.write_fd = -1;
1242 rctx.dest_dir_fd = -1;
1243 rctx.dest_dir_chroot = 0;
1244 realmnt[0] = 0;
1245 fromfile[0] = 0;
1247 while (1) {
1248 int c;
1249 enum { GETOPT_VAL_DUMP = 257 };
1250 static const struct option long_opts[] = {
1251 { "max-errors", required_argument, NULL, 'E' },
1252 { "chroot", no_argument, NULL, 'C' },
1253 { "dump", no_argument, NULL, GETOPT_VAL_DUMP },
1254 { NULL, 0, NULL, 0 }
1257 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1258 if (c < 0)
1259 break;
1261 switch (c) {
1262 case 'v':
1263 g_verbose++;
1264 break;
1265 case 'f':
1266 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1267 error("input file path too long (%zu)",
1268 strlen(optarg));
1269 ret = 1;
1270 goto out;
1272 break;
1273 case 'e':
1274 rctx.honor_end_cmd = 1;
1275 break;
1276 case 'C':
1277 rctx.dest_dir_chroot = 1;
1278 break;
1279 case 'E':
1280 max_errors = arg_strtou64(optarg);
1281 break;
1282 case 'm':
1283 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1284 error("mount point path too long (%zu)",
1285 strlen(optarg));
1286 ret = 1;
1287 goto out;
1289 break;
1290 case GETOPT_VAL_DUMP:
1291 dump = 1;
1292 break;
1293 case '?':
1294 default:
1295 error("receive args invalid");
1296 return 1;
1300 if (dump && check_argc_exact(argc - optind, 0))
1301 usage(cmd_receive_usage);
1302 if (!dump && check_argc_exact(argc - optind, 1))
1303 usage(cmd_receive_usage);
1305 tomnt = argv[optind];
1307 if (fromfile[0]) {
1308 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1309 if (receive_fd < 0) {
1310 error("cannot open %s: %s", fromfile, strerror(errno));
1311 goto out;
1315 if (dump) {
1316 struct btrfs_dump_send_args dump_args;
1318 dump_args.root_path[0] = '.';
1319 dump_args.root_path[1] = '\0';
1320 dump_args.full_subvol_path[0] = '.';
1321 dump_args.full_subvol_path[1] = '\0';
1322 ret = btrfs_read_and_process_send_stream(receive_fd,
1323 &btrfs_print_send_ops, &dump_args, 0, 0);
1324 if (ret < 0)
1325 error("failed to dump the send stream: %s",
1326 strerror(-ret));
1327 } else {
1328 ret = do_receive(&rctx, tomnt, realmnt, receive_fd, max_errors);
1331 if (receive_fd != fileno(stdin))
1332 close(receive_fd);
1333 out:
1335 return !!ret;
1338 const char * const cmd_receive_usage[] = {
1339 "btrfs receive [options] <mount>\n"
1340 "btrfs receive --dump [options]",
1341 "Receive subvolumes from a stream",
1342 "Receives one or more subvolumes that were previously",
1343 "sent with btrfs send. The received subvolumes are stored",
1344 "into MOUNT.",
1345 "The receive will fail in case the receiving subvolume",
1346 "already exists. It will also fail in case a previously",
1347 "received subvolume has been changed after it was received.",
1348 "After receiving a subvolume, it is immediately set to",
1349 "read-only.",
1351 "-v increase verbosity about performed actions",
1352 "-f FILE read the stream from FILE instead of stdin",
1353 "-e terminate after receiving an <end cmd> marker in the stream.",
1354 " Without this option the receiver side terminates only in case",
1355 " of an error on end of file.",
1356 "-C|--chroot confine the process to <mount> using chroot",
1357 "-E|--max-errors NERR",
1358 " terminate as soon as NERR errors occur while",
1359 " stream processing commands from the stream.",
1360 " Default value is 1. A value of 0 means no limit.",
1361 "-m ROOTMOUNT the root mount point of the destination filesystem.",
1362 " If /proc is not accessible, use this to tell us where",
1363 " this file system is mounted.",
1364 "--dump dump stream metadata, one line per operation,",
1365 " does not require the MOUNT parameter",
1366 NULL