btrfs-progs: Restrict e2fsprogs version for convert
[platform/upstream/btrfs-progs.git] / cmds-receive.c
1 /*
2  * Copyright (C) 2012 Alexander Block.  All rights reserved.
3  *
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.
7  *
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.
12  *
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.
17  */
18
19 #include "kerncompat.h"
20 #include "androidcompat.h"
21
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>
33
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>
41
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"
48
49 #include "send.h"
50 #include "send-stream.h"
51 #include "send-utils.h"
52
53 static int g_verbose = 0;
54
55 struct btrfs_receive
56 {
57         int mnt_fd;
58         int dest_dir_fd;
59
60         int write_fd;
61         char write_path[PATH_MAX];
62
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;
68
69         struct subvol_info cur_subvol;
70         /*
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.
73          */
74         char cur_subvol_path[PATH_MAX];
75
76         struct subvol_uuid_search sus;
77
78         int honor_end_cmd;
79
80         /*
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.
84          */
85         char cached_capabilities[64];
86         int cached_capabilities_len;
87 };
88
89 static int finish_subvol(struct btrfs_receive *r)
90 {
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;
96
97         if (r->cur_subvol_path[0] == 0)
98                 return 0;
99
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;
107         }
108
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;
112
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);
117         }
118
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;
125         }
126         r->cur_subvol.rtransid = rs_args.rtransid;
127
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;
134         }
135
136         flags |= BTRFS_SUBVOL_RDONLY;
137
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;
144         }
145
146         ret = 0;
147
148 out:
149         if (r->cur_subvol_path[0]) {
150                 r->cur_subvol_path[0] = 0;
151         }
152         if (subvol_fd != -1)
153                 close(subvol_fd);
154         return ret;
155 }
156
157 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
158                           void *user)
159 {
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];
164
165         ret = finish_subvol(r);
166         if (ret < 0)
167                 goto out;
168
169         BUG_ON(r->cur_subvol.path);
170         BUG_ON(r->cur_subvol_path[0]);
171
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;
179                 }
180         }
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;
186         }
187
188         fprintf(stderr, "At subvol %s\n", path);
189
190         memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
191         r->cur_subvol.stransid = ctransid;
192
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);
198         }
199
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;
207         }
208
209 out:
210         return ret;
211 }
212
213 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
214                             const u8 *parent_uuid, u64 parent_ctransid,
215                             void *user)
216 {
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;
222
223         ret = finish_subvol(r);
224         if (ret < 0)
225                 goto out;
226
227         BUG_ON(r->cur_subvol.path);
228         BUG_ON(r->cur_subvol_path[0]);
229
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;
237                 }
238         }
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;
244         }
245
246         fprintf(stdout, "At snapshot %s\n", path);
247
248         memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
249         r->cur_subvol.stransid = ctransid;
250
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);
259         }
260
261         memset(&args_v2, 0, sizeof(args_v2));
262         strncpy_null(args_v2.name, path);
263
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);
269         }
270         if (!parent_subvol) {
271                 ret = -ENOENT;
272                 error("cannot find parent subvolume");
273                 goto out;
274         }
275
276         /*
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.
280          */
281         if (r->full_root_path) {
282                 size_t root_len;
283                 size_t sub_len;
284
285                 root_len = strlen(r->full_root_path);
286                 sub_len = strlen(parent_subvol->path);
287
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;
295                 }
296
297                 if (sub_len == root_len) {
298                         parent_subvol->path[0] = '/';
299                         parent_subvol->path[1] = '\0';
300                 } else {
301                         /*
302                          * root path is foo/bar
303                          * subvol path is foo/bar/baz
304                          *
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.
309                          */
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';
314                 }
315         }
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);
323                 }
324         }*/
325
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;
343         }
344
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;
352         }
353
354 out:
355         if (parent_subvol) {
356                 free(parent_subvol->path);
357                 free(parent_subvol);
358         }
359         return ret;
360 }
361
362 static int process_mkfile(const char *path, void *user)
363 {
364         int ret;
365         struct btrfs_receive *r = user;
366         char full_path[PATH_MAX];
367
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;
372         }
373
374         if (g_verbose >= 2)
375                 fprintf(stderr, "mkfile %s\n", path);
376
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;
382         }
383         close(ret);
384         ret = 0;
385
386 out:
387         return ret;
388 }
389
390 static int process_mkdir(const char *path, void *user)
391 {
392         int ret;
393         struct btrfs_receive *r = user;
394         char full_path[PATH_MAX];
395
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;
400         }
401
402         if (g_verbose >= 2)
403                 fprintf(stderr, "mkdir %s\n", path);
404
405         ret = mkdir(full_path, 0700);
406         if (ret < 0) {
407                 ret = -errno;
408                 error("mkdir %s failed: %s", path, strerror(-ret));
409         }
410
411 out:
412         return ret;
413 }
414
415 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
416 {
417         int ret;
418         struct btrfs_receive *r = user;
419         char full_path[PATH_MAX];
420
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;
425         }
426
427         if (g_verbose >= 2)
428                 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
429                                 path, mode, dev);
430
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));
435         }
436
437 out:
438         return ret;
439 }
440
441 static int process_mkfifo(const char *path, void *user)
442 {
443         int ret;
444         struct btrfs_receive *r = user;
445         char full_path[PATH_MAX];
446
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;
451         }
452
453         if (g_verbose >= 2)
454                 fprintf(stderr, "mkfifo %s\n", path);
455
456         ret = mkfifo(full_path, 0600);
457         if (ret < 0) {
458                 ret = -errno;
459                 error("mkfifo %s failed: %s", path, strerror(-ret));
460         }
461
462 out:
463         return ret;
464 }
465
466 static int process_mksock(const char *path, void *user)
467 {
468         int ret;
469         struct btrfs_receive *r = user;
470         char full_path[PATH_MAX];
471
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;
476         }
477
478         if (g_verbose >= 2)
479                 fprintf(stderr, "mksock %s\n", path);
480
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));
485         }
486
487 out:
488         return ret;
489 }
490
491 static int process_symlink(const char *path, const char *lnk, void *user)
492 {
493         int ret;
494         struct btrfs_receive *r = user;
495         char full_path[PATH_MAX];
496
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;
501         }
502
503         if (g_verbose >= 2)
504                 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
505
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));
511         }
512
513 out:
514         return ret;
515 }
516
517 static int process_rename(const char *from, const char *to, void *user)
518 {
519         int ret;
520         struct btrfs_receive *r = user;
521         char full_from[PATH_MAX];
522         char full_to[PATH_MAX];
523
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;
528         }
529
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;
534         }
535
536         if (g_verbose >= 2)
537                 fprintf(stderr, "rename %s -> %s\n", from, to);
538
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));
544         }
545
546 out:
547         return ret;
548 }
549
550 static int process_link(const char *path, const char *lnk, void *user)
551 {
552         int ret;
553         struct btrfs_receive *r = user;
554         char full_path[PATH_MAX];
555         char full_link_path[PATH_MAX];
556
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;
561         }
562
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;
567         }
568
569         if (g_verbose >= 2)
570                 fprintf(stderr, "link %s -> %s\n", path, lnk);
571
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));
576         }
577
578 out:
579         return ret;
580 }
581
582
583 static int process_unlink(const char *path, void *user)
584 {
585         int ret;
586         struct btrfs_receive *r = user;
587         char full_path[PATH_MAX];
588
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;
593         }
594
595         if (g_verbose >= 2)
596                 fprintf(stderr, "unlink %s\n", path);
597
598         ret = unlink(full_path);
599         if (ret < 0) {
600                 ret = -errno;
601                 error("unlink %s failed. %s", path, strerror(-ret));
602         }
603
604 out:
605         return ret;
606 }
607
608 static int process_rmdir(const char *path, void *user)
609 {
610         int ret;
611         struct btrfs_receive *r = user;
612         char full_path[PATH_MAX];
613
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;
618         }
619
620         if (g_verbose >= 2)
621                 fprintf(stderr, "rmdir %s\n", path);
622
623         ret = rmdir(full_path);
624         if (ret < 0) {
625                 ret = -errno;
626                 error("rmdir %s failed: %s", path, strerror(-ret));
627         }
628
629 out:
630         return ret;
631 }
632
633 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
634 {
635         int ret = 0;
636
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;
642         }
643
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;
649         }
650         strncpy_null(r->write_path, path);
651
652 out:
653         return ret;
654 }
655
656 static void close_inode_for_write(struct btrfs_receive *r)
657 {
658         if(r->write_fd == -1)
659                 return;
660
661         close(r->write_fd);
662         r->write_fd = -1;
663         r->write_path[0] = 0;
664 }
665
666 static int process_write(const char *path, const void *data, u64 offset,
667                          u64 len, void *user)
668 {
669         int ret = 0;
670         struct btrfs_receive *r = user;
671         char full_path[PATH_MAX];
672         u64 pos = 0;
673         int w;
674
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;
679         }
680
681         ret = open_inode_for_write(r, full_path);
682         if (ret < 0)
683                 goto out;
684
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;
693                 }
694                 pos += w;
695         }
696
697 out:
698         return ret;
699 }
700
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)
705 {
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;
714
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;
719         }
720
721         ret = open_inode_for_write(r, full_path);
722         if (ret < 0)
723                 goto out;
724
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;
736                 }
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);
751                         }
752                 }*/
753                 subvol_path = strdup(si->path);
754         }
755
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;
760         }
761
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;
767         }
768
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;
779         }
780
781 out:
782         if (si) {
783                 free(si->path);
784                 free(si);
785         }
786         free(subvol_path);
787         if (clone_fd != -1)
788                 close(clone_fd);
789         return ret;
790 }
791
792
793 static int process_set_xattr(const char *path, const char *name,
794                              const void *data, int len, void *user)
795 {
796         int ret = 0;
797         struct btrfs_receive *r = user;
798         char full_path[PATH_MAX];
799
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;
804         }
805
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;
817                 }
818                 r->cached_capabilities_len = len;
819                 memcpy(r->cached_capabilities, data, len);
820         }
821
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);
826         }
827
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;
834         }
835
836 out:
837         return ret;
838 }
839
840 static int process_remove_xattr(const char *path, const char *name, void *user)
841 {
842         int ret = 0;
843         struct btrfs_receive *r = user;
844         char full_path[PATH_MAX];
845
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;
850         }
851
852         if (g_verbose >= 2) {
853                 fprintf(stderr, "remove_xattr %s - name=%s\n",
854                                 path, name);
855         }
856
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;
863         }
864
865 out:
866         return ret;
867 }
868
869 static int process_truncate(const char *path, u64 size, void *user)
870 {
871         int ret = 0;
872         struct btrfs_receive *r = user;
873         char full_path[PATH_MAX];
874
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;
879         }
880
881         if (g_verbose >= 2)
882                 fprintf(stderr, "truncate %s size=%llu\n", path, size);
883
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;
889         }
890
891 out:
892         return ret;
893 }
894
895 static int process_chmod(const char *path, u64 mode, void *user)
896 {
897         int ret = 0;
898         struct btrfs_receive *r = user;
899         char full_path[PATH_MAX];
900
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;
905         }
906
907         if (g_verbose >= 2)
908                 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
909
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;
915         }
916
917 out:
918         return ret;
919 }
920
921 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
922 {
923         int ret = 0;
924         struct btrfs_receive *r = user;
925         char full_path[PATH_MAX];
926
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;
931         }
932
933         if (g_verbose >= 2)
934                 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
935                                 uid, gid);
936
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;
942         }
943
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;
958                 }
959         }
960
961 out:
962         return ret;
963 }
964
965 static int process_utimes(const char *path, struct timespec *at,
966                           struct timespec *mt, struct timespec *ct,
967                           void *user)
968 {
969         int ret = 0;
970         struct btrfs_receive *r = user;
971         char full_path[PATH_MAX];
972         struct timespec tv[2];
973
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;
978         }
979
980         if (g_verbose >= 2)
981                 fprintf(stderr, "utimes %s\n", path);
982
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;
991         }
992
993 out:
994         return ret;
995 }
996
997 static int process_update_extent(const char *path, u64 offset, u64 len,
998                 void *user)
999 {
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);
1004
1005         /*
1006          * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1007          */
1008
1009         return 0;
1010 }
1011
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,
1034 };
1035
1036 static int do_receive(struct btrfs_receive *r, const char *tomnt,
1037                       char *realmnt, int r_fd, u64 max_errors)
1038 {
1039         u64 subvol_id;
1040         int ret;
1041         char *dest_dir_full_path;
1042         char root_subvol_path[PATH_MAX];
1043         int end = 0;
1044
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;
1050         }
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;
1057         }
1058
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;
1068                 }
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;
1074                 }
1075         }
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;
1081         }
1082
1083         /*
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.
1087          */
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;
1093         }
1094
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;
1101         }
1102
1103         /*
1104          * Ok we're inside of a subvol off of the root subvol, we need to
1105          * actually set full_root_path.
1106          */
1107         if (*root_subvol_path)
1108                 r->full_root_path = root_subvol_path;
1109
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;
1116                 }
1117                 if (chdir("/")) {
1118                         ret = -errno;
1119                         error("failed to chdir to / after chroot: %s",
1120                                 strerror(-ret));
1121                         goto out;
1122                 }
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 {
1127                 /*
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.
1131                  */
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++;
1135         }
1136
1137         ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
1138         if (ret < 0)
1139                 goto out;
1140
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;
1148                 }
1149
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;
1157
1158                 close_inode_for_write(r);
1159                 ret = finish_subvol(r);
1160                 if (ret < 0)
1161                         goto out;
1162         }
1163         ret = 0;
1164
1165 out:
1166         if (r->write_fd != -1) {
1167                 close(r->write_fd);
1168                 r->write_fd = -1;
1169         }
1170
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;
1180         }
1181         if (r->dest_dir_fd != -1) {
1182                 close(r->dest_dir_fd);
1183                 r->dest_dir_fd = -1;
1184         }
1185
1186         return ret;
1187 }
1188
1189 int cmd_receive(int argc, char **argv)
1190 {
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;
1198
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;
1206
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 }
1213                 };
1214
1215                 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1216                 if (c < 0)
1217                         break;
1218
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;
1229                         }
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;
1246                         }
1247                         break;
1248                 case '?':
1249                 default:
1250                         error("receive args invalid");
1251                         return 1;
1252                 }
1253         }
1254
1255         if (check_argc_exact(argc - optind, 1))
1256                 usage(cmd_receive_usage);
1257
1258         tomnt = argv[optind];
1259
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;
1265                 }
1266         }
1267
1268         ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1269         if (receive_fd != fileno(stdin))
1270                 close(receive_fd);
1271
1272 out:
1273
1274         return !!ret;
1275 }
1276
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
1306 };