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