Btrfs-progs: make debug-tree spit out full_backref flag
[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
65         struct subvol_info *cur_subvol;
66
67         struct subvol_uuid_search sus;
68
69         int honor_end_cmd;
70 };
71
72 static int finish_subvol(struct btrfs_receive *r)
73 {
74         int ret;
75         int subvol_fd = -1;
76         struct btrfs_ioctl_received_subvol_args rs_args;
77         char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
78         u64 flags;
79
80         if (r->cur_subvol == NULL)
81                 return 0;
82
83         subvol_fd = openat(r->mnt_fd, r->cur_subvol->path,
84                         O_RDONLY | O_NOATIME);
85         if (subvol_fd < 0) {
86                 ret = -errno;
87                 fprintf(stderr, "ERROR: open %s failed. %s\n",
88                                 r->cur_subvol->path, strerror(-ret));
89                 goto out;
90         }
91
92         memset(&rs_args, 0, sizeof(rs_args));
93         memcpy(rs_args.uuid, r->cur_subvol->received_uuid, BTRFS_UUID_SIZE);
94         rs_args.stransid = r->cur_subvol->stransid;
95
96         if (g_verbose >= 1) {
97                 uuid_unparse((u8*)rs_args.uuid, uuid_str);
98                 fprintf(stderr, "BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=%s, "
99                                 "stransid=%llu\n", uuid_str, rs_args.stransid);
100         }
101
102         ret = ioctl(subvol_fd, BTRFS_IOC_SET_RECEIVED_SUBVOL, &rs_args);
103         if (ret < 0) {
104                 ret = -errno;
105                 fprintf(stderr, "ERROR: BTRFS_IOC_SET_RECEIVED_SUBVOL failed. %s\n",
106                                 strerror(-ret));
107                 goto out;
108         }
109         r->cur_subvol->rtransid = rs_args.rtransid;
110
111         ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags);
112         if (ret < 0) {
113                 ret = -errno;
114                 fprintf(stderr, "ERROR: BTRFS_IOC_SUBVOL_GETFLAGS failed. %s\n",
115                                 strerror(-ret));
116                 goto out;
117         }
118
119         flags |= BTRFS_SUBVOL_RDONLY;
120
121         ret = ioctl(subvol_fd, BTRFS_IOC_SUBVOL_SETFLAGS, &flags);
122         if (ret < 0) {
123                 ret = -errno;
124                 fprintf(stderr, "ERROR: failed to make subvolume read only. "
125                                 "%s\n", strerror(-ret));
126                 goto out;
127         }
128
129         ret = 0;
130
131 out:
132         if (r->cur_subvol) {
133                 free(r->cur_subvol->path);
134                 free(r->cur_subvol);
135                 r->cur_subvol = NULL;
136         }
137         if (subvol_fd != -1)
138                 close(subvol_fd);
139         return ret;
140 }
141
142 static int process_subvol(const char *path, const u8 *uuid, u64 ctransid,
143                           void *user)
144 {
145         int ret;
146         struct btrfs_receive *r = user;
147         struct btrfs_ioctl_vol_args args_v1;
148         char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
149
150         ret = finish_subvol(r);
151         if (ret < 0)
152                 goto out;
153
154         r->cur_subvol = calloc(1, sizeof(*r->cur_subvol));
155
156         if (strlen(r->dest_dir_path) == 0)
157                 r->cur_subvol->path = strdup(path);
158         else
159                 r->cur_subvol->path = path_cat(r->dest_dir_path, path);
160         free(r->full_subvol_path);
161         r->full_subvol_path = path_cat3(r->root_path, r->dest_dir_path, path);
162
163         fprintf(stderr, "At subvol %s\n", path);
164
165         memcpy(r->cur_subvol->received_uuid, uuid, BTRFS_UUID_SIZE);
166         r->cur_subvol->stransid = ctransid;
167
168         if (g_verbose) {
169                 uuid_unparse((u8*)r->cur_subvol->received_uuid, uuid_str);
170                 fprintf(stderr, "receiving subvol %s uuid=%s, stransid=%llu\n",
171                                 path, uuid_str,
172                                 r->cur_subvol->stransid);
173         }
174
175         memset(&args_v1, 0, sizeof(args_v1));
176         strncpy_null(args_v1.name, path);
177         ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SUBVOL_CREATE, &args_v1);
178         if (ret < 0) {
179                 ret = -errno;
180                 fprintf(stderr, "ERROR: creating subvolume %s failed. "
181                                 "%s\n", path, strerror(-ret));
182                 goto out;
183         }
184
185 out:
186         return ret;
187 }
188
189 static int process_snapshot(const char *path, const u8 *uuid, u64 ctransid,
190                             const u8 *parent_uuid, u64 parent_ctransid,
191                             void *user)
192 {
193         int ret;
194         struct btrfs_receive *r = user;
195         char uuid_str[BTRFS_UUID_UNPARSED_SIZE];
196         struct btrfs_ioctl_vol_args_v2 args_v2;
197         struct subvol_info *parent_subvol = NULL;
198
199         ret = finish_subvol(r);
200         if (ret < 0)
201                 goto out;
202
203         r->cur_subvol = calloc(1, sizeof(*r->cur_subvol));
204
205         if (strlen(r->dest_dir_path) == 0)
206                 r->cur_subvol->path = strdup(path);
207         else
208                 r->cur_subvol->path = path_cat(r->dest_dir_path, path);
209         free(r->full_subvol_path);
210         r->full_subvol_path = path_cat3(r->root_path, r->dest_dir_path, path);
211
212         fprintf(stdout, "At snapshot %s\n", path);
213
214         memcpy(r->cur_subvol->received_uuid, uuid, BTRFS_UUID_SIZE);
215         r->cur_subvol->stransid = ctransid;
216
217         if (g_verbose) {
218                 uuid_unparse((u8*)r->cur_subvol->received_uuid, uuid_str);
219                 fprintf(stderr, "receiving snapshot %s uuid=%s, "
220                                 "ctransid=%llu ", path, uuid_str,
221                                 r->cur_subvol->stransid);
222                 uuid_unparse(parent_uuid, uuid_str);
223                 fprintf(stderr, "parent_uuid=%s, parent_ctransid=%llu\n",
224                                 uuid_str, parent_ctransid);
225         }
226
227         memset(&args_v2, 0, sizeof(args_v2));
228         strncpy_null(args_v2.name, path);
229
230         parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
231                         parent_ctransid, NULL, subvol_search_by_received_uuid);
232         if (!parent_subvol) {
233                 parent_subvol = subvol_uuid_search(&r->sus, 0, parent_uuid,
234                                 parent_ctransid, NULL, subvol_search_by_uuid);
235         }
236         if (!parent_subvol) {
237                 ret = -ENOENT;
238                 fprintf(stderr, "ERROR: could not find parent subvolume\n");
239                 goto out;
240         }
241
242         /*if (rs_args.ctransid > rs_args.rtransid) {
243                 if (!r->force) {
244                         ret = -EINVAL;
245                         fprintf(stderr, "ERROR: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
246                         goto out;
247                 } else {
248                         fprintf(stderr, "WARNING: subvolume %s was modified after it was received.\n", r->subvol_parent_name);
249                 }
250         }*/
251
252         args_v2.fd = openat(r->mnt_fd, parent_subvol->path,
253                         O_RDONLY | O_NOATIME);
254         if (args_v2.fd < 0) {
255                 ret = -errno;
256                 if (errno != ENOENT)
257                         fprintf(stderr, "ERROR: open %s failed. %s\n",
258                                         parent_subvol->path, strerror(-ret));
259                 else
260                         fprintf(stderr,
261                                 "It seems that you have changed your default "
262                                 "subvolume or you specify other subvolume to\n"
263                                 "mount btrfs, try to remount this btrfs filesystem "
264                                 "with fs tree, and run btrfs receive again!\n");
265                 goto out;
266         }
267
268         ret = ioctl(r->dest_dir_fd, BTRFS_IOC_SNAP_CREATE_V2, &args_v2);
269         close(args_v2.fd);
270         if (ret < 0) {
271                 ret = -errno;
272                 fprintf(stderr, "ERROR: creating snapshot %s -> %s "
273                                 "failed. %s\n", parent_subvol->path,
274                                 path, strerror(-ret));
275                 goto out;
276         }
277
278 out:
279         if (parent_subvol) {
280                 free(parent_subvol->path);
281                 free(parent_subvol);
282         }
283         return ret;
284 }
285
286 static int process_mkfile(const char *path, void *user)
287 {
288         int ret;
289         struct btrfs_receive *r = user;
290         char *full_path = path_cat(r->full_subvol_path, path);
291
292         if (g_verbose >= 2)
293                 fprintf(stderr, "mkfile %s\n", path);
294
295         ret = creat(full_path, 0600);
296         if (ret < 0) {
297                 ret = -errno;
298                 fprintf(stderr, "ERROR: mkfile %s failed. %s\n", path,
299                                 strerror(-ret));
300                 goto out;
301         }
302         close(ret);
303         ret = 0;
304
305 out:
306         free(full_path);
307         return ret;
308 }
309
310 static int process_mkdir(const char *path, void *user)
311 {
312         int ret;
313         struct btrfs_receive *r = user;
314         char *full_path = path_cat(r->full_subvol_path, path);
315
316         if (g_verbose >= 2)
317                 fprintf(stderr, "mkdir %s\n", path);
318
319         ret = mkdir(full_path, 0700);
320         if (ret < 0) {
321                 ret = -errno;
322                 fprintf(stderr, "ERROR: mkdir %s failed. %s\n", path,
323                                 strerror(-ret));
324         }
325
326         free(full_path);
327         return ret;
328 }
329
330 static int process_mknod(const char *path, u64 mode, u64 dev, void *user)
331 {
332         int ret;
333         struct btrfs_receive *r = user;
334         char *full_path = path_cat(r->full_subvol_path, path);
335
336         if (g_verbose >= 2)
337                 fprintf(stderr, "mknod %s mode=%llu, dev=%llu\n",
338                                 path, mode, dev);
339
340         ret = mknod(full_path, mode & S_IFMT, dev);
341         if (ret < 0) {
342                 ret = -errno;
343                 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
344                                 strerror(-ret));
345         }
346
347         free(full_path);
348         return ret;
349 }
350
351 static int process_mkfifo(const char *path, void *user)
352 {
353         int ret;
354         struct btrfs_receive *r = user;
355         char *full_path = path_cat(r->full_subvol_path, path);
356
357         if (g_verbose >= 2)
358                 fprintf(stderr, "mkfifo %s\n", path);
359
360         ret = mkfifo(full_path, 0600);
361         if (ret < 0) {
362                 ret = -errno;
363                 fprintf(stderr, "ERROR: mkfifo %s failed. %s\n", path,
364                                 strerror(-ret));
365         }
366
367         free(full_path);
368         return ret;
369 }
370
371 static int process_mksock(const char *path, void *user)
372 {
373         int ret;
374         struct btrfs_receive *r = user;
375         char *full_path = path_cat(r->full_subvol_path, path);
376
377         if (g_verbose >= 2)
378                 fprintf(stderr, "mksock %s\n", path);
379
380         ret = mknod(full_path, 0600 | S_IFSOCK, 0);
381         if (ret < 0) {
382                 ret = -errno;
383                 fprintf(stderr, "ERROR: mknod %s failed. %s\n", path,
384                                 strerror(-ret));
385         }
386
387         free(full_path);
388         return ret;
389 }
390
391 static int process_symlink(const char *path, const char *lnk, void *user)
392 {
393         int ret;
394         struct btrfs_receive *r = user;
395         char *full_path = path_cat(r->full_subvol_path, path);
396
397         if (g_verbose >= 2)
398                 fprintf(stderr, "symlink %s -> %s\n", path, lnk);
399
400         ret = symlink(lnk, full_path);
401         if (ret < 0) {
402                 ret = -errno;
403                 fprintf(stderr, "ERROR: symlink %s -> %s failed. %s\n", path,
404                                 lnk, strerror(-ret));
405         }
406
407         free(full_path);
408         return ret;
409 }
410
411 static int process_rename(const char *from, const char *to, void *user)
412 {
413         int ret;
414         struct btrfs_receive *r = user;
415         char *full_from = path_cat(r->full_subvol_path, from);
416         char *full_to = path_cat(r->full_subvol_path, to);
417
418         if (g_verbose >= 2)
419                 fprintf(stderr, "rename %s -> %s\n", from, to);
420
421         ret = rename(full_from, full_to);
422         if (ret < 0) {
423                 ret = -errno;
424                 fprintf(stderr, "ERROR: rename %s -> %s failed. %s\n", from,
425                                 to, strerror(-ret));
426         }
427
428         free(full_from);
429         free(full_to);
430         return ret;
431 }
432
433 static int process_link(const char *path, const char *lnk, void *user)
434 {
435         int ret;
436         struct btrfs_receive *r = user;
437         char *full_path = path_cat(r->full_subvol_path, path);
438         char *full_link_path = path_cat(r->full_subvol_path, lnk);
439
440         if (g_verbose >= 2)
441                 fprintf(stderr, "link %s -> %s\n", path, lnk);
442
443         ret = link(full_link_path, full_path);
444         if (ret < 0) {
445                 ret = -errno;
446                 fprintf(stderr, "ERROR: link %s -> %s failed. %s\n", path,
447                                 lnk, strerror(-ret));
448         }
449
450         free(full_path);
451         free(full_link_path);
452         return ret;
453 }
454
455
456 static int process_unlink(const char *path, void *user)
457 {
458         int ret;
459         struct btrfs_receive *r = user;
460         char *full_path = path_cat(r->full_subvol_path, path);
461
462         if (g_verbose >= 2)
463                 fprintf(stderr, "unlink %s\n", path);
464
465         ret = unlink(full_path);
466         if (ret < 0) {
467                 ret = -errno;
468                 fprintf(stderr, "ERROR: unlink %s failed. %s\n", path,
469                                 strerror(-ret));
470         }
471
472         free(full_path);
473         return ret;
474 }
475
476 static int process_rmdir(const char *path, void *user)
477 {
478         int ret;
479         struct btrfs_receive *r = user;
480         char *full_path = path_cat(r->full_subvol_path, path);
481
482         if (g_verbose >= 2)
483                 fprintf(stderr, "rmdir %s\n", path);
484
485         ret = rmdir(full_path);
486         if (ret < 0) {
487                 ret = -errno;
488                 fprintf(stderr, "ERROR: rmdir %s failed. %s\n", path,
489                                 strerror(-ret));
490         }
491
492         free(full_path);
493         return ret;
494 }
495
496
497 static int open_inode_for_write(struct btrfs_receive *r, const char *path)
498 {
499         int ret = 0;
500
501         if (r->write_fd != -1) {
502                 if (strcmp(r->write_path, path) == 0)
503                         goto out;
504                 close(r->write_fd);
505                 r->write_fd = -1;
506         }
507
508         r->write_fd = open(path, O_RDWR);
509         if (r->write_fd < 0) {
510                 ret = -errno;
511                 fprintf(stderr, "ERROR: open %s failed. %s\n", path,
512                                 strerror(-ret));
513                 goto out;
514         }
515         free(r->write_path);
516         r->write_path = strdup(path);
517
518 out:
519         return ret;
520 }
521
522 static void close_inode_for_write(struct btrfs_receive *r)
523 {
524         if(r->write_fd == -1)
525                 return;
526
527         close(r->write_fd);
528         r->write_fd = -1;
529         r->write_path[0] = 0;
530 }
531
532 static int process_write(const char *path, const void *data, u64 offset,
533                          u64 len, void *user)
534 {
535         int ret = 0;
536         struct btrfs_receive *r = user;
537         char *full_path = path_cat(r->full_subvol_path, path);
538         u64 pos = 0;
539         int w;
540
541         ret = open_inode_for_write(r, full_path);
542         if (ret < 0)
543                 goto out;
544
545         while (pos < len) {
546                 w = pwrite(r->write_fd, (char*)data + pos, len - pos,
547                                 offset + pos);
548                 if (w < 0) {
549                         ret = -errno;
550                         fprintf(stderr, "ERROR: writing to %s failed. %s\n",
551                                         path, strerror(-ret));
552                         goto out;
553                 }
554                 pos += w;
555         }
556
557 out:
558         free(full_path);
559         return ret;
560 }
561
562 static int process_clone(const char *path, u64 offset, u64 len,
563                          const u8 *clone_uuid, u64 clone_ctransid,
564                          const char *clone_path, u64 clone_offset,
565                          void *user)
566 {
567         int ret;
568         struct btrfs_receive *r = user;
569         struct btrfs_ioctl_clone_range_args clone_args;
570         struct subvol_info *si = NULL;
571         char *full_path = path_cat(r->full_subvol_path, path);
572         char *subvol_path = NULL;
573         char *full_clone_path = NULL;
574         int clone_fd = -1;
575
576         ret = open_inode_for_write(r, full_path);
577         if (ret < 0)
578                 goto out;
579
580         si = subvol_uuid_search(&r->sus, 0, clone_uuid, clone_ctransid, NULL,
581                         subvol_search_by_received_uuid);
582         if (!si) {
583                 if (memcmp(clone_uuid, r->cur_subvol->received_uuid,
584                                 BTRFS_UUID_SIZE) == 0) {
585                         /* TODO check generation of extent */
586                         subvol_path = strdup(r->cur_subvol->path);
587                 } else {
588                         ret = -ENOENT;
589                         fprintf(stderr, "ERROR: did not find source subvol.\n");
590                         goto out;
591                 }
592         } else {
593                 /*if (rs_args.ctransid > rs_args.rtransid) {
594                         if (!r->force) {
595                                 ret = -EINVAL;
596                                 fprintf(stderr, "ERROR: subvolume %s was "
597                                                 "modified after it was "
598                                                 "received.\n",
599                                                 r->subvol_parent_name);
600                                 goto out;
601                         } else {
602                                 fprintf(stderr, "WARNING: subvolume %s was "
603                                                 "modified after it was "
604                                                 "received.\n",
605                                                 r->subvol_parent_name);
606                         }
607                 }*/
608                 subvol_path = strdup(si->path);
609         }
610
611         full_clone_path = path_cat3(r->root_path, subvol_path, clone_path);
612
613         clone_fd = open(full_clone_path, O_RDONLY | O_NOATIME);
614         if (clone_fd < 0) {
615                 ret = -errno;
616                 fprintf(stderr, "ERROR: failed to open %s. %s\n",
617                                 full_clone_path, strerror(-ret));
618                 goto out;
619         }
620
621         clone_args.src_fd = clone_fd;
622         clone_args.src_offset = clone_offset;
623         clone_args.src_length = len;
624         clone_args.dest_offset = offset;
625         ret = ioctl(r->write_fd, BTRFS_IOC_CLONE_RANGE, &clone_args);
626         if (ret) {
627                 ret = -errno;
628                 fprintf(stderr, "ERROR: failed to clone extents to %s\n%s\n",
629                                 path, strerror(-ret));
630                 goto out;
631         }
632
633 out:
634         if (si) {
635                 free(si->path);
636                 free(si);
637         }
638         free(full_path);
639         free(full_clone_path);
640         free(subvol_path);
641         if (clone_fd != -1)
642                 close(clone_fd);
643         return ret;
644 }
645
646
647 static int process_set_xattr(const char *path, const char *name,
648                              const void *data, int len, void *user)
649 {
650         int ret = 0;
651         struct btrfs_receive *r = user;
652         char *full_path = path_cat(r->full_subvol_path, path);
653
654         if (g_verbose >= 2) {
655                 fprintf(stderr, "set_xattr %s - name=%s data_len=%d "
656                                 "data=%.*s\n", path, name, len,
657                                 len, (char*)data);
658         }
659
660         ret = lsetxattr(full_path, name, data, len, 0);
661         if (ret < 0) {
662                 ret = -errno;
663                 fprintf(stderr, "ERROR: lsetxattr %s %s=%.*s failed. %s\n",
664                                 path, name, len, (char*)data, strerror(-ret));
665                 goto out;
666         }
667
668 out:
669         free(full_path);
670         return ret;
671 }
672
673 static int process_remove_xattr(const char *path, const char *name, void *user)
674 {
675         int ret = 0;
676         struct btrfs_receive *r = user;
677         char *full_path = path_cat(r->full_subvol_path, path);
678
679         if (g_verbose >= 2) {
680                 fprintf(stderr, "remove_xattr %s - name=%s\n",
681                                 path, name);
682         }
683
684         ret = lremovexattr(full_path, name);
685         if (ret < 0) {
686                 ret = -errno;
687                 fprintf(stderr, "ERROR: lremovexattr %s %s failed. %s\n",
688                                 path, name, strerror(-ret));
689                 goto out;
690         }
691
692 out:
693         free(full_path);
694         return ret;
695 }
696
697 static int process_truncate(const char *path, u64 size, void *user)
698 {
699         int ret = 0;
700         struct btrfs_receive *r = user;
701         char *full_path = path_cat(r->full_subvol_path, path);
702
703         if (g_verbose >= 2)
704                 fprintf(stderr, "truncate %s size=%llu\n", path, size);
705
706         ret = truncate(full_path, size);
707         if (ret < 0) {
708                 ret = -errno;
709                 fprintf(stderr, "ERROR: truncate %s failed. %s\n",
710                                 path, strerror(-ret));
711                 goto out;
712         }
713
714 out:
715         free(full_path);
716         return ret;
717 }
718
719 static int process_chmod(const char *path, u64 mode, void *user)
720 {
721         int ret = 0;
722         struct btrfs_receive *r = user;
723         char *full_path = path_cat(r->full_subvol_path, path);
724
725         if (g_verbose >= 2)
726                 fprintf(stderr, "chmod %s - mode=0%o\n", path, (int)mode);
727
728         ret = chmod(full_path, mode);
729         if (ret < 0) {
730                 ret = -errno;
731                 fprintf(stderr, "ERROR: chmod %s failed. %s\n",
732                                 path, strerror(-ret));
733                 goto out;
734         }
735
736 out:
737         free(full_path);
738         return ret;
739 }
740
741 static int process_chown(const char *path, u64 uid, u64 gid, void *user)
742 {
743         int ret = 0;
744         struct btrfs_receive *r = user;
745         char *full_path = path_cat(r->full_subvol_path, path);
746
747         if (g_verbose >= 2)
748                 fprintf(stderr, "chown %s - uid=%llu, gid=%llu\n", path,
749                                 uid, gid);
750
751         ret = lchown(full_path, uid, gid);
752         if (ret < 0) {
753                 ret = -errno;
754                 fprintf(stderr, "ERROR: chown %s failed. %s\n",
755                                 path, strerror(-ret));
756                 goto out;
757         }
758
759 out:
760         free(full_path);
761         return ret;
762 }
763
764 static int process_utimes(const char *path, struct timespec *at,
765                           struct timespec *mt, struct timespec *ct,
766                           void *user)
767 {
768         int ret = 0;
769         struct btrfs_receive *r = user;
770         char *full_path = path_cat(r->full_subvol_path, path);
771         struct timespec tv[2];
772
773         if (g_verbose >= 2)
774                 fprintf(stderr, "utimes %s\n", path);
775
776         tv[0] = *at;
777         tv[1] = *mt;
778         ret = utimensat(AT_FDCWD, full_path, tv, AT_SYMLINK_NOFOLLOW);
779         if (ret < 0) {
780                 ret = -errno;
781                 fprintf(stderr, "ERROR: utimes %s failed. %s\n",
782                                 path, strerror(-ret));
783                 goto out;
784         }
785
786 out:
787         free(full_path);
788         return ret;
789 }
790
791
792 static struct btrfs_send_ops send_ops = {
793         .subvol = process_subvol,
794         .snapshot = process_snapshot,
795         .mkfile = process_mkfile,
796         .mkdir = process_mkdir,
797         .mknod = process_mknod,
798         .mkfifo = process_mkfifo,
799         .mksock = process_mksock,
800         .symlink = process_symlink,
801         .rename = process_rename,
802         .link = process_link,
803         .unlink = process_unlink,
804         .rmdir = process_rmdir,
805         .write = process_write,
806         .clone = process_clone,
807         .set_xattr = process_set_xattr,
808         .remove_xattr = process_remove_xattr,
809         .truncate = process_truncate,
810         .chmod = process_chmod,
811         .chown = process_chown,
812         .utimes = process_utimes,
813 };
814
815 static int do_receive(struct btrfs_receive *r, const char *tomnt, int r_fd,
816                       u64 max_errors)
817 {
818         int ret;
819         char *dest_dir_full_path;
820         int end = 0;
821
822         dest_dir_full_path = realpath(tomnt, NULL);
823         if (!dest_dir_full_path) {
824                 ret = -errno;
825                 fprintf(stderr, "ERROR: realpath(%s) failed. %s\n", tomnt,
826                         strerror(-ret));
827                 goto out;
828         }
829         r->dest_dir_fd = open(dest_dir_full_path, O_RDONLY | O_NOATIME);
830         if (r->dest_dir_fd < 0) {
831                 ret = -errno;
832                 fprintf(stderr,
833                         "ERROR: failed to open destination directory %s. %s\n",
834                         dest_dir_full_path, strerror(-ret));
835                 goto out;
836         }
837
838         ret = find_mount_root(dest_dir_full_path, &r->root_path);
839         if (ret < 0) {
840                 fprintf(stderr,
841                         "ERROR: failed to determine mount point for %s: %s\n",
842                         dest_dir_full_path, strerror(-ret));
843                 ret = -EINVAL;
844                 goto out;
845         }
846         if (ret > 0) {
847                 fprintf(stderr,
848                         "ERROR: %s doesn't belong to btrfs mount point\n",
849                         dest_dir_full_path);
850                 ret = -EINVAL;
851                 goto out;
852         }
853         r->mnt_fd = open(r->root_path, O_RDONLY | O_NOATIME);
854         if (r->mnt_fd < 0) {
855                 ret = -errno;
856                 fprintf(stderr, "ERROR: failed to open %s. %s\n", r->root_path,
857                         strerror(-ret));
858                 goto out;
859         }
860
861         /*
862          * find_mount_root returns a root_path that is a subpath of
863          * dest_dir_full_path. Now get the other part of root_path,
864          * which is the destination dir relative to root_path.
865          */
866         r->dest_dir_path = dest_dir_full_path + strlen(r->root_path);
867         while (r->dest_dir_path[0] == '/')
868                 r->dest_dir_path++;
869
870         ret = subvol_uuid_search_init(r->mnt_fd, &r->sus);
871         if (ret < 0)
872                 goto out;
873
874         while (!end) {
875                 ret = btrfs_read_and_process_send_stream(r_fd, &send_ops, r,
876                                                          r->honor_end_cmd,
877                                                          max_errors);
878                 if (ret < 0)
879                         goto out;
880                 if (ret)
881                         end = 1;
882
883                 close_inode_for_write(r);
884                 ret = finish_subvol(r);
885                 if (ret < 0)
886                         goto out;
887         }
888         ret = 0;
889
890 out:
891         if (r->write_fd != -1) {
892                 close(r->write_fd);
893                 r->write_fd = -1;
894         }
895         free(r->root_path);
896         r->root_path = NULL;
897         free(r->write_path);
898         r->write_path = NULL;
899         free(r->full_subvol_path);
900         r->full_subvol_path = NULL;
901         r->dest_dir_path = NULL;
902         free(dest_dir_full_path);
903         if (r->cur_subvol) {
904                 free(r->cur_subvol->path);
905                 free(r->cur_subvol);
906                 r->cur_subvol = NULL;
907         }
908         subvol_uuid_search_finit(&r->sus);
909         if (r->mnt_fd != -1) {
910                 close(r->mnt_fd);
911                 r->mnt_fd = -1;
912         }
913         if (r->dest_dir_fd != -1) {
914                 close(r->dest_dir_fd);
915                 r->dest_dir_fd = -1;
916         }
917         return ret;
918 }
919
920 int cmd_receive(int argc, char **argv)
921 {
922         char *tomnt = NULL;
923         char *fromfile = NULL;
924         struct btrfs_receive r;
925         int receive_fd = fileno(stdin);
926         u64 max_errors = 1;
927         int ret;
928
929         memset(&r, 0, sizeof(r));
930         r.mnt_fd = -1;
931         r.write_fd = -1;
932         r.dest_dir_fd = -1;
933
934         while (1) {
935                 int c;
936                 static const struct option long_opts[] = {
937                         { "max-errors", 1, NULL, 'E' },
938                         { NULL, 0, NULL, 0 }
939                 };
940
941                 c = getopt_long(argc, argv, "evf:", long_opts, NULL);
942                 if (c < 0)
943                         break;
944
945                 switch (c) {
946                 case 'v':
947                         g_verbose++;
948                         break;
949                 case 'f':
950                         fromfile = optarg;
951                         break;
952                 case 'e':
953                         r.honor_end_cmd = 1;
954                         break;
955                 case 'E':
956                         max_errors = arg_strtou64(optarg);
957                         break;
958                 case '?':
959                 default:
960                         fprintf(stderr, "ERROR: receive args invalid.\n");
961                         return 1;
962                 }
963         }
964
965         if (check_argc_exact(argc - optind, 1))
966                 usage(cmd_receive_usage);
967
968         tomnt = argv[optind];
969
970         if (fromfile) {
971                 receive_fd = open(fromfile, O_RDONLY | O_NOATIME);
972                 if (receive_fd < 0) {
973                         fprintf(stderr, "ERROR: failed to open %s\n", fromfile);
974                         return 1;
975                 }
976         }
977
978         ret = do_receive(&r, tomnt, receive_fd, max_errors);
979
980         return !!ret;
981 }
982
983 const char * const cmd_receive_usage[] = {
984         "btrfs receive [-ve] [-f <infile>] [--max-errors <N>] <mount>",
985         "Receive subvolumes from stdin.",
986         "Receives one or more subvolumes that were previously",
987         "sent with btrfs send. The received subvolumes are stored",
988         "into <mount>.",
989         "btrfs receive will fail in case a receiving subvolume",
990         "already exists. It will also fail in case a previously",
991         "received subvolume was changed after it was received.",
992         "After receiving a subvolume, it is immediately set to",
993         "read only.\n",
994         "-v               Enable verbose debug output. Each",
995         "                 occurrence of this option increases the",
996         "                 verbose level more.",
997         "-f <infile>      By default, btrfs receive uses stdin",
998         "                 to receive the subvolumes. Use this",
999         "                 option to specify a file to use instead.",
1000         "-e               Terminate after receiving an <end cmd>",
1001         "                 in the data stream. Without this option,",
1002         "                 the receiver terminates only if an error",
1003         "                 is recognized or on EOF.",
1004         "--max-errors <N> Terminate as soon as N errors happened while",
1005         "                 processing commands from the send stream.",
1006         "                 Default value is 1. A value of 0 means no limit.",
1007         NULL
1008 };