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