btrfs-progs: use PATH_MAX instead of BTRFS_PATH_NAME_MAX
[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 static int process_update_extent(const char *path, u64 offset, u64 len,
880                 void *user)
881 {
882         if (g_verbose >= 2)
883                 fprintf(stderr, "update_extent %s: offset=%llu, len=%llu\n",
884                                 path, (unsigned long long)offset,
885                                 (unsigned long long)len);
886
887         /*
888          * Sent with BTRFS_SEND_FLAG_NO_FILE_DATA, nothing to do.
889          */
890
891         return 0;
892 }
893
894 static struct btrfs_send_ops send_ops = {
895         .subvol = process_subvol,
896         .snapshot = process_snapshot,
897         .mkfile = process_mkfile,
898         .mkdir = process_mkdir,
899         .mknod = process_mknod,
900         .mkfifo = process_mkfifo,
901         .mksock = process_mksock,
902         .symlink = process_symlink,
903         .rename = process_rename,
904         .link = process_link,
905         .unlink = process_unlink,
906         .rmdir = process_rmdir,
907         .write = process_write,
908         .clone = process_clone,
909         .set_xattr = process_set_xattr,
910         .remove_xattr = process_remove_xattr,
911         .truncate = process_truncate,
912         .chmod = process_chmod,
913         .chown = process_chown,
914         .utimes = process_utimes,
915         .update_extent = process_update_extent,
916 };
917
918 static int do_receive(struct btrfs_receive *r, const char *tomnt,
919                       char *realmnt, int r_fd, u64 max_errors)
920 {
921         u64 subvol_id;
922         int ret;
923         char *dest_dir_full_path;
924         char *root_subvol_path;
925         int end = 0;
926
927         dest_dir_full_path = realpath(tomnt, NULL);
928         if (!dest_dir_full_path) {
929                 ret = -errno;
930                 fprintf(stderr, "ERROR: realpath(%s) failed. %s\n", tomnt,
931                         strerror(-ret));
932                 goto out;
933         }
934         r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
935         if (r->dest_dir_fd < 0) {
936                 ret = -errno;
937                 fprintf(stderr,
938                         "ERROR: failed to open destination directory %s. %s\n",
939                         dest_dir_full_path, strerror(-ret));
940                 goto out;
941         }
942
943         if (realmnt) {
944                 r->root_path = realmnt;
945         } else {
946                 ret = find_mount_root(dest_dir_full_path, &r->root_path);
947                 if (ret < 0) {
948                         fprintf(stderr,
949                                 "ERROR: failed to determine mount point for %s: %s\n",
950                                 dest_dir_full_path, strerror(-ret));
951                         ret = -EINVAL;
952                         goto out;
953                 }
954                 if (ret > 0) {
955                         fprintf(stderr,
956                         "ERROR: %s doesn't belong to btrfs mount point\n",
957                         dest_dir_full_path);
958                         ret = -EINVAL;
959                         goto out;
960                 }
961         }
962         r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
963         if (r->mnt_fd < 0) {
964                 ret = -errno;
965                 fprintf(stderr, "ERROR: failed to open %s. %s\n", r->root_path,
966                         strerror(-ret));
967                 goto out;
968         }
969
970         /*
971          * If we use -m or a default subvol we want to resolve the path to the
972          * subvolume we're sitting in so that we can adjust the paths of any
973          * subvols we want to receive in.
974          */
975         ret = btrfs_list_get_path_rootid(r->mnt_fd, &subvol_id);
976         if (ret) {
977                 fprintf(stderr, "ERROR: couldn't resolve our subvolid %d\n",
978                         ret);
979                 goto out;
980         }
981
982         root_subvol_path = malloc(PATH_MAX);
983         if (!root_subvol_path) {
984                 ret = -ENOMEM;
985                 fprintf(stderr, "ERROR: couldn't allocate buffer for the root "
986                         "subvol path\n");
987                 goto out;
988         }
989
990         ret = btrfs_subvolid_resolve(r->mnt_fd, root_subvol_path,
991                                      PATH_MAX, subvol_id);
992         if (ret) {
993                 fprintf(stderr, "ERROR: couldn't resolve our subvol path\n");
994                 goto out;
995         }
996
997         /*
998          * Ok we're inside of a subvol off of the root subvol, we need to
999          * actually set full_root_path.
1000          */
1001         if (strlen(root_subvol_path))
1002                 r->full_root_path = root_subvol_path;
1003         else
1004                 free(root_subvol_path);
1005
1006         if (r->dest_dir_chroot) {
1007                 if (chroot(dest_dir_full_path)) {
1008                         ret = -errno;
1009                         fprintf(stderr,
1010                                 "ERROR: failed to chroot to %s, %s\n",
1011                                 dest_dir_full_path,
1012                                 strerror(-ret));
1013                         goto out;
1014                 }
1015                 if (chdir("/")) {
1016                         ret = -errno;
1017                         fprintf(stderr,
1018                                 "ERROR: failed to chdir to /, %s\n",
1019                                 strerror(-ret));
1020                         goto out;
1021                 }
1022                 fprintf(stderr, "Chroot to %s\n", dest_dir_full_path);
1023                 r->root_path = strdup("/");
1024                 r->dest_dir_path = r->root_path;
1025         } else {
1026                 /*
1027                  * find_mount_root returns a root_path that is a subpath of
1028                  * dest_dir_full_path. Now get the other part of root_path,
1029                  * which is the destination dir relative to root_path.
1030                  */
1031                 r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
1032                 while (r->dest_dir_path[0] == '/')
1033                         r->dest_dir_path++;
1034         }
1035
1036         ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
1037         if (ret < 0)
1038                 goto out;
1039
1040         while (!end) {
1041                 if (r->cached_capabilities_len) {
1042                         if (g_verbose >= 3)
1043                                 fprintf(stderr, "clear cached capabilities\n");
1044                         memset(r->cached_capabilities, 0,
1045                                         sizeof(r->cached_capabilities));
1046                         r->cached_capabilities_len = 0;
1047                 }
1048
1049                 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
1050                                                          r->honor_end_cmd,
1051                                                          max_errors);
1052                 if (ret < 0)
1053                         goto out;
1054                 if (ret)
1055                         end = 1;
1056
1057                 close_inode_for_write(r);
1058                 ret = finish_subvol(r);
1059                 if (ret < 0)
1060                         goto out;
1061         }
1062         ret = 0;
1063
1064 out:
1065         if (r->write_fd != -1) {
1066                 close(r->write_fd);
1067                 r->write_fd = -1;
1068         }
1069         free(r->root_path);
1070         r->root_path = NULL;
1071         free(r->write_path);
1072         r->write_path = NULL;
1073         free(r->full_subvol_path);
1074         r->full_subvol_path = NULL;
1075         r->dest_dir_path = NULL;
1076         free(dest_dir_full_path);
1077         if (r->cur_subvol) {
1078                 free(r->cur_subvol->path);
1079                 free(r->cur_subvol);
1080                 r->cur_subvol = NULL;
1081         }
1082         subvol_uuid_search_finit(&r->sus);
1083         if (r->mnt_fd != -1) {
1084                 close(r->mnt_fd);
1085                 r->mnt_fd = -1;
1086         }
1087         if (r->dest_dir_fd != -1) {
1088                 close(r->dest_dir_fd);
1089                 r->dest_dir_fd = -1;
1090         }
1091         if (r->full_root_path) {
1092                 free(r->full_root_path);
1093                 r->full_root_path = NULL;
1094         }
1095         return ret;
1096 }
1097
1098 int cmd_receive(int argc, char **argv)
1099 {
1100         char *tomnt = NULL;
1101         char *fromfile = NULL;
1102         char *realmnt = NULL;
1103         struct btrfs_receive r;
1104         int receive_fd = fileno(stdin);
1105         u64 max_errors = 1;
1106         int ret = 0;
1107
1108         memset(&r, 0, sizeof(r));
1109         r.mnt_fd = -1;
1110         r.write_fd = -1;
1111         r.dest_dir_fd = -1;
1112         r.dest_dir_chroot = 0;
1113
1114         while (1) {
1115                 int c;
1116                 static const struct option long_opts[] = {
1117                         { "max-errors", required_argument, NULL, 'E' },
1118                         { "chroot", no_argument, NULL, 'C' },
1119                         { NULL, 0, NULL, 0 }
1120                 };
1121
1122                 c = getopt_long(argc, argv, "Cevf:m:", long_opts, NULL);
1123                 if (c < 0)
1124                         break;
1125
1126                 switch (c) {
1127                 case 'v':
1128                         g_verbose++;
1129                         break;
1130                 case 'f':
1131                         fromfile = optarg;
1132                         break;
1133                 case 'e':
1134                         r.honor_end_cmd = 1;
1135                         break;
1136                 case 'C':
1137                         r.dest_dir_chroot = 1;
1138                         break;
1139                 case 'E':
1140                         max_errors = arg_strtou64(optarg);
1141                         break;
1142                 case 'm':
1143                         free(realmnt);
1144                         realmnt = strdup(optarg);
1145                         if (!realmnt) {
1146                                 fprintf(stderr, "ERROR: couldn't allocate realmnt.\n");
1147                                 goto out;
1148                         }
1149                         break;
1150                 case '?':
1151                 default:
1152                         fprintf(stderr, "ERROR: receive args invalid.\n");
1153                         return 1;
1154                 }
1155         }
1156
1157         if (check_argc_exact(argc - optind, 1))
1158                 usage(cmd_receive_usage);
1159
1160         tomnt = argv[optind];
1161
1162         if (fromfile) {
1163                 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
1164                 if (receive_fd < 0) {
1165                         fprintf(stderr, "ERROR: failed to open %s\n", fromfile);
1166                         goto out;
1167                 }
1168         }
1169
1170         ret = do_receive(&r, tomnt, realmnt, receive_fd, max_errors);
1171
1172 out:
1173         free(realmnt);
1174
1175         return !!ret;
1176 }
1177
1178 const char * const cmd_receive_usage[] = {
1179         "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
1180         "Receive subvolumes from stdin.",
1181         "Receives one or more subvolumes that were previously",
1182         "sent with btrfs send. The received subvolumes are stored",
1183         "into <mount>.",
1184         "btrfs receive will fail in case a receiving subvolume",
1185         "already exists. It will also fail in case a previously",
1186         "received subvolume was changed after it was received.",
1187         "After receiving a subvolume, it is immediately set to",
1188         "read only.\n",
1189         "-v               Enable verbose debug output. Each",
1190         "                 occurrence of this option increases the",
1191         "                 verbose level more.",
1192         "-f <infile>      By default, btrfs receive uses stdin",
1193         "                 to receive the subvolumes. Use this",
1194         "                 option to specify a file to use instead.",
1195         "-e               Terminate after receiving an <end cmd>",
1196         "                 in the data stream. Without this option,",
1197         "                 the receiver terminates only if an error",
1198         "                 is recognized or on EOF.",
1199         "-C|--chroot      confine the process to <mount> using chroot",
1200         "--max-errors <N> Terminate as soon as N errors happened while",
1201         "                 processing commands from the send stream.",
1202         "                 Default value is 1. A value of 0 means no limit.",
1203         "-m <mountpoint>  The root mount point of the destination fs.",
1204         "                 If you do not have /proc use this to tell us where ",
1205         "                 this file system is mounted.",
1206         NULL
1207 };