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