Btrfs progs v4.5-rc1
[btrfs-progs-unstable/devel.git] / cmds-receive.c
blobcbb16421b14963e9edd98f3c27ffa1d6214bb969
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"
53 static int g_verbose = 0;
55 struct btrfs_receive
57 int mnt_fd;
58 int dest_dir_fd;
60 int write_fd;
61 char write_path[PATH_MAX];
63 char *root_path;
64 char *dest_dir_path; /* relative to root_path */
65 char full_subvol_path[PATH_MAX];
66 char *full_root_path;
67 int dest_dir_chroot;
69 struct subvol_info cur_subvol;
71 * Substitute for cur_subvol::path which is a pointer and we cannot
72 * change it to an array as it's a public API.
74 char cur_subvol_path[PATH_MAX];
76 struct subvol_uuid_search sus;
78 int honor_end_cmd;
81 * Buffer to store capabilities from security.capabilities xattr,
82 * usually 20 bytes, but make same room for potentially larger
83 * encodings. Must be set only once per file, denoted by length > 0.
85 char cached_capabilities[64];
86 int cached_capabilities_len;
89 static int finish_subvol(struct btrfs_receive *r)
91 int ret;
92 int subvol_fd = -1;
93 struct btrfs_ioctl_received_subvol_args rs_args;
94 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
95 u64 flags;
97 if (r->cur_subvol_path[0] == 0)
98 return 0;
100 subvol_fd = openat(r->mnt_fd, r->cur_subvol_path,
101 O_RDONLY | O_NOATIME);
102 if (subvol_fd < 0) {
103 ret = -errno;
104 error("cannot open %s: %s\n",
105 r->cur_subvol_path, strerror(-ret));
106 goto out;
109 memset(&rs_args, 0, sizeof(rs_args));
110 memcpy(rs_args.uuid, r->cur_subvol.received_uuid, BTRFS_UUID_SIZE);
111 rs_args.stransid = r->cur_subvol.stransid;
113 if (g_verbose >= 1) {
114 uuid_unparse((u8*)rs_args.uuid, uuid_str);
115 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
116 "stransid=%llu\n", uuid_str, rs_args.stransid);
119 ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
120 if (ret < 0) {
121 ret = -errno;
122 error("ioctl BTRFS_IOC_SET_RECEIVED_SUBVOL failed: %s",
123 strerror(-ret));
124 goto out;
126 r->cur_subvol.rtransid = rs_args.rtransid;
128 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
129 if (ret < 0) {
130 ret = -errno;
131 error("ioctl BTRFS_IOC_SUBVOL_GETFLAGS failed: %s",
132 strerror(-ret));
133 goto out;
136 flags |= BTRFS_SUBVOL_RDONLY;
138 ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
139 if (ret < 0) {
140 ret = -errno;
141 error("failed to make subvolume read only: %s",
142 strerror(-ret));
143 goto out;
146 ret = 0;
148 out:
149 if (r->cur_subvol_path[0]) {
150 r->cur_subvol_path[0] = 0;
152 if (subvol_fd != -1)
153 close(subvol_fd);
154 return ret;
157 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
158 void *user)
160 int ret;
161 struct btrfs_receive *r = user;
162 struct btrfs_ioctl_vol_args args_v1;
163 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
165 ret = finish_subvol(r);
166 if (ret < 0)
167 goto out;
169 BUG_ON(r->cur_subvol.path);
170 BUG_ON(r->cur_subvol_path[0]);
172 if (*r->dest_dir_path == 0) {
173 strncpy_null(r->cur_subvol_path, path);
174 } else {
175 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
176 if (ret < 0) {
177 error("subvol: path invalid: %s\n", path);
178 goto out;
181 ret = path_cat3_out(r->full_subvol_path, r->root_path,
182 r->dest_dir_path, path);
183 if (ret < 0) {
184 error("subvol: path invalid: %s", path);
185 goto out;
188 fprintf(stderr, "At subvol %s\n", path);
190 memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
191 r->cur_subvol.stransid = ctransid;
193 if (g_verbose) {
194 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
195 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
196 path, uuid_str,
197 r->cur_subvol.stransid);
200 memset(&args_v1, 0, sizeof(args_v1));
201 strncpy_null(args_v1.name, path);
202 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
203 if (ret < 0) {
204 ret = -errno;
205 error("creating subvolume %s failed: %s", path, strerror(-ret));
206 goto out;
209 out:
210 return ret;
213 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
214 const u8 *parent_uuid, u64 parent_ctransid,
215 void *user)
217 int ret;
218 struct btrfs_receive *r = user;
219 char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
220 struct btrfs_ioctl_vol_args_v2 args_v2;
221 struct subvol_info *parent_subvol = NULL;
223 ret = finish_subvol(r);
224 if (ret < 0)
225 goto out;
227 BUG_ON(r->cur_subvol.path);
228 BUG_ON(r->cur_subvol_path[0]);
230 if (*r->dest_dir_path == 0) {
231 strncpy_null(r->cur_subvol_path, path);
232 } else {
233 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
234 if (ret < 0) {
235 error("snapshot: path invalid: %s", path);
236 goto out;
239 ret = path_cat3_out(r->full_subvol_path, r->root_path,
240 r->dest_dir_path, path);
241 if (ret < 0) {
242 error("snapshot: path invalid: %s", path);
243 goto out;
246 fprintf(stdout, "At snapshot %s\n", path);
248 memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
249 r->cur_subvol.stransid = ctransid;
251 if (g_verbose) {
252 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
253 fprintf(stderr, "receiving snapshot %s uuid=%s, "
254 "ctransid=%llu ", path, uuid_str,
255 r->cur_subvol.stransid);
256 uuid_unparse(parent_uuid, uuid_str);
257 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
258 uuid_str, parent_ctransid);
261 memset(&args_v2, 0, sizeof(args_v2));
262 strncpy_null(args_v2.name, path);
264 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
265 parent_ctransid, NULL, subvol_search_by_received_uuid);
266 if (!parent_subvol) {
267 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
268 parent_ctransid, NULL, subvol_search_by_uuid);
270 if (!parent_subvol) {
271 ret = -ENOENT;
272 error("cannot find parent subvolume");
273 goto out;
277 * The path is resolved from the root subvol, but we could be in some
278 * subvolume under the root subvolume, so try and adjust the path to be
279 * relative to our root path.
281 if (r->full_root_path) {
282 size_t root_len;
283 size_t sub_len;
285 root_len = strlen(r->full_root_path);
286 sub_len = strlen(parent_subvol->path);
288 /* First make sure the parent subvol is actually in our path */
289 if (sub_len < root_len ||
290 strstr(parent_subvol->path, r->full_root_path) == NULL) {
291 error(
292 "parent subvol is not reachable from inside the root subvol");
293 ret = -ENOENT;
294 goto out;
297 if (sub_len == root_len) {
298 parent_subvol->path[0] = '/';
299 parent_subvol->path[1] = '\0';
300 } else {
302 * root path is foo/bar
303 * subvol path is foo/bar/baz
305 * we need to have baz be the path, so we need to move
306 * the bit after foo/bar/, so path + root_len + 1, and
307 * move the part we care about, so sub_len - root_len -
308 * 1.
310 memmove(parent_subvol->path,
311 parent_subvol->path + root_len + 1,
312 sub_len - root_len - 1);
313 parent_subvol->path[sub_len - root_len - 1] = '\0';
316 /*if (rs_args.ctransid > rs_args.rtransid) {
317 if (!r->force) {
318 ret = -EINVAL;
319 fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
320 goto out;
321 } else {
322 fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
326 if (*parent_subvol->path == 0)
327 args_v2.fd = dup(r->mnt_fd);
328 else
329 args_v2.fd = openat(r->mnt_fd, parent_subvol->path,
330 O_RDONLY | O_NOATIME);
331 if (args_v2.fd < 0) {
332 ret = -errno;
333 if (errno != ENOENT)
334 error("cannot open %s: %s",
335 parent_subvol->path, strerror(-ret));
336 else
337 fprintf(stderr,
338 "It seems that you have changed your default "
339 "subvolume or you specify other subvolume to\n"
340 "mount btrfs, try to remount this btrfs filesystem "
341 "with fs tree, and run btrfs receive again!\n");
342 goto out;
345 ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
346 close(args_v2.fd);
347 if (ret < 0) {
348 ret = -errno;
349 error("creating snapshot %s -> %s failed: %s",
350 parent_subvol->path, path, strerror(-ret));
351 goto out;
354 out:
355 if (parent_subvol) {
356 free(parent_subvol->path);
357 free(parent_subvol);
359 return ret;
362 static int process_mkfile(const char *path, void *user)
364 int ret;
365 struct btrfs_receive *r = user;
366 char full_path[PATH_MAX];
368 ret = path_cat_out(full_path, r->full_subvol_path, path);
369 if (ret < 0) {
370 error("mkfile: path invalid: %s", path);
371 goto out;
374 if (g_verbose >= 2)
375 fprintf(stderr, "mkfile %s\n", path);
377 ret = creat(full_path, 0600);
378 if (ret < 0) {
379 ret = -errno;
380 error("mkfile %s failed: %s", path, strerror(-ret));
381 goto out;
383 close(ret);
384 ret = 0;
386 out:
387 return ret;
390 static int process_mkdir(const char *path, void *user)
392 int ret;
393 struct btrfs_receive *r = user;
394 char full_path[PATH_MAX];
396 ret = path_cat_out(full_path, r->full_subvol_path, path);
397 if (ret < 0) {
398 error("mkdir: path invalid: %s", path);
399 goto out;
402 if (g_verbose >= 2)
403 fprintf(stderr, "mkdir %s\n", path);
405 ret = mkdir(full_path, 0700);
406 if (ret < 0) {
407 ret = -errno;
408 error("mkdir %s failed: %s", path, strerror(-ret));
411 out:
412 return ret;
415 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
417 int ret;
418 struct btrfs_receive *r = user;
419 char full_path[PATH_MAX];
421 ret = path_cat_out(full_path, r->full_subvol_path, path);
422 if (ret < 0) {
423 error("mknod: path invalid: %s", path);
424 goto out;
427 if (g_verbose >= 2)
428 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
429 path, mode, dev);
431 ret = mknod(full_path, mode & S_IFMT, dev);
432 if (ret < 0) {
433 ret = -errno;
434 error("mknod %s failed: %s", path, strerror(-ret));
437 out:
438 return ret;
441 static int process_mkfifo(const char *path, void *user)
443 int ret;
444 struct btrfs_receive *r = user;
445 char full_path[PATH_MAX];
447 ret = path_cat_out(full_path, r->full_subvol_path, path);
448 if (ret < 0) {
449 error("mkfifo: path invalid: %s", path);
450 goto out;
453 if (g_verbose >= 2)
454 fprintf(stderr, "mkfifo %s\n", path);
456 ret = mkfifo(full_path, 0600);
457 if (ret < 0) {
458 ret = -errno;
459 error("mkfifo %s failed: %s", path, strerror(-ret));
462 out:
463 return ret;
466 static int process_mksock(const char *path, void *user)
468 int ret;
469 struct btrfs_receive *r = user;
470 char full_path[PATH_MAX];
472 ret = path_cat_out(full_path, r->full_subvol_path, path);
473 if (ret < 0) {
474 error("mksock: path invalid: %s", path);
475 goto out;
478 if (g_verbose >= 2)
479 fprintf(stderr, "mksock %s\n", path);
481 ret = mknod(full_path, 0600 | S_IFSOCK, 0);
482 if (ret < 0) {
483 ret = -errno;
484 error("mknod %s failed: %s", path, strerror(-ret));
487 out:
488 return ret;
491 static int process_symlink(const char *path, const char *lnk, void *user)
493 int ret;
494 struct btrfs_receive *r = user;
495 char full_path[PATH_MAX];
497 ret = path_cat_out(full_path, r->full_subvol_path, path);
498 if (ret < 0) {
499 error("symlink: path invalid: %s", path);
500 goto out;
503 if (g_verbose >= 2)
504 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
506 ret = symlink(lnk, full_path);
507 if (ret < 0) {
508 ret = -errno;
509 error("symlink %s -> %s failed: %s", path,
510 lnk, strerror(-ret));
513 out:
514 return ret;
517 static int process_rename(const char *from, const char *to, void *user)
519 int ret;
520 struct btrfs_receive *r = user;
521 char full_from[PATH_MAX];
522 char full_to[PATH_MAX];
524 ret = path_cat_out(full_from, r->full_subvol_path, from);
525 if (ret < 0) {
526 error("rename: source path invalid: %s", from);
527 goto out;
530 ret = path_cat_out(full_to, r->full_subvol_path, to);
531 if (ret < 0) {
532 error("rename: target path invalid: %s", to);
533 goto out;
536 if (g_verbose >= 2)
537 fprintf(stderr, "rename %s -> %s\n", from, to);
539 ret = rename(full_from, full_to);
540 if (ret < 0) {
541 ret = -errno;
542 error("rename %s -> %s failed: %s", from,
543 to, strerror(-ret));
546 out:
547 return ret;
550 static int process_link(const char *path, const char *lnk, void *user)
552 int ret;
553 struct btrfs_receive *r = user;
554 char full_path[PATH_MAX];
555 char full_link_path[PATH_MAX];
557 ret = path_cat_out(full_path, r->full_subvol_path, path);
558 if (ret < 0) {
559 error("link: source path invalid: %s", full_path);
560 goto out;
563 ret = path_cat_out(full_link_path, r->full_subvol_path, lnk);
564 if (ret < 0) {
565 error("link: target path invalid: %s", full_link_path);
566 goto out;
569 if (g_verbose >= 2)
570 fprintf(stderr, "link %s -> %s\n", path, lnk);
572 ret = link(full_link_path, full_path);
573 if (ret < 0) {
574 ret = -errno;
575 error("link %s -> %s failed: %s", path, lnk, strerror(-ret));
578 out:
579 return ret;
583 static int process_unlink(const char *path, void *user)
585 int ret;
586 struct btrfs_receive *r = user;
587 char full_path[PATH_MAX];
589 ret = path_cat_out(full_path, r->full_subvol_path, path);
590 if (ret < 0) {
591 error("unlink: path invalid: %s", path);
592 goto out;
595 if (g_verbose >= 2)
596 fprintf(stderr, "unlink %s\n", path);
598 ret = unlink(full_path);
599 if (ret < 0) {
600 ret = -errno;
601 error("unlink %s failed. %s", path, strerror(-ret));
604 out:
605 return ret;
608 static int process_rmdir(const char *path, void *user)
610 int ret;
611 struct btrfs_receive *r = user;
612 char full_path[PATH_MAX];
614 ret = path_cat_out(full_path, r->full_subvol_path, path);
615 if (ret < 0) {
616 error("rmdir: path invalid: %s", path);
617 goto out;
620 if (g_verbose >= 2)
621 fprintf(stderr, "rmdir %s\n", path);
623 ret = rmdir(full_path);
624 if (ret < 0) {
625 ret = -errno;
626 error("rmdir %s failed: %s", path, strerror(-ret));
629 out:
630 return ret;
633 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
635 int ret = 0;
637 if (r->write_fd != -1) {
638 if (strcmp(r->write_path, path) == 0)
639 goto out;
640 close(r->write_fd);
641 r->write_fd = -1;
644 r->write_fd = open(path, O_RDWR);
645 if (r->write_fd < 0) {
646 ret = -errno;
647 error("cannont open %s: %s", path, strerror(-ret));
648 goto out;
650 strncpy_null(r->write_path, path);
652 out:
653 return ret;
656 static void close_inode_for_write(struct btrfs_receive *r)
658 if(r->write_fd == -1)
659 return;
661 close(r->write_fd);
662 r->write_fd = -1;
663 r->write_path[0] = 0;
666 static int process_write(const char *path, const void *data, u64 offset,
667 u64 len, void *user)
669 int ret = 0;
670 struct btrfs_receive *r = user;
671 char full_path[PATH_MAX];
672 u64 pos = 0;
673 int w;
675 ret = path_cat_out(full_path, r->full_subvol_path, path);
676 if (ret < 0) {
677 error("write: path invalid: %s", path);
678 goto out;
681 ret = open_inode_for_write(r, full_path);
682 if (ret < 0)
683 goto out;
685 while (pos < len) {
686 w = pwrite(r->write_fd, (char*)data + pos, len - pos,
687 offset + pos);
688 if (w < 0) {
689 ret = -errno;
690 error("writing to %s failed: %s\n",
691 path, strerror(-ret));
692 goto out;
694 pos += w;
697 out:
698 return ret;
701 static int process_clone(const char *path, u64 offset, u64 len,
702 const u8 *clone_uuid, u64 clone_ctransid,
703 const char *clone_path, u64 clone_offset,
704 void *user)
706 int ret;
707 struct btrfs_receive *r = user;
708 struct btrfs_ioctl_clone_range_args clone_args;
709 struct subvol_info *si = NULL;
710 char full_path[PATH_MAX];
711 char *subvol_path = NULL;
712 char full_clone_path[PATH_MAX];
713 int clone_fd = -1;
715 ret = path_cat_out(full_path, r->full_subvol_path, path);
716 if (ret < 0) {
717 error("clone: source path invalid: %s", path);
718 goto out;
721 ret = open_inode_for_write(r, full_path);
722 if (ret < 0)
723 goto out;
725 si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL,
726 subvol_search_by_received_uuid);
727 if (!si) {
728 if (memcmp(clone_uuid, r->cur_subvol.received_uuid,
729 BTRFS_UUID_SIZE) == 0) {
730 /* TODO check generation of extent */
731 subvol_path = strdup(r->cur_subvol_path);
732 } else {
733 ret = -ENOENT;
734 error("clone: did not find source subvol");
735 goto out;
737 } else {
738 /*if (rs_args.ctransid > rs_args.rtransid) {
739 if (!r->force) {
740 ret = -EINVAL;
741 fprintf(stderr, "ERROR: subvolume %s was "
742 "modified after it was "
743 "received.\n",
744 r->subvol_parent_name);
745 goto out;
746 } else {
747 fprintf(stderr, "WARNING: subvolume %s was "
748 "modified after it was "
749 "received.\n",
750 r->subvol_parent_name);
753 subvol_path = strdup(si->path);
756 ret = path_cat_out(full_clone_path, subvol_path, clone_path);
757 if (ret < 0) {
758 error("clone: target path invalid: %s", clone_path);
759 goto out;
762 clone_fd = openat(r->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
763 if (clone_fd < 0) {
764 ret = -errno;
765 error("cannot open %s: %s", full_clone_path, strerror(-ret));
766 goto out;
769 clone_args.src_fd = clone_fd;
770 clone_args.src_offset = clone_offset;
771 clone_args.src_length = len;
772 clone_args.dest_offset = offset;
773 ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
774 if (ret < 0) {
775 ret = -errno;
776 error("failed to clone extents to %s\n%s\n",
777 path, strerror(-ret));
778 goto out;
781 out:
782 if (si) {
783 free(si->path);
784 free(si);
786 free(subvol_path);
787 if (clone_fd != -1)
788 close(clone_fd);
789 return ret;
793 static int process_set_xattr(const char *path, const char *name,
794 const void *data, int len, void *user)
796 int ret = 0;
797 struct btrfs_receive *r = user;
798 char full_path[PATH_MAX];
800 ret = path_cat_out(full_path, r->full_subvol_path, path);
801 if (ret < 0) {
802 error("set_xattr: path invalid: %s", path);
803 goto out;
806 if (strcmp("security.capability", name) == 0) {
807 if (g_verbose >= 3)
808 fprintf(stderr, "set_xattr: cache capabilities\n");
809 if (r->cached_capabilities_len)
810 warning("capabilities set multiple times per file: %s",
811 full_path);
812 if (len > sizeof(r->cached_capabilities)) {
813 error("capabilities encoded to %d bytes, buffer too small",
814 len);
815 ret = -E2BIG;
816 goto out;
818 r->cached_capabilities_len = len;
819 memcpy(r->cached_capabilities, data, len);
822 if (g_verbose >= 2) {
823 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
824 "data=%.*s\n", path, name, len,
825 len, (char*)data);
828 ret = lsetxattr(full_path, name, data, len, 0);
829 if (ret < 0) {
830 ret = -errno;
831 error("lsetxattr %s %s=%.*s failed: %s",
832 path, name, len, (char*)data, strerror(-ret));
833 goto out;
836 out:
837 return ret;
840 static int process_remove_xattr(const char *path, const char *name, void *user)
842 int ret = 0;
843 struct btrfs_receive *r = user;
844 char full_path[PATH_MAX];
846 ret = path_cat_out(full_path, r->full_subvol_path, path);
847 if (ret < 0) {
848 error("remove_xattr: path invalid: %s", path);
849 goto out;
852 if (g_verbose >= 2) {
853 fprintf(stderr, "remove_xattr %s - name=%s\n",
854 path, name);
857 ret = lremovexattr(full_path, name);
858 if (ret < 0) {
859 ret = -errno;
860 error("lremovexattr %s %s failed: %s",
861 path, name, strerror(-ret));
862 goto out;
865 out:
866 return ret;
869 static int process_truncate(const char *path, u64 size, void *user)
871 int ret = 0;
872 struct btrfs_receive *r = user;
873 char full_path[PATH_MAX];
875 ret = path_cat_out(full_path, r->full_subvol_path, path);
876 if (ret < 0) {
877 error("truncate: path invalid: %s", path);
878 goto out;
881 if (g_verbose >= 2)
882 fprintf(stderr, "truncate %s size=%llu\n", path, size);
884 ret = truncate(full_path, size);
885 if (ret < 0) {
886 ret = -errno;
887 error("truncate %s failed: %s", path, strerror(-ret));
888 goto out;
891 out:
892 return ret;
895 static int process_chmod(const char *path, u64 mode, void *user)
897 int ret = 0;
898 struct btrfs_receive *r = user;
899 char full_path[PATH_MAX];
901 ret = path_cat_out(full_path, r->full_subvol_path, path);
902 if (ret < 0) {
903 error("chmod: path invalid: %s", path);
904 goto out;
907 if (g_verbose >= 2)
908 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
910 ret = chmod(full_path, mode);
911 if (ret < 0) {
912 ret = -errno;
913 error("chmod %s failed: %s", path, strerror(-ret));
914 goto out;
917 out:
918 return ret;
921 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
923 int ret = 0;
924 struct btrfs_receive *r = user;
925 char full_path[PATH_MAX];
927 ret = path_cat_out(full_path, r->full_subvol_path, path);
928 if (ret < 0) {
929 error("chown: path invalid: %s", path);
930 goto out;
933 if (g_verbose >= 2)
934 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
935 uid, gid);
937 ret = lchown(full_path, uid, gid);
938 if (ret < 0) {
939 ret = -errno;
940 error("chown %s failed: %s", path, strerror(-ret));
941 goto out;
944 if (r->cached_capabilities_len) {
945 if (g_verbose >= 2)
946 fprintf(stderr, "chown: restore capabilities\n");
947 ret = lsetxattr(full_path, "security.capability",
948 r->cached_capabilities,
949 r->cached_capabilities_len, 0);
950 memset(r->cached_capabilities, 0,
951 sizeof(r->cached_capabilities));
952 r->cached_capabilities_len = 0;
953 if (ret < 0) {
954 ret = -errno;
955 error("restoring capabilities %s: %s",
956 path, strerror(-ret));
957 goto out;
961 out:
962 return ret;
965 static int process_utimes(const char *path, struct timespec *at,
966 struct timespec *mt, struct timespec *ct,
967 void *user)
969 int ret = 0;
970 struct btrfs_receive *r = user;
971 char full_path[PATH_MAX];
972 struct timespec tv[2];
974 ret = path_cat_out(full_path, r->full_subvol_path, path);
975 if (ret < 0) {
976 error("utimes: path invalid: %s", path);
977 goto out;
980 if (g_verbose >= 2)
981 fprintf(stderr, "utimes %s\n", path);
983 tv[0] = *at;
984 tv[1] = *mt;
985 ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
986 if (ret < 0) {
987 ret = -errno;
988 error("utimes %s failed: %s",
989 path, strerror(-ret));
990 goto out;
993 out:
994 return ret;
997 static int process_update_extent(const char *path, u64 offset, u64 len,
998 void *user)
1000 if (g_verbose >= 2)
1001 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1002 path, (unsigned long long)offset,
1003 (unsigned long long)len);
1006 * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1009 return 0;
1012 static struct btrfs_send_ops send_ops = {
1013 .subvol = process_subvol,
1014 .snapshot = process_snapshot,
1015 .mkfile = process_mkfile,
1016 .mkdir = process_mkdir,
1017 .mknod = process_mknod,
1018 .mkfifo = process_mkfifo,
1019 .mksock = process_mksock,
1020 .symlink = process_symlink,
1021 .rename = process_rename,
1022 .link = process_link,
1023 .unlink = process_unlink,
1024 .rmdir = process_rmdir,
1025 .write = process_write,
1026 .clone = process_clone,
1027 .set_xattr = process_set_xattr,
1028 .remove_xattr = process_remove_xattr,
1029 .truncate = process_truncate,
1030 .chmod = process_chmod,
1031 .chown = process_chown,
1032 .utimes = process_utimes,
1033 .update_extent = process_update_extent,
1036 static int do_receive(struct btrfs_receive *r, const char *tomnt,
1037 char *realmnt, int r_fd, u64 max_errors)
1039 u64 subvol_id;
1040 int ret;
1041 char *dest_dir_full_path;
1042 char root_subvol_path[PATH_MAX];
1043 int end = 0;
1045 dest_dir_full_path = realpath(tomnt, NULL);
1046 if (!dest_dir_full_path) {
1047 ret = -errno;
1048 error("realpath(%s) failed: %s", tomnt, strerror(-ret));
1049 goto out;
1051 r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1052 if (r->dest_dir_fd < 0) {
1053 ret = -errno;
1054 error("cannot open destination directory %s: %s",
1055 dest_dir_full_path, strerror(-ret));
1056 goto out;
1059 if (realmnt[0]) {
1060 r->root_path = realmnt;
1061 } else {
1062 ret = find_mount_root(dest_dir_full_path, &r->root_path);
1063 if (ret < 0) {
1064 error("failed to determine mount point for %s: %s",
1065 dest_dir_full_path, strerror(-ret));
1066 ret = -EINVAL;
1067 goto out;
1069 if (ret > 0) {
1070 error("%s doesn't belong to btrfs mount point",
1071 dest_dir_full_path);
1072 ret = -EINVAL;
1073 goto out;
1076 r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
1077 if (r->mnt_fd < 0) {
1078 ret = -errno;
1079 error("cannot open %s: %s", r->root_path, strerror(-ret));
1080 goto out;
1084 * If we use -m or a default subvol we want to resolve the path to the
1085 * subvolume we're sitting in so that we can adjust the paths of any
1086 * subvols we want to receive in.
1088 ret = btrfs_list_get_path_rootid(r->mnt_fd, &subvol_id);
1089 if (ret) {
1090 error("cannot resolve our subvolid: %d",
1091 ret);
1092 goto out;
1095 root_subvol_path[0] = 0;
1096 ret = btrfs_subvolid_resolve(r->mnt_fd, root_subvol_path,
1097 PATH_MAX, subvol_id);
1098 if (ret) {
1099 error("cannot resolve our subvol path");
1100 goto out;
1104 * Ok we're inside of a subvol off of the root subvol, we need to
1105 * actually set full_root_path.
1107 if (*root_subvol_path)
1108 r->full_root_path = root_subvol_path;
1110 if (r->dest_dir_chroot) {
1111 if (chroot(dest_dir_full_path)) {
1112 ret = -errno;
1113 error("failed to chroot to %s: %s",
1114 dest_dir_full_path, strerror(-ret));
1115 goto out;
1117 if (chdir("/")) {
1118 ret = -errno;
1119 error("failed to chdir to / after chroot: %s",
1120 strerror(-ret));
1121 goto out;
1123 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1124 r->root_path = strdup("/");
1125 r->dest_dir_path = r->root_path;
1126 } else {
1128 * find_mount_root returns a root_path that is a subpath of
1129 * dest_dir_full_path. Now get the other part of root_path,
1130 * which is the destination dir relative to root_path.
1132 r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
1133 while (r->dest_dir_path[0] == '/')
1134 r->dest_dir_path++;
1137 ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
1138 if (ret < 0)
1139 goto out;
1141 while (!end) {
1142 if (r->cached_capabilities_len) {
1143 if (g_verbose >= 3)
1144 fprintf(stderr, "clear cached capabilities\n");
1145 memset(r->cached_capabilities, 0,
1146 sizeof(r->cached_capabilities));
1147 r->cached_capabilities_len = 0;
1150 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
1151 r->honor_end_cmd,
1152 max_errors);
1153 if (ret < 0)
1154 goto out;
1155 if (ret)
1156 end = 1;
1158 close_inode_for_write(r);
1159 ret = finish_subvol(r);
1160 if (ret < 0)
1161 goto out;
1163 ret = 0;
1165 out:
1166 if (r->write_fd != -1) {
1167 close(r->write_fd);
1168 r->write_fd = -1;
1171 if (r->root_path != realmnt)
1172 free(r->root_path);
1173 r->root_path = NULL;
1174 r->dest_dir_path = NULL;
1175 free(dest_dir_full_path);
1176 subvol_uuid_search_finit(&r->sus);
1177 if (r->mnt_fd != -1) {
1178 close(r->mnt_fd);
1179 r->mnt_fd = -1;
1181 if (r->dest_dir_fd != -1) {
1182 close(r->dest_dir_fd);
1183 r->dest_dir_fd = -1;
1186 return ret;
1189 int cmd_receive(int argc, char **argv)
1191 char *tomnt = NULL;
1192 char fromfile[PATH_MAX];
1193 char realmnt[PATH_MAX];
1194 struct btrfs_receive r;
1195 int receive_fd = fileno(stdin);
1196 u64 max_errors = 1;
1197 int ret = 0;
1199 memset(&r, 0, sizeof(r));
1200 r.mnt_fd = -1;
1201 r.write_fd = -1;
1202 r.dest_dir_fd = -1;
1203 r.dest_dir_chroot = 0;
1204 realmnt[0] = 0;
1205 fromfile[0] = 0;
1207 while (1) {
1208 int c;
1209 static const struct option long_opts[] = {
1210 { "max-errors", required_argument, NULL, 'E' },
1211 { "chroot", no_argument, NULL, 'C' },
1212 { NULL, 0, NULL, 0 }
1215 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1216 if (c < 0)
1217 break;
1219 switch (c) {
1220 case 'v':
1221 g_verbose++;
1222 break;
1223 case 'f':
1224 if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1225 error("input file path too long (%zu)",
1226 strlen(optarg));
1227 ret = 1;
1228 goto out;
1230 break;
1231 case 'e':
1232 r.honor_end_cmd = 1;
1233 break;
1234 case 'C':
1235 r.dest_dir_chroot = 1;
1236 break;
1237 case 'E':
1238 max_errors = arg_strtou64(optarg);
1239 break;
1240 case 'm':
1241 if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1242 error("mount point path too long (%zu)",
1243 strlen(optarg));
1244 ret = 1;
1245 goto out;
1247 break;
1248 case '?':
1249 default:
1250 error("receive args invalid");
1251 return 1;
1255 if (check_argc_exact(argc - optind, 1))
1256 usage(cmd_receive_usage);
1258 tomnt = argv[optind];
1260 if (fromfile[0]) {
1261 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1262 if (receive_fd < 0) {
1263 error("cannot open %s: %s", fromfile, strerror(errno));
1264 goto out;
1268 ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1269 if (receive_fd != fileno(stdin))
1270 close(receive_fd);
1272 out:
1274 return !!ret;
1277 const char * const cmd_receive_usage[] = {
1278 "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1279 "Receive subvolumes from stdin.",
1280 "Receives one or more subvolumes that were previously",
1281 "sent with btrfs send. The received subvolumes are stored",
1282 "into <mount>.",
1283 "btrfs receive will fail in case a receiving subvolume",
1284 "already exists. It will also fail in case a previously",
1285 "received subvolume was changed after it was received.",
1286 "After receiving a subvolume, it is immediately set to",
1287 "read only.\n",
1288 "-v Enable verbose debug output. Each",
1289 " occurrence of this option increases the",
1290 " verbose level more.",
1291 "-f <infile> By default, btrfs receive uses stdin",
1292 " to receive the subvolumes. Use this",
1293 " option to specify a file to use instead.",
1294 "-e Terminate after receiving an <end cmd>",
1295 " in the data stream. Without this option,",
1296 " the receiver terminates only if an error",
1297 " is recognized or on EOF.",
1298 "-C|--chroot confine the process to <mount> using chroot",
1299 "--max-errors <N> Terminate as soon as N errors happened while",
1300 " processing commands from the send stream.",
1301 " Default value is 1. A value of 0 means no limit.",
1302 "-m <mountpoint> The root mount point of the destination fs.",
1303 " If you do not have /proc use this to tell us where ",
1304 " this file system is mounted.",
1305 NULL