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