btrfs-progs: remove stale dir-test
[btrfs-progs-unstable/devel.git] / cmds-receive.c
blob34d51ef3f30195b54bbfced71490c5430c834384
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 (strstr(parent_subvol->path, rctx->full_root_path) != parent_subvol->path ||
319 (sub_len > root_len && parent_subvol->path[root_len] != '/')) {
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);
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);
796 } else {
797 error("clone: source subvol path %s unreachable from %s",
798 si->path, rctx->full_root_path);
799 goto out;
801 } else {
802 subvol_path = strdup(si->path);
806 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
807 if (ret < 0) {
808 error("clone: target path invalid: %s", clone_path);
809 goto out;
812 clone_fd = openat(rctx->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
813 if (clone_fd < 0) {
814 ret = -errno;
815 error("cannot open %s: %s", full_clone_path, strerror(-ret));
816 goto out;
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);
824 if (ret < 0) {
825 ret = -errno;
826 error("failed to clone extents to %s\n%s",
827 path, strerror(-ret));
828 goto out;
831 out:
832 if (si) {
833 free(si->path);
834 free(si);
836 free(subvol_path);
837 if (clone_fd != -1)
838 close(clone_fd);
839 return ret;
843 static int process_set_xattr(const char *path, const char *name,
844 const void *data, int len, void *user)
846 int ret = 0;
847 struct btrfs_receive *rctx = user;
848 char full_path[PATH_MAX];
850 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
851 if (ret < 0) {
852 error("set_xattr: path invalid: %s", path);
853 goto out;
856 if (strcmp("security.capability", name) == 0) {
857 if (g_verbose >= 3)
858 fprintf(stderr, "set_xattr: cache capabilities\n");
859 if (rctx->cached_capabilities_len)
860 warning("capabilities set multiple times per file: %s",
861 full_path);
862 if (len > sizeof(rctx->cached_capabilities)) {
863 error("capabilities encoded to %d bytes, buffer too small",
864 len);
865 ret = -E2BIG;
866 goto out;
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,
875 len, (char*)data);
878 ret = lsetxattr(full_path, name, data, len, 0);
879 if (ret < 0) {
880 ret = -errno;
881 error("lsetxattr %s %s=%.*s failed: %s",
882 path, name, len, (char*)data, strerror(-ret));
883 goto out;
886 out:
887 return ret;
890 static int process_remove_xattr(const char *path, const char *name, void *user)
892 int ret = 0;
893 struct btrfs_receive *rctx = user;
894 char full_path[PATH_MAX];
896 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
897 if (ret < 0) {
898 error("remove_xattr: path invalid: %s", path);
899 goto out;
902 if (g_verbose >= 2) {
903 fprintf(stderr, "remove_xattr %s - name=%s\n",
904 path, name);
907 ret = lremovexattr(full_path, name);
908 if (ret < 0) {
909 ret = -errno;
910 error("lremovexattr %s %s failed: %s",
911 path, name, strerror(-ret));
912 goto out;
915 out:
916 return ret;
919 static int process_truncate(const char *path, u64 size, void *user)
921 int ret = 0;
922 struct btrfs_receive *rctx = user;
923 char full_path[PATH_MAX];
925 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
926 if (ret < 0) {
927 error("truncate: path invalid: %s", path);
928 goto out;
931 if (g_verbose >= 2)
932 fprintf(stderr, "truncate %s size=%llu\n", path, size);
934 ret = truncate(full_path, size);
935 if (ret < 0) {
936 ret = -errno;
937 error("truncate %s failed: %s", path, strerror(-ret));
938 goto out;
941 out:
942 return ret;
945 static int process_chmod(const char *path, u64 mode, void *user)
947 int ret = 0;
948 struct btrfs_receive *rctx = user;
949 char full_path[PATH_MAX];
951 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
952 if (ret < 0) {
953 error("chmod: path invalid: %s", path);
954 goto out;
957 if (g_verbose >= 2)
958 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
960 ret = chmod(full_path, mode);
961 if (ret < 0) {
962 ret = -errno;
963 error("chmod %s failed: %s", path, strerror(-ret));
964 goto out;
967 out:
968 return ret;
971 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
973 int ret = 0;
974 struct btrfs_receive *rctx = user;
975 char full_path[PATH_MAX];
977 ret = path_cat_out(full_path, rctx->full_subvol_path, path);
978 if (ret < 0) {
979 error("chown: path invalid: %s", path);
980 goto out;
983 if (g_verbose >= 2)
984 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
985 uid, gid);
987 ret = lchown(full_path, uid, gid);
988 if (ret < 0) {
989 ret = -errno;
990 error("chown %s failed: %s", path, strerror(-ret));
991 goto out;
994 if (rctx->cached_capabilities_len) {
995 if (g_verbose >= 2)
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;
1003 if (ret < 0) {
1004 ret = -errno;
1005 error("restoring capabilities %s: %s",
1006 path, strerror(-ret));
1007 goto out;
1011 out:
1012 return ret;
1015 static int process_utimes(const char *path, struct timespec *at,
1016 struct timespec *mt, struct timespec *ct,
1017 void *user)
1019 int ret = 0;
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);
1025 if (ret < 0) {
1026 error("utimes: path invalid: %s", path);
1027 goto out;
1030 if (g_verbose >= 2)
1031 fprintf(stderr, "utimes %s\n", path);
1033 tv[0] = *at;
1034 tv[1] = *mt;
1035 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1036 if (ret < 0) {
1037 ret = -errno;
1038 error("utimes %s failed: %s",
1039 path, strerror(-ret));
1040 goto out;
1043 out:
1044 return ret;
1047 static int process_update_extent(const char *path, u64 offset, u64 len,
1048 void *user)
1050 if (g_verbose >= 2)
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.
1059 return 0;
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)
1089 u64 subvol_id;
1090 int ret;
1091 char *dest_dir_full_path;
1092 char root_subvol_path[PATH_MAX];
1093 int end = 0;
1094 int iterations = 0;
1096 dest_dir_full_path = realpath(tomnt, NULL);
1097 if (!dest_dir_full_path) {
1098 ret = -errno;
1099 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1100 goto out;
1102 rctx->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1103 if (rctx->dest_dir_fd < 0) {
1104 ret = -errno;
1105 error("cannot open destination directory %s: %s",
1106 dest_dir_full_path, strerror(-ret));
1107 goto out;
1110 if (realmnt[0]) {
1111 rctx->root_path = realmnt;
1112 } else {
1113 ret = find_mount_root(dest_dir_full_path, &rctx->root_path);
1114 if (ret < 0) {
1115 error("failed to determine mount point for %s: %s",
1116 dest_dir_full_path, strerror(-ret));
1117 ret = -EINVAL;
1118 goto out;
1120 if (ret > 0) {
1121 error("%s doesn't belong to btrfs mount point",
1122 dest_dir_full_path);
1123 ret = -EINVAL;
1124 goto out;
1127 rctx->mnt_fd = open(rctx->root_path, O_RDONLY | O_NOATIME);
1128 if (rctx->mnt_fd < 0) {
1129 ret = -errno;
1130 error("cannot open %s: %s", rctx->root_path, strerror(-ret));
1131 goto out;
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);
1140 if (ret)
1141 goto out;
1143 root_subvol_path[0] = 0;
1144 ret = btrfs_subvolid_resolve(rctx->mnt_fd, root_subvol_path,
1145 PATH_MAX, subvol_id);
1146 if (ret) {
1147 error("cannot resolve our subvol path");
1148 goto out;
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)) {
1160 ret = -errno;
1161 error("failed to chroot to %s: %s",
1162 dest_dir_full_path, strerror(-ret));
1163 goto out;
1165 if (chdir("/")) {
1166 ret = -errno;
1167 error("failed to chdir to / after chroot: %s",
1168 strerror(-ret));
1169 goto out;
1171 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1172 rctx->root_path = strdup("/");
1173 rctx->dest_dir_path = rctx->root_path;
1174 } else {
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);
1186 if (ret < 0)
1187 goto out;
1189 while (!end) {
1190 if (rctx->cached_capabilities_len) {
1191 if (g_verbose >= 3)
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,
1199 rctx,
1200 rctx->honor_end_cmd,
1201 max_errors);
1202 if (ret < 0) {
1203 if (ret != -ENODATA)
1204 goto out;
1206 /* Empty stream is invalid */
1207 if (iterations == 0) {
1208 error("empty stream is not considered valid");
1209 ret = -EINVAL;
1210 goto out;
1213 ret = 1;
1215 if (ret > 0)
1216 end = 1;
1218 close_inode_for_write(rctx);
1219 ret = finish_subvol(rctx);
1220 if (ret < 0)
1221 goto out;
1223 iterations++;
1225 ret = 0;
1227 out:
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);
1241 rctx->mnt_fd = -1;
1243 if (rctx->dest_dir_fd != -1) {
1244 close(rctx->dest_dir_fd);
1245 rctx->dest_dir_fd = -1;
1248 return ret;
1251 int cmd_receive(int argc, char **argv)
1253 char *tomnt = NULL;
1254 char fromfile[PATH_MAX];
1255 char realmnt[PATH_MAX];
1256 struct btrfs_receive rctx;
1257 int receive_fd = fileno(stdin);
1258 u64 max_errors = 1;
1259 int dump = 0;
1260 int ret = 0;
1262 memset(&rctx, 0, sizeof(rctx));
1263 rctx.mnt_fd = -1;
1264 rctx.write_fd = -1;
1265 rctx.dest_dir_fd = -1;
1266 rctx.dest_dir_chroot = 0;
1267 realmnt[0] = 0;
1268 fromfile[0] = 0;
1270 optind = 0;
1271 while (1) {
1272 int c;
1273 enum { GETOPT_VAL_DUMP = 257 };
1274 static const struct option long_opts[] = {
1275 { "max-errors", required_argument, NULL, 'E' },
1276 { "chroot", no_argument, NULL, 'C' },
1277 { "dump", no_argument, NULL, GETOPT_VAL_DUMP },
1278 { NULL, 0, NULL, 0 }
1281 c = getopt_long(argc, argv, "Cevf:m:E:", long_opts, NULL);
1282 if (c < 0)
1283 break;
1285 switch (c) {
1286 case 'v':
1287 g_verbose++;
1288 break;
1289 case 'f':
1290 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1291 error("input file path too long (%zu)",
1292 strlen(optarg));
1293 ret = 1;
1294 goto out;
1296 break;
1297 case 'e':
1298 rctx.honor_end_cmd = 1;
1299 break;
1300 case 'C':
1301 rctx.dest_dir_chroot = 1;
1302 break;
1303 case 'E':
1304 max_errors = arg_strtou64(optarg);
1305 break;
1306 case 'm':
1307 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1308 error("mount point path too long (%zu)",
1309 strlen(optarg));
1310 ret = 1;
1311 goto out;
1313 break;
1314 case GETOPT_VAL_DUMP:
1315 dump = 1;
1316 break;
1317 case '?':
1318 default:
1319 error("receive args invalid");
1320 return 1;
1324 if (dump && check_argc_exact(argc - optind, 0))
1325 usage(cmd_receive_usage);
1326 if (!dump && check_argc_exact(argc - optind, 1))
1327 usage(cmd_receive_usage);
1329 tomnt = argv[optind];
1331 if (fromfile[0]) {
1332 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1333 if (receive_fd < 0) {
1334 error("cannot open %s: %m", fromfile);
1335 goto out;
1339 if (dump) {
1340 struct btrfs_dump_send_args dump_args;
1342 dump_args.root_path[0] = '.';
1343 dump_args.root_path[1] = '\0';
1344 dump_args.full_subvol_path[0] = '.';
1345 dump_args.full_subvol_path[1] = '\0';
1346 ret = btrfs_read_and_process_send_stream(receive_fd,
1347 &btrfs_print_send_ops, &dump_args, 0, 0);
1348 if (ret < 0)
1349 error("failed to dump the send stream: %s",
1350 strerror(-ret));
1351 } else {
1352 ret = do_receive(&rctx, tomnt, realmnt, receive_fd, max_errors);
1355 if (receive_fd != fileno(stdin))
1356 close(receive_fd);
1357 out:
1359 return !!ret;
1362 const char * const cmd_receive_usage[] = {
1363 "btrfs receive [options] <mount>\n"
1364 "btrfs receive --dump [options]",
1365 "Receive subvolumes from a stream",
1366 "Receives one or more subvolumes that were previously",
1367 "sent with btrfs send. The received subvolumes are stored",
1368 "into MOUNT.",
1369 "The receive will fail in case the receiving subvolume",
1370 "already exists. It will also fail in case a previously",
1371 "received subvolume has been changed after it was received.",
1372 "After receiving a subvolume, it is immediately set to",
1373 "read-only.",
1375 "-v increase verbosity about performed actions",
1376 "-f FILE read the stream from FILE instead of stdin",
1377 "-e terminate after receiving an <end cmd> marker in the stream.",
1378 " Without this option the receiver side terminates only in case",
1379 " of an error on end of file.",
1380 "-C|--chroot confine the process to <mount> using chroot",
1381 "-E|--max-errors NERR",
1382 " terminate as soon as NERR errors occur while",
1383 " stream processing commands from the stream.",
1384 " Default value is 1. A value of 0 means no limit.",
1385 "-m ROOTMOUNT the root mount point of the destination filesystem.",
1386 " If /proc is not accessible, use this to tell us where",
1387 " this file system is mounted.",
1388 "--dump dump stream metadata, one line per operation,",
1389 " does not require the MOUNT parameter",
1390 NULL