btrfs-progs: tests: add testing image for zstd for btrfs-restore
[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 #include "send-dump.h"
53 #include "help.h"
54
55 static int g_verbose = 0;
56
57 struct btrfs_receive
58 {
59         int mnt_fd;
60         int dest_dir_fd;
61
62         int write_fd;
63         char write_path[PATH_MAX];
64
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;
70
71         struct subvol_info cur_subvol;
72         /*
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.
75          */
76         char cur_subvol_path[PATH_MAX];
77
78         struct subvol_uuid_search sus;
79
80         int honor_end_cmd;
81
82         /*
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.
86          */
87         char cached_capabilities[64];
88         int cached_capabilities_len;
89 };
90
91 static int finish_subvol(struct btrfs_receive *rctx)
92 {
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;
98
99         if (rctx->cur_subvol_path[0] == 0)
100                 return 0;
101
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;
109         }
110
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;
114
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);
119         }
120
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;
127         }
128         rctx->cur_subvol.rtransid = rs_args.rtransid;
129
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;
136         }
137
138         flags |= BTRFS_SUBVOL_RDONLY;
139
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;
146         }
147
148         ret = 0;
149
150 out:
151         if (rctx->cur_subvol_path[0]) {
152                 rctx->cur_subvol_path[0] = 0;
153         }
154         if (subvol_fd != -1)
155                 close(subvol_fd);
156         return ret;
157 }
158
159 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
160                           void *user)
161 {
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];
166
167         ret = finish_subvol(rctx);
168         if (ret < 0)
169                 goto out;
170
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;
176         }
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;
182         }
183
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;
192                 }
193         }
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;
199         }
200
201         fprintf(stderr, "At subvol %s\n", path);
202
203         memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
204         rctx->cur_subvol.stransid = ctransid;
205
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);
211         }
212
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;
220         }
221
222 out:
223         return ret;
224 }
225
226 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
227                             const u8 *parent_uuid, u64 parent_ctransid,
228                             void *user)
229 {
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;
235
236         ret = finish_subvol(rctx);
237         if (ret < 0)
238                 goto out;
239
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;
245         }
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;
251         }
252
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;
261                 }
262         }
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;
268         }
269
270         fprintf(stdout, "At snapshot %s\n", path);
271
272         memcpy(rctx->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
273         rctx->cur_subvol.stransid = ctransid;
274
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);
283         }
284
285         memset(&args_v2, 0, sizeof(args_v2));
286         strncpy_null(args_v2.name, path);
287
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);
295         }
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;
303         }
304
305         /*
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.
309          */
310         if (rctx->full_root_path) {
311                 size_t root_len;
312                 size_t sub_len;
313
314                 root_len = strlen(rctx->full_root_path);
315                 sub_len = strlen(parent_subvol->path);
316
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;
324                 }
325
326                 if (sub_len == root_len) {
327                         parent_subvol->path[0] = '.';
328                         parent_subvol->path[1] = '\0';
329                 } else {
330                         /*
331                          * root path is foo/bar
332                          * subvol path is foo/bar/baz
333                          *
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.
338                          */
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';
343                 }
344         }
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);
352                 }
353         }*/
354
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;
372         }
373
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;
381         }
382
383 out:
384         if (parent_subvol) {
385                 free(parent_subvol->path);
386                 free(parent_subvol);
387         }
388         return ret;
389 }
390
391 static int process_mkfile(const char *path, void *user)
392 {
393         int ret;
394         struct btrfs_receive *rctx = user;
395         char full_path[PATH_MAX];
396
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;
401         }
402
403         if (g_verbose >= 2)
404                 fprintf(stderr, "mkfile %s\n", path);
405
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;
411         }
412         close(ret);
413         ret = 0;
414
415 out:
416         return ret;
417 }
418
419 static int process_mkdir(const char *path, void *user)
420 {
421         int ret;
422         struct btrfs_receive *rctx = user;
423         char full_path[PATH_MAX];
424
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;
429         }
430
431         if (g_verbose >= 2)
432                 fprintf(stderr, "mkdir %s\n", path);
433
434         ret = mkdir(full_path, 0700);
435         if (ret < 0) {
436                 ret = -errno;
437                 error("mkdir %s failed: %s", path, strerror(-ret));
438         }
439
440 out:
441         return ret;
442 }
443
444 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
445 {
446         int ret;
447         struct btrfs_receive *rctx = user;
448         char full_path[PATH_MAX];
449
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;
454         }
455
456         if (g_verbose >= 2)
457                 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
458                                 path, mode, dev);
459
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));
464         }
465
466 out:
467         return ret;
468 }
469
470 static int process_mkfifo(const char *path, void *user)
471 {
472         int ret;
473         struct btrfs_receive *rctx = user;
474         char full_path[PATH_MAX];
475
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;
480         }
481
482         if (g_verbose >= 2)
483                 fprintf(stderr, "mkfifo %s\n", path);
484
485         ret = mkfifo(full_path, 0600);
486         if (ret < 0) {
487                 ret = -errno;
488                 error("mkfifo %s failed: %s", path, strerror(-ret));
489         }
490
491 out:
492         return ret;
493 }
494
495 static int process_mksock(const char *path, void *user)
496 {
497         int ret;
498         struct btrfs_receive *rctx = user;
499         char full_path[PATH_MAX];
500
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;
505         }
506
507         if (g_verbose >= 2)
508                 fprintf(stderr, "mksock %s\n", path);
509
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));
514         }
515
516 out:
517         return ret;
518 }
519
520 static int process_symlink(const char *path, const char *lnk, void *user)
521 {
522         int ret;
523         struct btrfs_receive *rctx = user;
524         char full_path[PATH_MAX];
525
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;
530         }
531
532         if (g_verbose >= 2)
533                 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
534
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));
540         }
541
542 out:
543         return ret;
544 }
545
546 static int process_rename(const char *from, const char *to, void *user)
547 {
548         int ret;
549         struct btrfs_receive *rctx = user;
550         char full_from[PATH_MAX];
551         char full_to[PATH_MAX];
552
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;
557         }
558
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;
563         }
564
565         if (g_verbose >= 2)
566                 fprintf(stderr, "rename %s -> %s\n", from, to);
567
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));
573         }
574
575 out:
576         return ret;
577 }
578
579 static int process_link(const char *path, const char *lnk, void *user)
580 {
581         int ret;
582         struct btrfs_receive *rctx = user;
583         char full_path[PATH_MAX];
584         char full_link_path[PATH_MAX];
585
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;
590         }
591
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;
596         }
597
598         if (g_verbose >= 2)
599                 fprintf(stderr, "link %s -> %s\n", path, lnk);
600
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));
605         }
606
607 out:
608         return ret;
609 }
610
611
612 static int process_unlink(const char *path, void *user)
613 {
614         int ret;
615         struct btrfs_receive *rctx = user;
616         char full_path[PATH_MAX];
617
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;
622         }
623
624         if (g_verbose >= 2)
625                 fprintf(stderr, "unlink %s\n", path);
626
627         ret = unlink(full_path);
628         if (ret < 0) {
629                 ret = -errno;
630                 error("unlink %s failed. %s", path, strerror(-ret));
631         }
632
633 out:
634         return ret;
635 }
636
637 static int process_rmdir(const char *path, void *user)
638 {
639         int ret;
640         struct btrfs_receive *rctx = user;
641         char full_path[PATH_MAX];
642
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;
647         }
648
649         if (g_verbose >= 2)
650                 fprintf(stderr, "rmdir %s\n", path);
651
652         ret = rmdir(full_path);
653         if (ret < 0) {
654                 ret = -errno;
655                 error("rmdir %s failed: %s", path, strerror(-ret));
656         }
657
658 out:
659         return ret;
660 }
661
662 static int open_inode_for_write(struct btrfs_receive *rctx, const char *path)
663 {
664         int ret = 0;
665
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;
671         }
672
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;
678         }
679         strncpy_null(rctx->write_path, path);
680
681 out:
682         return ret;
683 }
684
685 static void close_inode_for_write(struct btrfs_receive *rctx)
686 {
687         if(rctx->write_fd == -1)
688                 return;
689
690         close(rctx->write_fd);
691         rctx->write_fd = -1;
692         rctx->write_path[0] = 0;
693 }
694
695 static int process_write(const char *path, const void *data, u64 offset,
696                          u64 len, void *user)
697 {
698         int ret = 0;
699         struct btrfs_receive *rctx = user;
700         char full_path[PATH_MAX];
701         u64 pos = 0;
702         int w;
703
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;
708         }
709
710         ret = open_inode_for_write(rctx, full_path);
711         if (ret < 0)
712                 goto out;
713
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;
722                 }
723                 pos += w;
724         }
725
726 out:
727         return ret;
728 }
729
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)
734 {
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;
743
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;
748         }
749
750         ret = open_inode_for_write(rctx, full_path);
751         if (ret < 0)
752                 goto out;
753
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;
769                 }
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);
784                         }
785                 }*/
786
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);
791
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;
800                         }
801                 } else {
802                         subvol_path = strdup(si->path);
803                 }
804         }
805
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;
810         }
811
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;
817         }
818
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;
829         }
830
831 out:
832         if (si) {
833                 free(si->path);
834                 free(si);
835         }
836         free(subvol_path);
837         if (clone_fd != -1)
838                 close(clone_fd);
839         return ret;
840 }
841
842
843 static int process_set_xattr(const char *path, const char *name,
844                              const void *data, int len, void *user)
845 {
846         int ret = 0;
847         struct btrfs_receive *rctx = user;
848         char full_path[PATH_MAX];
849
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;
854         }
855
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;
867                 }
868                 rctx->cached_capabilities_len = len;
869                 memcpy(rctx->cached_capabilities, data, len);
870         }
871
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);
876         }
877
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;
884         }
885
886 out:
887         return ret;
888 }
889
890 static int process_remove_xattr(const char *path, const char *name, void *user)
891 {
892         int ret = 0;
893         struct btrfs_receive *rctx = user;
894         char full_path[PATH_MAX];
895
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;
900         }
901
902         if (g_verbose >= 2) {
903                 fprintf(stderr, "remove_xattr %s - name=%s\n",
904                                 path, name);
905         }
906
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;
913         }
914
915 out:
916         return ret;
917 }
918
919 static int process_truncate(const char *path, u64 size, void *user)
920 {
921         int ret = 0;
922         struct btrfs_receive *rctx = user;
923         char full_path[PATH_MAX];
924
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;
929         }
930
931         if (g_verbose >= 2)
932                 fprintf(stderr, "truncate %s size=%llu\n", path, size);
933
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;
939         }
940
941 out:
942         return ret;
943 }
944
945 static int process_chmod(const char *path, u64 mode, void *user)
946 {
947         int ret = 0;
948         struct btrfs_receive *rctx = user;
949         char full_path[PATH_MAX];
950
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;
955         }
956
957         if (g_verbose >= 2)
958                 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
959
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;
965         }
966
967 out:
968         return ret;
969 }
970
971 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
972 {
973         int ret = 0;
974         struct btrfs_receive *rctx = user;
975         char full_path[PATH_MAX];
976
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;
981         }
982
983         if (g_verbose >= 2)
984                 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
985                                 uid, gid);
986
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;
992         }
993
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;
1008                 }
1009         }
1010
1011 out:
1012         return ret;
1013 }
1014
1015 static int process_utimes(const char *path, struct timespec *at,
1016                           struct timespec *mt, struct timespec *ct,
1017                           void *user)
1018 {
1019         int ret = 0;
1020         struct btrfs_receive *rctx = user;
1021         char full_path[PATH_MAX];
1022         struct timespec tv[2];
1023
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;
1028         }
1029
1030         if (g_verbose >= 2)
1031                 fprintf(stderr, "utimes %s\n", path);
1032
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;
1041         }
1042
1043 out:
1044         return ret;
1045 }
1046
1047 static int process_update_extent(const char *path, u64 offset, u64 len,
1048                 void *user)
1049 {
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);
1054
1055         /*
1056          * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1057          */
1058
1059         return 0;
1060 }
1061
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,
1084 };
1085
1086 static int do_receive(struct btrfs_receive *rctx, const char *tomnt,
1087                       char *realmnt, int r_fd, u64 max_errors)
1088 {
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;
1095
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;
1101         }
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;
1108         }
1109
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;
1119                 }
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;
1125                 }
1126         }
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;
1132         }
1133
1134         /*
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.
1138          */
1139         ret = btrfs_list_get_path_rootid(rctx->mnt_fd, &subvol_id);
1140         if (ret)
1141                 goto out;
1142
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;
1149         }
1150
1151         /*
1152          * Ok we're inside of a subvol off of the root subvol, we need to
1153          * actually set full_root_path.
1154          */
1155         if (*root_subvol_path)
1156                 rctx->full_root_path = root_subvol_path;
1157
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;
1164                 }
1165                 if (chdir("/")) {
1166                         ret = -errno;
1167                         error("failed to chdir to / after chroot: %s",
1168                                 strerror(-ret));
1169                         goto out;
1170                 }
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 {
1175                 /*
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.
1179                  */
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++;
1183         }
1184
1185         ret = subvol_uuid_search_init(rctx->mnt_fd, &rctx->sus);
1186         if (ret < 0)
1187                 goto out;
1188
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;
1196                 }
1197
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;
1205
1206                         /* Empty stream is invalid */
1207                         if (iterations == 0) {
1208                                 error("empty stream is not considered valid");
1209                                 ret = -EINVAL;
1210                                 goto out;
1211                         }
1212
1213                         ret = 1;
1214                 }
1215                 if (ret > 0)
1216                         end = 1;
1217
1218                 close_inode_for_write(rctx);
1219                 ret = finish_subvol(rctx);
1220                 if (ret < 0)
1221                         goto out;
1222
1223                 iterations++;
1224         }
1225         ret = 0;
1226
1227 out:
1228         if (rctx->write_fd != -1) {
1229                 close(rctx->write_fd);
1230                 rctx->write_fd = -1;
1231         }
1232
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;
1242         }
1243         if (rctx->dest_dir_fd != -1) {
1244                 close(rctx->dest_dir_fd);
1245                 rctx->dest_dir_fd = -1;
1246         }
1247
1248         return ret;
1249 }
1250
1251 int cmd_receive(int argc, char **argv)
1252 {
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;
1261
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;
1269
1270         while (1) {
1271                 int c;
1272                 enum { GETOPT_VAL_DUMP = 257 };
1273                 static const struct option long_opts[] = {
1274                         { "max-errors", required_argument, NULL, 'E' },
1275                         { "chroot", no_argument, NULL, 'C' },
1276                         { "dump", no_argument, NULL, GETOPT_VAL_DUMP },
1277                         { NULL, 0, NULL, 0 }
1278                 };
1279
1280                 c = getopt_long(argc, argv, "Cevf:m:E:", long_opts, NULL);
1281                 if (c < 0)
1282                         break;
1283
1284                 switch (c) {
1285                 case 'v':
1286                         g_verbose++;
1287                         break;
1288                 case 'f':
1289                         if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1290                                 error("input file path too long (%zu)",
1291                                         strlen(optarg));
1292                                 ret = 1;
1293                                 goto out;
1294                         }
1295                         break;
1296                 case 'e':
1297                         rctx.honor_end_cmd = 1;
1298                         break;
1299                 case 'C':
1300                         rctx.dest_dir_chroot = 1;
1301                         break;
1302                 case 'E':
1303                         max_errors = arg_strtou64(optarg);
1304                         break;
1305                 case 'm':
1306                         if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1307                                 error("mount point path too long (%zu)",
1308                                         strlen(optarg));
1309                                 ret = 1;
1310                                 goto out;
1311                         }
1312                         break;
1313                 case GETOPT_VAL_DUMP:
1314                         dump = 1;
1315                         break;
1316                 case '?':
1317                 default:
1318                         error("receive args invalid");
1319                         return 1;
1320                 }
1321         }
1322
1323         if (dump && check_argc_exact(argc - optind, 0))
1324                 usage(cmd_receive_usage);
1325         if (!dump && check_argc_exact(argc - optind, 1))
1326                 usage(cmd_receive_usage);
1327
1328         tomnt = argv[optind];
1329
1330         if (fromfile[0]) {
1331                 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1332                 if (receive_fd < 0) {
1333                         error("cannot open %s: %s", fromfile, strerror(errno));
1334                         goto out;
1335                 }
1336         }
1337
1338         if (dump) {
1339                 struct btrfs_dump_send_args dump_args;
1340
1341                 dump_args.root_path[0] = '.';
1342                 dump_args.root_path[1] = '\0';
1343                 dump_args.full_subvol_path[0] = '.';
1344                 dump_args.full_subvol_path[1] = '\0';
1345                 ret = btrfs_read_and_process_send_stream(receive_fd,
1346                                 &btrfs_print_send_ops, &dump_args, 0, 0);
1347                 if (ret < 0)
1348                         error("failed to dump the send stream: %s",
1349                               strerror(-ret));
1350         } else {
1351                 ret = do_receive(&rctx, tomnt, realmnt, receive_fd, max_errors);
1352         }
1353
1354         if (receive_fd != fileno(stdin))
1355                 close(receive_fd);
1356 out:
1357
1358         return !!ret;
1359 }
1360
1361 const char * const cmd_receive_usage[] = {
1362         "btrfs receive [options] <mount>\n"
1363         "btrfs receive --dump [options]",
1364         "Receive subvolumes from a stream",
1365         "Receives one or more subvolumes that were previously",
1366         "sent with btrfs send. The received subvolumes are stored",
1367         "into MOUNT.",
1368         "The receive will fail in case the receiving subvolume",
1369         "already exists. It will also fail in case a previously",
1370         "received subvolume has been changed after it was received.",
1371         "After receiving a subvolume, it is immediately set to",
1372         "read-only.",
1373         "",
1374         "-v               increase verbosity about performed actions",
1375         "-f FILE          read the stream from FILE instead of stdin",
1376         "-e               terminate after receiving an <end cmd> marker in the stream.",
1377         "                 Without this option the receiver side terminates only in case",
1378         "                 of an error on end of file.",
1379         "-C|--chroot      confine the process to <mount> using chroot",
1380         "-E|--max-errors NERR",
1381         "                 terminate as soon as NERR errors occur while",
1382         "                 stream processing commands from the stream.",
1383         "                 Default value is 1. A value of 0 means no limit.",
1384         "-m ROOTMOUNT     the root mount point of the destination filesystem.",
1385         "                 If /proc is not accessible, use this to tell us where",
1386         "                 this file system is mounted.",
1387         "--dump           dump stream metadata, one line per operation,",
1388         "                 does not require the MOUNT parameter",
1389         NULL
1390 };