btrfs-progs: use android compat header
[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                 fprintf(stderr, "ERROR: open %s failed. %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                 fprintf(stderr, "ERROR: BTRFS_IOC_SET_RECEIVED_SUBVOL failed. %s\n",
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                 fprintf(stderr, "ERROR: BTRFS_IOC_SUBVOL_GETFLAGS failed. %s\n",
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                 fprintf(stderr, "ERROR: failed to make subvolume read only. "
142                                 "%s\n", 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 (strlen(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                         fprintf(stderr, "ERROR: subvol: path invalid: %s\n",
178                                         path);
179                         goto out;
180                 }
181         }
182         ret = path_cat3_out(r->full_subvol_path, r->root_path,
183                         r->dest_dir_path, path);
184         if (ret < 0) {
185                 fprintf(stderr, "ERROR: subvol: path invalid: %s\n", path);
186                 goto out;
187         }
188
189         fprintf(stderr, "At subvol %s\n", path);
190
191         memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
192         r->cur_subvol.stransid = ctransid;
193
194         if (g_verbose) {
195                 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
196                 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
197                                 path, uuid_str,
198                                 r->cur_subvol.stransid);
199         }
200
201         memset(&args_v1, 0, sizeof(args_v1));
202         strncpy_null(args_v1.name, path);
203         ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
204         if (ret < 0) {
205                 ret = -errno;
206                 fprintf(stderr, "ERROR: creating subvolume %s failed. "
207                                 "%s\n", path, strerror(-ret));
208                 goto out;
209         }
210
211 out:
212         return ret;
213 }
214
215 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
216                             const u8 *parent_uuid, u64 parent_ctransid,
217                             void *user)
218 {
219         int ret;
220         struct btrfs_receive *r = user;
221         char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
222         struct btrfs_ioctl_vol_args_v2 args_v2;
223         struct subvol_info *parent_subvol = NULL;
224
225         ret = finish_subvol(r);
226         if (ret < 0)
227                 goto out;
228
229         BUG_ON(r->cur_subvol.path);
230         BUG_ON(r->cur_subvol_path[0]);
231
232         if (strlen(r->dest_dir_path) == 0) {
233                 strncpy_null(r->cur_subvol_path, path);
234         } else {
235                 ret = path_cat_out(r->cur_subvol_path, r->dest_dir_path, path);
236                 if (ret < 0) {
237                         fprintf(stderr, "ERROR: snapshot: path invalid: %s\n",
238                                         path);
239                         goto out;
240                 }
241         }
242         ret = path_cat3_out(r->full_subvol_path, r->root_path,
243                         r->dest_dir_path, path);
244         if (ret < 0) {
245                 fprintf(stderr, "ERROR: snapshot: path invalid: %s\n", path);
246                 goto out;
247         }
248
249         fprintf(stdout, "At snapshot %s\n", path);
250
251         memcpy(r->cur_subvol.received_uuid, uuid, BTRFS_UUID_SIZE);
252         r->cur_subvol.stransid = ctransid;
253
254         if (g_verbose) {
255                 uuid_unparse((u8*)r->cur_subvol.received_uuid, uuid_str);
256                 fprintf(stderr, "receiving snapshot %s uuid=%s, "
257                                 "ctransid=%llu ", path, uuid_str,
258                                 r->cur_subvol.stransid);
259                 uuid_unparse(parent_uuid, uuid_str);
260                 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
261                                 uuid_str, parent_ctransid);
262         }
263
264         memset(&args_v2, 0, sizeof(args_v2));
265         strncpy_null(args_v2.name, path);
266
267         parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
268                         parent_ctransid, NULL, subvol_search_by_received_uuid);
269         if (!parent_subvol) {
270                 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
271                                 parent_ctransid, NULL, subvol_search_by_uuid);
272         }
273         if (!parent_subvol) {
274                 ret = -ENOENT;
275                 fprintf(stderr, "ERROR: could not find parent subvolume\n");
276                 goto out;
277         }
278
279         /*
280          * The path is resolved from the root subvol, but we could be in some
281          * subvolume under the root subvolume, so try and adjust the path to be
282          * relative to our root path.
283          */
284         if (r->full_root_path) {
285                 size_t root_len;
286                 size_t sub_len;
287
288                 root_len = strlen(r->full_root_path);
289                 sub_len = strlen(parent_subvol->path);
290
291                 /* First make sure the parent subvol is actually in our path */
292                 if (sub_len < root_len ||
293                     strstr(parent_subvol->path, r->full_root_path) == NULL) {
294                         fprintf(stderr, "ERROR: parent subvol is not reachable"
295                                 " from inside the root subvol.\n");
296                         ret = -ENOENT;
297                         goto out;
298                 }
299
300                 if (sub_len == root_len) {
301                         parent_subvol->path[0] = '/';
302                         parent_subvol->path[1] = '\0';
303                 } else {
304                         /*
305                          * root path is foo/bar
306                          * subvol path is foo/bar/baz
307                          *
308                          * we need to have baz be the path, so we need to move
309                          * the bit after foo/bar/, so path + root_len + 1, and
310                          * move the part we care about, so sub_len - root_len -
311                          * 1.
312                          */
313                         memmove(parent_subvol->path,
314                                 parent_subvol->path + root_len + 1,
315                                 sub_len - root_len - 1);
316                         parent_subvol->path[sub_len - root_len - 1] = '\0';
317                 }
318         }
319         /*if (rs_args.ctransid > rs_args.rtransid) {
320                 if (!r->force) {
321                         ret = -EINVAL;
322                         fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
323                         goto out;
324                 } else {
325                         fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
326                 }
327         }*/
328
329         if (strlen(parent_subvol->path) == 0)
330                 args_v2.fd = dup(r->mnt_fd);
331         else
332                 args_v2.fd = openat(r->mnt_fd, parent_subvol->path,
333                                 O_RDONLY | O_NOATIME);
334         if (args_v2.fd < 0) {
335                 ret = -errno;
336                 if (errno != ENOENT)
337                         fprintf(stderr, "ERROR: open %s failed. %s\n",
338                                         parent_subvol->path, strerror(-ret));
339                 else
340                         fprintf(stderr,
341                                 "It seems that you have changed your default "
342                                 "subvolume or you specify other subvolume to\n"
343                                 "mount btrfs, try to remount this btrfs filesystem "
344                                 "with fs tree, and run btrfs receive again!\n");
345                 goto out;
346         }
347
348         ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
349         close(args_v2.fd);
350         if (ret < 0) {
351                 ret = -errno;
352                 fprintf(stderr, "ERROR: creating snapshot %s -> %s "
353                                 "failed. %s\n", parent_subvol->path,
354                                 path, strerror(-ret));
355                 goto out;
356         }
357
358 out:
359         if (parent_subvol) {
360                 free(parent_subvol->path);
361                 free(parent_subvol);
362         }
363         return ret;
364 }
365
366 static int process_mkfile(const char *path, void *user)
367 {
368         int ret;
369         struct btrfs_receive *r = user;
370         char full_path[PATH_MAX];
371
372         ret = path_cat_out(full_path, r->full_subvol_path, path);
373         if (ret < 0) {
374                 fprintf(stderr, "ERROR: mkfile: path invalid: %s\n", path);
375                 goto out;
376         }
377
378         if (g_verbose >= 2)
379                 fprintf(stderr, "mkfile %s\n", path);
380
381         ret = creat(full_path, 0600);
382         if (ret < 0) {
383                 ret = -errno;
384                 fprintf(stderr, "ERROR: mkfile %s failed. %s\n", path,
385                                 strerror(-ret));
386                 goto out;
387         }
388         close(ret);
389         ret = 0;
390
391 out:
392         return ret;
393 }
394
395 static int process_mkdir(const char *path, void *user)
396 {
397         int ret;
398         struct btrfs_receive *r = user;
399         char full_path[PATH_MAX];
400
401         ret = path_cat_out(full_path, r->full_subvol_path, path);
402         if (ret < 0) {
403                 fprintf(stderr, "ERROR: mkdir: path invalid: %s\n", path);
404                 goto out;
405         }
406
407         if (g_verbose >= 2)
408                 fprintf(stderr, "mkdir %s\n", path);
409
410         ret = mkdir(full_path, 0700);
411         if (ret < 0) {
412                 ret = -errno;
413                 fprintf(stderr, "ERROR: mkdir %s failed. %s\n", path,
414                                 strerror(-ret));
415         }
416
417 out:
418         return ret;
419 }
420
421 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
422 {
423         int ret;
424         struct btrfs_receive *r = user;
425         char full_path[PATH_MAX];
426
427         ret = path_cat_out(full_path, r->full_subvol_path, path);
428         if (ret < 0) {
429                 fprintf(stderr, "ERROR: mknod: path invalid: %s\n", path);
430                 goto out;
431         }
432
433         if (g_verbose >= 2)
434                 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
435                                 path, mode, dev);
436
437         ret = mknod(full_path, mode & S_IFMT, dev);
438         if (ret < 0) {
439                 ret = -errno;
440                 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
441                                 strerror(-ret));
442         }
443
444 out:
445         return ret;
446 }
447
448 static int process_mkfifo(const char *path, void *user)
449 {
450         int ret;
451         struct btrfs_receive *r = user;
452         char full_path[PATH_MAX];
453
454         ret = path_cat_out(full_path, r->full_subvol_path, path);
455         if (ret < 0) {
456                 fprintf(stderr, "ERROR: mkfifo: path invalid: %s\n", path);
457                 goto out;
458         }
459
460         if (g_verbose >= 2)
461                 fprintf(stderr, "mkfifo %s\n", path);
462
463         ret = mkfifo(full_path, 0600);
464         if (ret < 0) {
465                 ret = -errno;
466                 fprintf(stderr, "ERROR: mkfifo %s failed. %s\n", path,
467                                 strerror(-ret));
468         }
469
470 out:
471         return ret;
472 }
473
474 static int process_mksock(const char *path, void *user)
475 {
476         int ret;
477         struct btrfs_receive *r = user;
478         char full_path[PATH_MAX];
479
480         ret = path_cat_out(full_path, r->full_subvol_path, path);
481         if (ret < 0) {
482                 fprintf(stderr, "ERROR: mksock: path invalid: %s\n", path);
483                 goto out;
484         }
485
486         if (g_verbose >= 2)
487                 fprintf(stderr, "mksock %s\n", path);
488
489         ret = mknod(full_path, 0600 | S_IFSOCK, 0);
490         if (ret < 0) {
491                 ret = -errno;
492                 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
493                                 strerror(-ret));
494         }
495
496 out:
497         return ret;
498 }
499
500 static int process_symlink(const char *path, const char *lnk, void *user)
501 {
502         int ret;
503         struct btrfs_receive *r = user;
504         char full_path[PATH_MAX];
505
506         ret = path_cat_out(full_path, r->full_subvol_path, path);
507         if (ret < 0) {
508                 fprintf(stderr, "ERROR: symlink: path invalid: %s\n", path);
509                 goto out;
510         }
511
512         if (g_verbose >= 2)
513                 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
514
515         ret = symlink(lnk, full_path);
516         if (ret < 0) {
517                 ret = -errno;
518                 fprintf(stderr, "ERROR: symlink %s -> %s failed. %s\n", path,
519                                 lnk, strerror(-ret));
520         }
521
522 out:
523         return ret;
524 }
525
526 static int process_rename(const char *from, const char *to, void *user)
527 {
528         int ret;
529         struct btrfs_receive *r = user;
530         char full_from[PATH_MAX];
531         char full_to[PATH_MAX];
532
533         ret = path_cat_out(full_from, r->full_subvol_path, from);
534         if (ret < 0) {
535                 fprintf(stderr, "ERROR: rename: source path invalid: %s\n",
536                                 from);
537                 goto out;
538         }
539
540         ret = path_cat_out(full_to, r->full_subvol_path, to);
541         if (ret < 0) {
542                 fprintf(stderr, "ERROR: rename: target path invalid: %s\n",
543                                 to);
544                 goto out;
545         }
546
547         if (g_verbose >= 2)
548                 fprintf(stderr, "rename %s -> %s\n", from, to);
549
550         ret = rename(full_from, full_to);
551         if (ret < 0) {
552                 ret = -errno;
553                 fprintf(stderr, "ERROR: rename %s -> %s failed. %s\n", from,
554                                 to, strerror(-ret));
555         }
556
557 out:
558         return ret;
559 }
560
561 static int process_link(const char *path, const char *lnk, void *user)
562 {
563         int ret;
564         struct btrfs_receive *r = user;
565         char full_path[PATH_MAX];
566         char full_link_path[PATH_MAX];
567
568         ret = path_cat_out(full_path, r->full_subvol_path, path);
569         if (ret < 0) {
570                 fprintf(stderr, "ERROR: link: source path invalid: %s\n",
571                                 full_path);
572                 goto out;
573         }
574
575         ret = path_cat_out(full_link_path, r->full_subvol_path, lnk);
576         if (ret < 0) {
577                 fprintf(stderr, "ERROR: link: target path invalid: %s\n",
578                                 full_link_path);
579                 goto out;
580         }
581
582         if (g_verbose >= 2)
583                 fprintf(stderr, "link %s -> %s\n", path, lnk);
584
585         ret = link(full_link_path, full_path);
586         if (ret < 0) {
587                 ret = -errno;
588                 fprintf(stderr, "ERROR: link %s -> %s failed. %s\n", path,
589                                 lnk, strerror(-ret));
590         }
591
592 out:
593         return ret;
594 }
595
596
597 static int process_unlink(const char *path, void *user)
598 {
599         int ret;
600         struct btrfs_receive *r = user;
601         char full_path[PATH_MAX];
602
603         ret = path_cat_out(full_path, r->full_subvol_path, path);
604         if (ret < 0) {
605                 fprintf(stderr, "ERROR: unlink: path invalid: %s\n", path);
606                 goto out;
607         }
608
609         if (g_verbose >= 2)
610                 fprintf(stderr, "unlink %s\n", path);
611
612         ret = unlink(full_path);
613         if (ret < 0) {
614                 ret = -errno;
615                 fprintf(stderr, "ERROR: unlink %s failed. %s\n", path,
616                                 strerror(-ret));
617         }
618
619 out:
620         return ret;
621 }
622
623 static int process_rmdir(const char *path, void *user)
624 {
625         int ret;
626         struct btrfs_receive *r = user;
627         char full_path[PATH_MAX];
628
629         ret = path_cat_out(full_path, r->full_subvol_path, path);
630         if (ret < 0) {
631                 fprintf(stderr, "ERROR: rmdir: path invalid: %s\n", path);
632                 goto out;
633         }
634
635         if (g_verbose >= 2)
636                 fprintf(stderr, "rmdir %s\n", path);
637
638         ret = rmdir(full_path);
639         if (ret < 0) {
640                 ret = -errno;
641                 fprintf(stderr, "ERROR: rmdir %s failed. %s\n", path,
642                                 strerror(-ret));
643         }
644
645 out:
646         return ret;
647 }
648
649 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
650 {
651         int ret = 0;
652
653         if (r->write_fd != -1) {
654                 if (strcmp(r->write_path, path) == 0)
655                         goto out;
656                 close(r->write_fd);
657                 r->write_fd = -1;
658         }
659
660         r->write_fd = open(path, O_RDWR);
661         if (r->write_fd < 0) {
662                 ret = -errno;
663                 fprintf(stderr, "ERROR: open %s failed. %s\n", path,
664                                 strerror(-ret));
665                 goto out;
666         }
667         strncpy_null(r->write_path, path);
668
669 out:
670         return ret;
671 }
672
673 static void close_inode_for_write(struct btrfs_receive *r)
674 {
675         if(r->write_fd == -1)
676                 return;
677
678         close(r->write_fd);
679         r->write_fd = -1;
680         r->write_path[0] = 0;
681 }
682
683 static int process_write(const char *path, const void *data, u64 offset,
684                          u64 len, void *user)
685 {
686         int ret = 0;
687         struct btrfs_receive *r = user;
688         char full_path[PATH_MAX];
689         u64 pos = 0;
690         int w;
691
692         ret = path_cat_out(full_path, r->full_subvol_path, path);
693         if (ret < 0) {
694                 fprintf(stderr, "ERROR: write: path invalid: %s\n", path);
695                 goto out;
696         }
697
698         ret = open_inode_for_write(r, full_path);
699         if (ret < 0)
700                 goto out;
701
702         while (pos < len) {
703                 w = pwrite(r->write_fd, (char*)data + pos, len - pos,
704                                 offset + pos);
705                 if (w < 0) {
706                         ret = -errno;
707                         fprintf(stderr, "ERROR: writing to %s failed. %s\n",
708                                         path, strerror(-ret));
709                         goto out;
710                 }
711                 pos += w;
712         }
713
714 out:
715         return ret;
716 }
717
718 static int process_clone(const char *path, u64 offset, u64 len,
719                          const u8 *clone_uuid, u64 clone_ctransid,
720                          const char *clone_path, u64 clone_offset,
721                          void *user)
722 {
723         int ret;
724         struct btrfs_receive *r = user;
725         struct btrfs_ioctl_clone_range_args clone_args;
726         struct subvol_info *si = NULL;
727         char full_path[PATH_MAX];
728         char *subvol_path = NULL;
729         char full_clone_path[PATH_MAX];
730         int clone_fd = -1;
731
732         ret = path_cat_out(full_path, r->full_subvol_path, path);
733         if (ret < 0) {
734                 fprintf(stderr, "ERROR: clone: source path invalid: %s\n",
735                                 path);
736                 goto out;
737         }
738
739         ret = open_inode_for_write(r, full_path);
740         if (ret < 0)
741                 goto out;
742
743         si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL,
744                         subvol_search_by_received_uuid);
745         if (!si) {
746                 if (memcmp(clone_uuid, r->cur_subvol.received_uuid,
747                                 BTRFS_UUID_SIZE) == 0) {
748                         /* TODO check generation of extent */
749                         subvol_path = strdup(r->cur_subvol_path);
750                 } else {
751                         ret = -ENOENT;
752                         fprintf(stderr, "ERROR: did not find source subvol.\n");
753                         goto out;
754                 }
755         } else {
756                 /*if (rs_args.ctransid > rs_args.rtransid) {
757                         if (!r->force) {
758                                 ret = -EINVAL;
759                                 fprintf(stderr, "ERROR: subvolume %s was "
760                                                 "modified after it was "
761                                                 "received.\n",
762                                                 r->subvol_parent_name);
763                                 goto out;
764                         } else {
765                                 fprintf(stderr, "WARNING: subvolume %s was "
766                                                 "modified after it was "
767                                                 "received.\n",
768                                                 r->subvol_parent_name);
769                         }
770                 }*/
771                 subvol_path = strdup(si->path);
772         }
773
774         ret = path_cat_out(full_clone_path, subvol_path, clone_path);
775         if (ret < 0) {
776                 fprintf(stderr, "ERROR: clone: target path invalid: %s\n",
777                                 clone_path);
778                 goto out;
779         }
780
781         clone_fd = openat(r->mnt_fd, full_clone_path, O_RDONLY | O_NOATIME);
782         if (clone_fd < 0) {
783                 ret = -errno;
784                 fprintf(stderr, "ERROR: failed to open %s. %s\n",
785                                 full_clone_path, strerror(-ret));
786                 goto out;
787         }
788
789         clone_args.src_fd = clone_fd;
790         clone_args.src_offset = clone_offset;
791         clone_args.src_length = len;
792         clone_args.dest_offset = offset;
793         ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
794         if (ret) {
795                 ret = -errno;
796                 fprintf(stderr, "ERROR: failed to clone extents to %s\n%s\n",
797                                 path, strerror(-ret));
798                 goto out;
799         }
800
801 out:
802         if (si) {
803                 free(si->path);
804                 free(si);
805         }
806         free(subvol_path);
807         if (clone_fd != -1)
808                 close(clone_fd);
809         return ret;
810 }
811
812
813 static int process_set_xattr(const char *path, const char *name,
814                              const void *data, int len, void *user)
815 {
816         int ret = 0;
817         struct btrfs_receive *r = user;
818         char full_path[PATH_MAX];
819
820         ret = path_cat_out(full_path, r->full_subvol_path, path);
821         if (ret < 0) {
822                 fprintf(stderr, "ERROR: set_xattr: path invalid: %s\n", path);
823                 goto out;
824         }
825
826         if (strcmp("security.capability", name) == 0) {
827                 if (g_verbose >= 3)
828                         fprintf(stderr, "set_xattr: cache capabilities\n");
829                 if (r->cached_capabilities_len)
830                         fprintf(stderr,
831                           "WARNING: capabilities set multiple times per file: %s\n",
832                                 full_path);
833                 if (len > sizeof(r->cached_capabilities)) {
834                         fprintf(stderr,
835                           "ERROR: capabilities encoded to %d bytes, buffer too small\n",
836                                 len);
837                         ret = -E2BIG;
838                         goto out;
839                 }
840                 r->cached_capabilities_len = len;
841                 memcpy(r->cached_capabilities, data, len);
842         }
843
844         if (g_verbose >= 2) {
845                 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
846                                 "data=%.*s\n", path, name, len,
847                                 len, (char*)data);
848         }
849
850         ret = lsetxattr(full_path, name, data, len, 0);
851         if (ret < 0) {
852                 ret = -errno;
853                 fprintf(stderr, "ERROR: lsetxattr %s %s=%.*s failed. %s\n",
854                                 path, name, len, (char*)data, strerror(-ret));
855                 goto out;
856         }
857
858 out:
859         return ret;
860 }
861
862 static int process_remove_xattr(const char *path, const char *name, void *user)
863 {
864         int ret = 0;
865         struct btrfs_receive *r = user;
866         char full_path[PATH_MAX];
867
868         ret = path_cat_out(full_path, r->full_subvol_path, path);
869         if (ret < 0) {
870                 fprintf(stderr, "ERROR: remove_xattr: path invalid: %s\n",
871                                 path);
872                 goto out;
873         }
874
875         if (g_verbose >= 2) {
876                 fprintf(stderr, "remove_xattr %s - name=%s\n",
877                                 path, name);
878         }
879
880         ret = lremovexattr(full_path, name);
881         if (ret < 0) {
882                 ret = -errno;
883                 fprintf(stderr, "ERROR: lremovexattr %s %s failed. %s\n",
884                                 path, name, strerror(-ret));
885                 goto out;
886         }
887
888 out:
889         return ret;
890 }
891
892 static int process_truncate(const char *path, u64 size, void *user)
893 {
894         int ret = 0;
895         struct btrfs_receive *r = user;
896         char full_path[PATH_MAX];
897
898         ret = path_cat_out(full_path, r->full_subvol_path, path);
899         if (ret < 0) {
900                 fprintf(stderr, "ERROR: truncate: path invalid: %s\n", path);
901                 goto out;
902         }
903
904         if (g_verbose >= 2)
905                 fprintf(stderr, "truncate %s size=%llu\n", path, size);
906
907         ret = truncate(full_path, size);
908         if (ret < 0) {
909                 ret = -errno;
910                 fprintf(stderr, "ERROR: truncate %s failed. %s\n",
911                                 path, strerror(-ret));
912                 goto out;
913         }
914
915 out:
916         return ret;
917 }
918
919 static int process_chmod(const char *path, u64 mode, void *user)
920 {
921         int ret = 0;
922         struct btrfs_receive *r = user;
923         char full_path[PATH_MAX];
924
925         ret = path_cat_out(full_path, r->full_subvol_path, path);
926         if (ret < 0) {
927                 fprintf(stderr, "ERROR: chmod: path invalid: %s\n", path);
928                 goto out;
929         }
930
931         if (g_verbose >= 2)
932                 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
933
934         ret = chmod(full_path, mode);
935         if (ret < 0) {
936                 ret = -errno;
937                 fprintf(stderr, "ERROR: chmod %s failed. %s\n",
938                                 path, strerror(-ret));
939                 goto out;
940         }
941
942 out:
943         return ret;
944 }
945
946 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
947 {
948         int ret = 0;
949         struct btrfs_receive *r = user;
950         char full_path[PATH_MAX];
951
952         ret = path_cat_out(full_path, r->full_subvol_path, path);
953         if (ret < 0) {
954                 fprintf(stderr, "ERROR: chown: path invalid: %s\n", path);
955                 goto out;
956         }
957
958         if (g_verbose >= 2)
959                 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
960                                 uid, gid);
961
962         ret = lchown(full_path, uid, gid);
963         if (ret < 0) {
964                 ret = -errno;
965                 fprintf(stderr, "ERROR: chown %s failed. %s\n",
966                                 path, strerror(-ret));
967                 goto out;
968         }
969
970         if (r->cached_capabilities_len) {
971                 if (g_verbose >= 2)
972                         fprintf(stderr, "chown: restore capabilities\n");
973                 ret = lsetxattr(full_path, "security.capability",
974                                 r->cached_capabilities,
975                                 r->cached_capabilities_len, 0);
976                 memset(r->cached_capabilities, 0,
977                                 sizeof(r->cached_capabilities));
978                 r->cached_capabilities_len = 0;
979                 if (ret < 0) {
980                         ret = -errno;
981                         fprintf(stderr, "ERROR: restoring capabilities %s: %s\n",
982                                         path, strerror(-ret));
983                         goto out;
984                 }
985         }
986
987 out:
988         return ret;
989 }
990
991 static int process_utimes(const char *path, struct timespec *at,
992                           struct timespec *mt, struct timespec *ct,
993                           void *user)
994 {
995         int ret = 0;
996         struct btrfs_receive *r = user;
997         char full_path[PATH_MAX];
998         struct timespec tv[2];
999
1000         ret = path_cat_out(full_path, r->full_subvol_path, path);
1001         if (ret < 0) {
1002                 fprintf(stderr, "ERROR: utimes: path invalid: %s\n", path);
1003                 goto out;
1004         }
1005
1006         if (g_verbose >= 2)
1007                 fprintf(stderr, "utimes %s\n", path);
1008
1009         tv[0] = *at;
1010         tv[1] = *mt;
1011         ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
1012         if (ret < 0) {
1013                 ret = -errno;
1014                 fprintf(stderr, "ERROR: utimes %s failed. %s\n",
1015                                 path, strerror(-ret));
1016                 goto out;
1017         }
1018
1019 out:
1020         return ret;
1021 }
1022
1023 static int process_update_extent(const char *path, u64 offset, u64 len,
1024                 void *user)
1025 {
1026         if (g_verbose >= 2)
1027                 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
1028                                 path, (unsigned long long)offset,
1029                                 (unsigned long long)len);
1030
1031         /*
1032          * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
1033          */
1034
1035         return 0;
1036 }
1037
1038 static struct btrfs_send_ops send_ops = {
1039         .subvol = process_subvol,
1040         .snapshot = process_snapshot,
1041         .mkfile = process_mkfile,
1042         .mkdir = process_mkdir,
1043         .mknod = process_mknod,
1044         .mkfifo = process_mkfifo,
1045         .mksock = process_mksock,
1046         .symlink = process_symlink,
1047         .rename = process_rename,
1048         .link = process_link,
1049         .unlink = process_unlink,
1050         .rmdir = process_rmdir,
1051         .write = process_write,
1052         .clone = process_clone,
1053         .set_xattr = process_set_xattr,
1054         .remove_xattr = process_remove_xattr,
1055         .truncate = process_truncate,
1056         .chmod = process_chmod,
1057         .chown = process_chown,
1058         .utimes = process_utimes,
1059         .update_extent = process_update_extent,
1060 };
1061
1062 static int do_receive(struct btrfs_receive *r, const char *tomnt,
1063                       char *realmnt, int r_fd, u64 max_errors)
1064 {
1065         u64 subvol_id;
1066         int ret;
1067         char *dest_dir_full_path;
1068         char root_subvol_path[PATH_MAX];
1069         int end = 0;
1070
1071         dest_dir_full_path = realpath(tomnt, NULL);
1072         if (!dest_dir_full_path) {
1073                 ret = -errno;
1074                 fprintf(stderr, "ERROR: realpath(%s) failed. %s\n", tomnt,
1075                         strerror(-ret));
1076                 goto out;
1077         }
1078         r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
1079         if (r->dest_dir_fd < 0) {
1080                 ret = -errno;
1081                 fprintf(stderr,
1082                         "ERROR: failed to open destination directory %s. %s\n",
1083                         dest_dir_full_path, strerror(-ret));
1084                 goto out;
1085         }
1086
1087         if (realmnt[0]) {
1088                 r->root_path = realmnt;
1089         } else {
1090                 ret = find_mount_root(dest_dir_full_path, &r->root_path);
1091                 if (ret < 0) {
1092                         fprintf(stderr,
1093                                 "ERROR: failed to determine mount point for %s: %s\n",
1094                                 dest_dir_full_path, strerror(-ret));
1095                         ret = -EINVAL;
1096                         goto out;
1097                 }
1098                 if (ret > 0) {
1099                         fprintf(stderr,
1100                         "ERROR: %s doesn't belong to btrfs mount point\n",
1101                         dest_dir_full_path);
1102                         ret = -EINVAL;
1103                         goto out;
1104                 }
1105         }
1106         r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
1107         if (r->mnt_fd < 0) {
1108                 ret = -errno;
1109                 fprintf(stderr, "ERROR: failed to open %s. %s\n", r->root_path,
1110                         strerror(-ret));
1111                 goto out;
1112         }
1113
1114         /*
1115          * If we use -m or a default subvol we want to resolve the path to the
1116          * subvolume we're sitting in so that we can adjust the paths of any
1117          * subvols we want to receive in.
1118          */
1119         ret = btrfs_list_get_path_rootid(r->mnt_fd, &subvol_id);
1120         if (ret) {
1121                 fprintf(stderr, "ERROR: couldn't resolve our subvolid %d\n",
1122                         ret);
1123                 goto out;
1124         }
1125
1126         root_subvol_path[0] = 0;
1127         ret = btrfs_subvolid_resolve(r->mnt_fd, root_subvol_path,
1128                                      PATH_MAX, subvol_id);
1129         if (ret) {
1130                 fprintf(stderr, "ERROR: couldn't resolve our subvol path\n");
1131                 goto out;
1132         }
1133
1134         /*
1135          * Ok we're inside of a subvol off of the root subvol, we need to
1136          * actually set full_root_path.
1137          */
1138         if (strlen(root_subvol_path))
1139                 r->full_root_path = root_subvol_path;
1140
1141         if (r->dest_dir_chroot) {
1142                 if (chroot(dest_dir_full_path)) {
1143                         ret = -errno;
1144                         fprintf(stderr,
1145                                 "ERROR: failed to chroot to %s, %s\n",
1146                                 dest_dir_full_path,
1147                                 strerror(-ret));
1148                         goto out;
1149                 }
1150                 if (chdir("/")) {
1151                         ret = -errno;
1152                         fprintf(stderr,
1153                                 "ERROR: failed to chdir to /, %s\n",
1154                                 strerror(-ret));
1155                         goto out;
1156                 }
1157                 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1158                 r->root_path = strdup("/");
1159                 r->dest_dir_path = r->root_path;
1160         } else {
1161                 /*
1162                  * find_mount_root returns a root_path that is a subpath of
1163                  * dest_dir_full_path. Now get the other part of root_path,
1164                  * which is the destination dir relative to root_path.
1165                  */
1166                 r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
1167                 while (r->dest_dir_path[0] == '/')
1168                         r->dest_dir_path++;
1169         }
1170
1171         ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
1172         if (ret < 0)
1173                 goto out;
1174
1175         while (!end) {
1176                 if (r->cached_capabilities_len) {
1177                         if (g_verbose >= 3)
1178                                 fprintf(stderr, "clear cached capabilities\n");
1179                         memset(r->cached_capabilities, 0,
1180                                         sizeof(r->cached_capabilities));
1181                         r->cached_capabilities_len = 0;
1182                 }
1183
1184                 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
1185                                                          r->honor_end_cmd,
1186                                                          max_errors);
1187                 if (ret < 0)
1188                         goto out;
1189                 if (ret)
1190                         end = 1;
1191
1192                 close_inode_for_write(r);
1193                 ret = finish_subvol(r);
1194                 if (ret < 0)
1195                         goto out;
1196         }
1197         ret = 0;
1198
1199 out:
1200         if (r->write_fd != -1) {
1201                 close(r->write_fd);
1202                 r->write_fd = -1;
1203         }
1204         free(r->root_path);
1205         r->root_path = NULL;
1206         r->dest_dir_path = NULL;
1207         free(dest_dir_full_path);
1208         subvol_uuid_search_finit(&r->sus);
1209         if (r->mnt_fd != -1) {
1210                 close(r->mnt_fd);
1211                 r->mnt_fd = -1;
1212         }
1213         if (r->dest_dir_fd != -1) {
1214                 close(r->dest_dir_fd);
1215                 r->dest_dir_fd = -1;
1216         }
1217
1218         return ret;
1219 }
1220
1221 int cmd_receive(int argc, char **argv)
1222 {
1223         char *tomnt = NULL;
1224         char fromfile[PATH_MAX];
1225         char realmnt[PATH_MAX];
1226         struct btrfs_receive r;
1227         int receive_fd = fileno(stdin);
1228         u64 max_errors = 1;
1229         int ret = 0;
1230
1231         memset(&r, 0, sizeof(r));
1232         r.mnt_fd = -1;
1233         r.write_fd = -1;
1234         r.dest_dir_fd = -1;
1235         r.dest_dir_chroot = 0;
1236         realmnt[0] = 0;
1237         fromfile[0] = 0;
1238
1239         while (1) {
1240                 int c;
1241                 static const struct option long_opts[] = {
1242                         { "max-errors", required_argument, NULL, 'E' },
1243                         { "chroot", no_argument, NULL, 'C' },
1244                         { NULL, 0, NULL, 0 }
1245                 };
1246
1247                 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1248                 if (c < 0)
1249                         break;
1250
1251                 switch (c) {
1252                 case 'v':
1253                         g_verbose++;
1254                         break;
1255                 case 'f':
1256                         if (arg_copy_path(fromfile, optarg, sizeof(fromfile))) {
1257                                 fprintf(stderr,
1258                                     "ERROR: input file path too long (%zu)\n",
1259                                     strlen(optarg));
1260                                 ret = 1;
1261                                 goto out;
1262                         }
1263                         break;
1264                 case 'e':
1265                         r.honor_end_cmd = 1;
1266                         break;
1267                 case 'C':
1268                         r.dest_dir_chroot = 1;
1269                         break;
1270                 case 'E':
1271                         max_errors = arg_strtou64(optarg);
1272                         break;
1273                 case 'm':
1274                         if (arg_copy_path(realmnt, optarg, sizeof(realmnt))) {
1275                                 fprintf(stderr,
1276                                     "ERROR: mount point path too long (%zu)\n",
1277                                     strlen(optarg));
1278                                 ret = 1;
1279                                 goto out;
1280                         }
1281                         break;
1282                 case '?':
1283                 default:
1284                         fprintf(stderr, "ERROR: receive args invalid.\n");
1285                         return 1;
1286                 }
1287         }
1288
1289         if (check_argc_exact(argc - optind, 1))
1290                 usage(cmd_receive_usage);
1291
1292         tomnt = argv[optind];
1293
1294         if (fromfile[0]) {
1295                 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1296                 if (receive_fd < 0) {
1297                         fprintf(stderr, "ERROR: failed to open %s\n", fromfile);
1298                         goto out;
1299                 }
1300         }
1301
1302         ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1303
1304 out:
1305
1306         return !!ret;
1307 }
1308
1309 const char * const cmd_receive_usage[] = {
1310         "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1311         "Receive subvolumes from stdin.",
1312         "Receives one or more subvolumes that were previously",
1313         "sent with btrfs send. The received subvolumes are stored",
1314         "into <mount>.",
1315         "btrfs receive will fail in case a receiving subvolume",
1316         "already exists. It will also fail in case a previously",
1317         "received subvolume was changed after it was received.",
1318         "After receiving a subvolume, it is immediately set to",
1319         "read only.\n",
1320         "-v               Enable verbose debug output. Each",
1321         "                 occurrence of this option increases the",
1322         "                 verbose level more.",
1323         "-f <infile>      By default, btrfs receive uses stdin",
1324         "                 to receive the subvolumes. Use this",
1325         "                 option to specify a file to use instead.",
1326         "-e               Terminate after receiving an <end cmd>",
1327         "                 in the data stream. Without this option,",
1328         "                 the receiver terminates only if an error",
1329         "                 is recognized or on EOF.",
1330         "-C|--chroot      confine the process to <mount> using chroot",
1331         "--max-errors <N> Terminate as soon as N errors happened while",
1332         "                 processing commands from the send stream.",
1333         "                 Default value is 1. A value of 0 means no limit.",
1334         "-m <mountpoint>  The root mount point of the destination fs.",
1335         "                 If you do not have /proc use this to tell us where ",
1336         "                 this file system is mounted.",
1337         NULL
1338 };