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