2 * Copyright (C) 2011 Red Hat. All rights reserved.
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.
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.
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.
19 #define _XOPEN_SOURCE 500
22 #include "kerncompat.h"
30 #include <sys/types.h>
31 #include <lzo/lzoconf.h>
32 #include <lzo/lzo1x.h>
36 #include <sys/types.h>
37 #include <sys/xattr.h>
41 #include "print-tree.h"
42 #include "transaction.h"
49 static char fs_name
[4096];
50 static char path_name
[4096];
51 static int get_snaps
= 0;
52 static int verbose
= 0;
53 static int ignore_errors
= 0;
54 static int overwrite
= 0;
55 static int get_xattrs
= 0;
56 static int dry_run
= 0;
59 #define PAGE_CACHE_SIZE 4096
60 #define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
62 static int decompress_zlib(char *inbuf
, char *outbuf
, u64 compress_len
,
68 memset(&strm
, 0, sizeof(strm
));
69 ret
= inflateInit(&strm
);
71 fprintf(stderr
, "inflate init returnd %d\n", ret
);
75 strm
.avail_in
= compress_len
;
76 strm
.next_in
= (unsigned char *)inbuf
;
77 strm
.avail_out
= decompress_len
;
78 strm
.next_out
= (unsigned char *)outbuf
;
79 ret
= inflate(&strm
, Z_NO_FLUSH
);
80 if (ret
!= Z_STREAM_END
) {
81 (void)inflateEnd(&strm
);
82 fprintf(stderr
, "failed to inflate: %d\n", ret
);
86 (void)inflateEnd(&strm
);
89 static inline size_t read_compress_length(unsigned char *buf
)
92 memcpy(&dlen
, buf
, LZO_LEN
);
93 return le32_to_cpu(dlen
);
96 static int decompress_lzo(unsigned char *inbuf
, char *outbuf
, u64 compress_len
,
107 if (ret
!= LZO_E_OK
) {
108 fprintf(stderr
, "lzo init returned %d\n", ret
);
112 tot_len
= read_compress_length(inbuf
);
116 while (tot_in
< tot_len
) {
117 in_len
= read_compress_length(inbuf
);
121 new_len
= lzo1x_worst_compress(PAGE_CACHE_SIZE
);
122 ret
= lzo1x_decompress_safe((const unsigned char *)inbuf
, in_len
,
123 (unsigned char *)outbuf
,
124 (void *)&new_len
, NULL
);
125 if (ret
!= LZO_E_OK
) {
126 fprintf(stderr
, "failed to inflate: %d\n", ret
);
135 *decompress_len
= out_len
;
140 static int decompress(char *inbuf
, char *outbuf
, u64 compress_len
,
141 u64
*decompress_len
, int compress
)
144 case BTRFS_COMPRESS_ZLIB
:
145 return decompress_zlib(inbuf
, outbuf
, compress_len
,
147 case BTRFS_COMPRESS_LZO
:
148 return decompress_lzo((unsigned char *)inbuf
, outbuf
, compress_len
,
154 fprintf(stderr
, "invalid compression type: %d\n", compress
);
158 static int next_leaf(struct btrfs_root
*root
, struct btrfs_path
*path
)
163 struct extent_buffer
*c
;
164 struct extent_buffer
*next
= NULL
;
167 for (; level
< BTRFS_MAX_LEVEL
; level
++) {
168 if (path
->nodes
[level
])
172 if (level
== BTRFS_MAX_LEVEL
)
175 slot
= path
->slots
[level
] + 1;
177 while(level
< BTRFS_MAX_LEVEL
) {
178 if (!path
->nodes
[level
])
181 slot
= path
->slots
[level
] + offset
;
182 c
= path
->nodes
[level
];
183 if (slot
>= btrfs_header_nritems(c
)) {
185 if (level
== BTRFS_MAX_LEVEL
)
191 reada_for_search(root
, path
, level
, slot
, 0);
193 next
= read_node_slot(root
, c
, slot
);
198 path
->slots
[level
] = slot
;
201 c
= path
->nodes
[level
];
202 free_extent_buffer(c
);
203 path
->nodes
[level
] = next
;
204 path
->slots
[level
] = 0;
208 reada_for_search(root
, path
, level
, 0, 0);
209 next
= read_node_slot(root
, next
, 0);
216 static int copy_one_inline(int fd
, struct btrfs_path
*path
, u64 pos
)
218 struct extent_buffer
*leaf
= path
->nodes
[0];
219 struct btrfs_file_extent_item
*fi
;
229 fi
= btrfs_item_ptr(leaf
, path
->slots
[0],
230 struct btrfs_file_extent_item
);
231 ptr
= btrfs_file_extent_inline_start(fi
);
232 len
= btrfs_file_extent_inline_len(leaf
, path
->slots
[0], fi
);
233 read_extent_buffer(leaf
, buf
, ptr
, len
);
235 compress
= btrfs_file_extent_compression(leaf
, fi
);
236 if (compress
== BTRFS_COMPRESS_NONE
) {
237 done
= pwrite(fd
, buf
, len
, pos
);
239 fprintf(stderr
, "Short inline write, wanted %d, did "
240 "%zd: %d\n", len
, done
, errno
);
246 ram_size
= btrfs_file_extent_ram_bytes(leaf
, fi
);
247 outbuf
= malloc(ram_size
);
249 fprintf(stderr
, "No memory\n");
253 ret
= decompress(buf
, outbuf
, len
, &ram_size
, compress
);
259 done
= pwrite(fd
, outbuf
, ram_size
, pos
);
261 if (done
< ram_size
) {
262 fprintf(stderr
, "Short compressed inline write, wanted %Lu, "
263 "did %zd: %d\n", ram_size
, done
, errno
);
270 static int copy_one_extent(struct btrfs_root
*root
, int fd
,
271 struct extent_buffer
*leaf
,
272 struct btrfs_file_extent_item
*fi
, u64 pos
)
274 struct btrfs_multi_bio
*multi
= NULL
;
275 struct btrfs_device
*device
;
276 char *inbuf
, *outbuf
= NULL
;
277 ssize_t done
, total
= 0;
293 compress
= btrfs_file_extent_compression(leaf
, fi
);
294 bytenr
= btrfs_file_extent_disk_bytenr(leaf
, fi
);
295 disk_size
= btrfs_file_extent_disk_num_bytes(leaf
, fi
);
296 ram_size
= btrfs_file_extent_ram_bytes(leaf
, fi
);
297 offset
= btrfs_file_extent_offset(leaf
, fi
);
298 num_bytes
= btrfs_file_extent_num_bytes(leaf
, fi
);
299 size_left
= disk_size
;
300 if (compress
== BTRFS_COMPRESS_NONE
)
304 printf("offset is %Lu\n", offset
);
305 /* we found a hole */
309 inbuf
= malloc(size_left
);
311 fprintf(stderr
, "No memory\n");
315 if (compress
!= BTRFS_COMPRESS_NONE
) {
316 outbuf
= malloc(ram_size
);
318 fprintf(stderr
, "No memory\n");
325 ret
= btrfs_map_block(&root
->fs_info
->mapping_tree
, READ
,
326 bytenr
, &length
, &multi
, mirror_num
, NULL
);
328 fprintf(stderr
, "Error mapping block %d\n", ret
);
331 device
= multi
->stripes
[0].dev
;
334 dev_bytenr
= multi
->stripes
[0].physical
;
337 if (size_left
< length
)
340 done
= pread(dev_fd
, inbuf
+count
, length
, dev_bytenr
);
341 /* Need both checks, or we miss negative values due to u64 conversion */
342 if (done
< 0 || done
< length
) {
343 num_copies
= btrfs_num_copies(&root
->fs_info
->mapping_tree
,
346 /* mirror_num is 1-indexed, so num_copies is a valid mirror. */
347 if (mirror_num
> num_copies
) {
349 fprintf(stderr
, "Exhausted mirrors trying to read\n");
352 fprintf(stderr
, "Trying another mirror\n");
363 if (compress
== BTRFS_COMPRESS_NONE
) {
364 while (total
< num_bytes
) {
365 done
= pwrite(fd
, inbuf
+total
, num_bytes
-total
,
369 fprintf(stderr
, "Error writing: %d %s\n", errno
, strerror(errno
));
378 ret
= decompress(inbuf
, outbuf
, disk_size
, &ram_size
, compress
);
380 num_copies
= btrfs_num_copies(&root
->fs_info
->mapping_tree
,
383 if (mirror_num
>= num_copies
) {
387 fprintf(stderr
, "Trying another mirror\n");
391 while (total
< num_bytes
) {
392 done
= pwrite(fd
, outbuf
+ offset
+ total
,
407 static int ask_to_continue(const char *file
)
412 printf("We seem to be looping a lot on %s, do you want to keep going "
413 "on ? (y/N): ", file
);
415 ret
= fgets(buf
, 2, stdin
);
416 if (*ret
== '\n' || tolower(*ret
) == 'n')
418 if (tolower(*ret
) != 'y') {
419 printf("Please enter either 'y' or 'n': ");
427 static int set_file_xattrs(struct btrfs_root
*root
, u64 inode
,
428 int fd
, const char *file_name
)
430 struct btrfs_key key
;
431 struct btrfs_path
*path
;
432 struct extent_buffer
*leaf
;
433 struct btrfs_dir_item
*di
;
442 key
.objectid
= inode
;
443 key
.type
= BTRFS_XATTR_ITEM_KEY
;
446 path
= btrfs_alloc_path();
450 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
454 leaf
= path
->nodes
[0];
456 if (path
->slots
[0] >= btrfs_header_nritems(leaf
)) {
458 ret
= next_leaf(root
, path
);
461 "Error searching for extended attributes: %d\n",
465 /* No more leaves to search */
469 leaf
= path
->nodes
[0];
474 btrfs_item_key_to_cpu(leaf
, &key
, path
->slots
[0]);
475 if (key
.type
!= BTRFS_XATTR_ITEM_KEY
|| key
.objectid
!= inode
)
478 total_len
= btrfs_item_size_nr(leaf
, path
->slots
[0]);
479 di
= btrfs_item_ptr(leaf
, path
->slots
[0],
480 struct btrfs_dir_item
);
482 while (cur
< total_len
) {
483 len
= btrfs_dir_name_len(leaf
, di
);
484 if (len
> name_len
) {
486 name
= (char *) malloc(len
+ 1);
492 read_extent_buffer(leaf
, name
,
493 (unsigned long)(di
+ 1), len
);
497 len
= btrfs_dir_data_len(leaf
, di
);
498 if (len
> data_len
) {
500 data
= (char *) malloc(len
);
506 read_extent_buffer(leaf
, data
,
507 (unsigned long)(di
+ 1) + name_len
,
511 if (fsetxattr(fd
, name
, data
, data_len
, 0)) {
515 "Error setting extended attribute %s on file %s: %s\n",
516 name
, file_name
, strerror(err
));
519 len
= sizeof(*di
) + name_len
+ data_len
;
521 di
= (struct btrfs_dir_item
*)((char *)di
+ len
);
527 btrfs_free_path(path
);
535 static int copy_file(struct btrfs_root
*root
, int fd
, struct btrfs_key
*key
,
538 struct extent_buffer
*leaf
;
539 struct btrfs_path
*path
;
540 struct btrfs_file_extent_item
*fi
;
541 struct btrfs_inode_item
*inode_item
;
542 struct btrfs_key found_key
;
549 path
= btrfs_alloc_path();
551 fprintf(stderr
, "Ran out of memory\n");
554 path
->skip_locking
= 1;
556 ret
= btrfs_lookup_inode(NULL
, root
, path
, key
, 0);
558 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
559 struct btrfs_inode_item
);
560 found_size
= btrfs_inode_size(path
->nodes
[0], inode_item
);
562 btrfs_release_path(path
);
565 key
->type
= BTRFS_EXTENT_DATA_KEY
;
567 ret
= btrfs_search_slot(NULL
, root
, key
, path
, 0, 0);
569 fprintf(stderr
, "Error searching %d\n", ret
);
570 btrfs_free_path(path
);
574 leaf
= path
->nodes
[0];
576 ret
= next_leaf(root
, path
);
578 fprintf(stderr
, "Error getting next leaf %d\n",
580 btrfs_free_path(path
);
582 } else if (ret
> 0) {
583 /* No more leaves to search */
584 btrfs_free_path(path
);
587 leaf
= path
->nodes
[0];
591 if (loops
++ >= 1024) {
592 ret
= ask_to_continue(file
);
597 if (path
->slots
[0] >= btrfs_header_nritems(leaf
)) {
599 ret
= next_leaf(root
, path
);
601 fprintf(stderr
, "Error searching %d\n", ret
);
602 btrfs_free_path(path
);
605 /* No more leaves to search */
606 btrfs_free_path(path
);
609 leaf
= path
->nodes
[0];
613 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
614 if (found_key
.objectid
!= key
->objectid
)
616 if (found_key
.type
!= key
->type
)
618 fi
= btrfs_item_ptr(leaf
, path
->slots
[0],
619 struct btrfs_file_extent_item
);
620 extent_type
= btrfs_file_extent_type(leaf
, fi
);
621 compression
= btrfs_file_extent_compression(leaf
, fi
);
622 if (compression
>= BTRFS_COMPRESS_LAST
) {
623 fprintf(stderr
, "Don't support compression yet %d\n",
625 btrfs_free_path(path
);
629 if (extent_type
== BTRFS_FILE_EXTENT_PREALLOC
)
631 if (extent_type
== BTRFS_FILE_EXTENT_INLINE
) {
632 ret
= copy_one_inline(fd
, path
, found_key
.offset
);
634 btrfs_free_path(path
);
637 } else if (extent_type
== BTRFS_FILE_EXTENT_REG
) {
638 ret
= copy_one_extent(root
, fd
, leaf
, fi
,
641 btrfs_free_path(path
);
645 printf("Weird extent type %d\n", extent_type
);
651 btrfs_free_path(path
);
654 ret
= ftruncate(fd
, (loff_t
)found_size
);
659 ret
= set_file_xattrs(root
, key
->objectid
, fd
, file
);
666 static int search_dir(struct btrfs_root
*root
, struct btrfs_key
*key
,
667 const char *output_rootdir
, const char *in_dir
,
670 struct btrfs_path
*path
;
671 struct extent_buffer
*leaf
;
672 struct btrfs_dir_item
*dir_item
;
673 struct btrfs_key found_key
, location
;
674 char filename
[BTRFS_NAME_LEN
+ 1];
675 unsigned long name_ptr
;
682 path
= btrfs_alloc_path();
684 fprintf(stderr
, "Ran out of memory\n");
687 path
->skip_locking
= 1;
690 key
->type
= BTRFS_DIR_INDEX_KEY
;
692 ret
= btrfs_search_slot(NULL
, root
, key
, path
, 0, 0);
694 fprintf(stderr
, "Error searching %d\n", ret
);
695 btrfs_free_path(path
);
699 leaf
= path
->nodes
[0];
702 printf("No leaf after search, looking for the next "
704 ret
= next_leaf(root
, path
);
706 fprintf(stderr
, "Error getting next leaf %d\n",
708 btrfs_free_path(path
);
710 } else if (ret
> 0) {
711 /* No more leaves to search */
713 printf("Reached the end of the tree looking "
714 "for the directory\n");
715 btrfs_free_path(path
);
718 leaf
= path
->nodes
[0];
722 if (loops
++ >= 1024) {
723 printf("We have looped trying to restore files in %s "
724 "too many times to be making progress, "
725 "stopping\n", in_dir
);
729 if (path
->slots
[0] >= btrfs_header_nritems(leaf
)) {
731 ret
= next_leaf(root
, path
);
733 fprintf(stderr
, "Error searching %d\n",
735 btrfs_free_path(path
);
737 } else if (ret
> 0) {
738 /* No more leaves to search */
740 printf("Reached the end of "
741 "the tree searching the"
743 btrfs_free_path(path
);
746 leaf
= path
->nodes
[0];
750 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
751 if (found_key
.objectid
!= key
->objectid
) {
753 printf("Found objectid=%Lu, key=%Lu\n",
754 found_key
.objectid
, key
->objectid
);
757 if (found_key
.type
!= key
->type
) {
759 printf("Found type=%u, want=%u\n",
760 found_key
.type
, key
->type
);
763 dir_item
= btrfs_item_ptr(leaf
, path
->slots
[0],
764 struct btrfs_dir_item
);
765 name_ptr
= (unsigned long)(dir_item
+ 1);
766 name_len
= btrfs_dir_name_len(leaf
, dir_item
);
767 read_extent_buffer(leaf
, filename
, name_ptr
, name_len
);
768 filename
[name_len
] = '\0';
769 type
= btrfs_dir_type(leaf
, dir_item
);
770 btrfs_dir_item_key_to_cpu(leaf
, dir_item
, &location
);
772 /* full path from root of btrfs being restored */
773 snprintf(fs_name
, 4096, "%s/%s", in_dir
, filename
);
775 if (mreg
&& REG_NOMATCH
== regexec(mreg
, fs_name
, 0, NULL
, 0))
778 /* full path from system root */
779 snprintf(path_name
, 4096, "%s%s", output_rootdir
, fs_name
);
782 * At this point we're only going to restore directories and
783 * files, no symlinks or anything else.
785 if (type
== BTRFS_FT_REG_FILE
) {
790 ret
= stat(path_name
, &st
);
793 if (verbose
|| !warn
)
794 printf("Skipping existing file"
798 printf("If you wish to overwrite use "
799 "the -o option to overwrite\n");
806 printf("Restoring %s\n", path_name
);
809 fd
= open(path_name
, O_CREAT
|O_WRONLY
, 0644);
811 fprintf(stderr
, "Error creating %s: %d\n",
815 btrfs_free_path(path
);
819 ret
= copy_file(root
, fd
, &location
, path_name
);
824 btrfs_free_path(path
);
827 } else if (type
== BTRFS_FT_DIR
) {
828 struct btrfs_root
*search_root
= root
;
829 char *dir
= strdup(fs_name
);
832 fprintf(stderr
, "Ran out of memory\n");
833 btrfs_free_path(path
);
837 if (location
.type
== BTRFS_ROOT_ITEM_KEY
) {
839 * If we are a snapshot and this is the index
840 * object to ourselves just skip it.
842 if (location
.objectid
==
843 root
->root_key
.objectid
) {
848 location
.offset
= (u64
)-1;
849 search_root
= btrfs_read_fs_root(root
->fs_info
,
851 if (IS_ERR(search_root
)) {
853 fprintf(stderr
, "Error reading "
854 "subvolume %s: %lu\n",
856 PTR_ERR(search_root
));
859 btrfs_free_path(path
);
860 return PTR_ERR(search_root
);
864 * A subvolume will have a key.offset of 0, a
865 * snapshot will have key.offset of a transid.
867 if (search_root
->root_key
.offset
!= 0 &&
870 printf("Skipping snapshot %s\n",
874 location
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
878 printf("Restoring %s\n", path_name
);
884 ret
= mkdir(path_name
, 0755);
885 if (ret
&& errno
!= EEXIST
) {
887 fprintf(stderr
, "Error mkdiring %s: %d\n",
891 btrfs_free_path(path
);
895 ret
= search_dir(search_root
, &location
,
896 output_rootdir
, dir
, mreg
);
901 btrfs_free_path(path
);
910 printf("Done searching %s\n", in_dir
);
911 btrfs_free_path(path
);
915 static int do_list_roots(struct btrfs_root
*root
)
917 struct btrfs_key key
;
918 struct btrfs_key found_key
;
919 struct btrfs_disk_key disk_key
;
920 struct btrfs_path
*path
;
921 struct extent_buffer
*leaf
;
922 struct btrfs_root_item ri
;
923 unsigned long offset
;
927 root
= root
->fs_info
->tree_root
;
928 path
= btrfs_alloc_path();
930 fprintf(stderr
, "Failed to alloc path\n");
936 key
.type
= BTRFS_ROOT_ITEM_KEY
;
938 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
940 fprintf(stderr
, "Failed to do search %d\n", ret
);
941 btrfs_free_path(path
);
946 leaf
= path
->nodes
[0];
947 slot
= path
->slots
[0];
948 if (slot
>= btrfs_header_nritems(leaf
)) {
949 ret
= btrfs_next_leaf(root
, path
);
952 leaf
= path
->nodes
[0];
953 slot
= path
->slots
[0];
955 btrfs_item_key(leaf
, &disk_key
, slot
);
956 btrfs_disk_key_to_cpu(&found_key
, &disk_key
);
957 if (btrfs_key_type(&found_key
) != BTRFS_ROOT_ITEM_KEY
) {
962 offset
= btrfs_item_ptr_offset(leaf
, slot
);
963 read_extent_buffer(leaf
, &ri
, offset
, sizeof(ri
));
965 btrfs_print_key(&disk_key
);
966 printf(" %Lu level %d\n", btrfs_root_bytenr(&ri
),
967 btrfs_root_level(&ri
));
970 btrfs_free_path(path
);
975 static struct btrfs_root
*open_fs(const char *dev
, u64 root_location
,
976 int super_mirror
, int list_roots
)
978 struct btrfs_fs_info
*fs_info
= NULL
;
979 struct btrfs_root
*root
= NULL
;
983 for (i
= super_mirror
; i
< BTRFS_SUPER_MIRROR_MAX
; i
++) {
984 bytenr
= btrfs_sb_offset(i
);
985 fs_info
= open_ctree_fs_info(dev
, bytenr
, root_location
,
989 fprintf(stderr
, "Could not open root, trying backup super\n");
996 * All we really need to succeed is reading the chunk tree, everything
997 * else we can do by hand, since we only need to read the tree root and
1000 if (!extent_buffer_uptodate(fs_info
->tree_root
->node
)) {
1003 root
= fs_info
->tree_root
;
1005 root_location
= btrfs_super_root(fs_info
->super_copy
);
1006 generation
= btrfs_super_generation(fs_info
->super_copy
);
1007 root
->node
= read_tree_block(root
, root_location
,
1008 root
->leafsize
, generation
);
1009 if (!extent_buffer_uptodate(root
->node
)) {
1010 fprintf(stderr
, "Error opening tree root\n");
1016 if (!list_roots
&& !fs_info
->fs_root
) {
1017 struct btrfs_key key
;
1019 key
.objectid
= BTRFS_FS_TREE_OBJECTID
;
1020 key
.type
= BTRFS_ROOT_ITEM_KEY
;
1021 key
.offset
= (u64
)-1;
1022 fs_info
->fs_root
= btrfs_read_fs_root_no_cache(fs_info
, &key
);
1023 if (IS_ERR(fs_info
->fs_root
)) {
1024 fprintf(stderr
, "Couldn't read fs root: %ld\n",
1025 PTR_ERR(fs_info
->fs_root
));
1026 close_ctree(fs_info
->tree_root
);
1031 if (list_roots
&& do_list_roots(fs_info
->tree_root
)) {
1032 close_ctree(fs_info
->tree_root
);
1036 return fs_info
->fs_root
;
1039 static int find_first_dir(struct btrfs_root
*root
, u64
*objectid
)
1041 struct btrfs_path
*path
;
1042 struct btrfs_key found_key
;
1043 struct btrfs_key key
;
1048 key
.type
= BTRFS_DIR_INDEX_KEY
;
1051 path
= btrfs_alloc_path();
1053 fprintf(stderr
, "Ran out of memory\n");
1057 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
1059 fprintf(stderr
, "Error searching %d\n", ret
);
1063 if (!path
->nodes
[0]) {
1064 fprintf(stderr
, "No leaf!\n");
1068 for (i
= path
->slots
[0];
1069 i
< btrfs_header_nritems(path
->nodes
[0]); i
++) {
1070 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
, i
);
1071 if (found_key
.type
!= key
.type
)
1074 printf("Using objectid %Lu for first dir\n",
1075 found_key
.objectid
);
1076 *objectid
= found_key
.objectid
;
1081 ret
= next_leaf(root
, path
);
1083 fprintf(stderr
, "Error getting next leaf %d\n",
1086 } else if (ret
> 0) {
1087 fprintf(stderr
, "No more leaves\n");
1090 } while (!path
->nodes
[0]);
1093 printf("Couldn't find a dir index item\n");
1095 btrfs_free_path(path
);
1099 static struct option long_options
[] = {
1100 { "path-regex", 1, NULL
, 256},
1101 { "dry-run", 0, NULL
, 'D'},
1105 const char * const cmd_restore_usage
[] = {
1106 "btrfs restore [options] <device> <path> | -l <device>",
1107 "Try to restore files from a damaged filesystem (unmounted)",
1110 "-x get extended attributes",
1114 "-t <location> tree location",
1115 "-f <offset> filesystem location",
1116 "-u <block> super mirror",
1117 "-r <rootid> root objectid",
1119 "-l list tree roots",
1120 "-D|--dry-run dry run (only list files that would be recovered)",
1121 "--path-regex <regex>",
1122 " restore only filenames matching regex,",
1123 " you have to use following syntax (possibly quoted):",
1124 " ^/(|home(|/username(|/Desktop(|/.*))))$",
1128 int cmd_restore(int argc
, char **argv
)
1130 struct btrfs_root
*root
;
1131 struct btrfs_key key
;
1133 u64 tree_location
= 0;
1134 u64 fs_location
= 0;
1135 u64 root_objectid
= 0;
1139 int option_index
= 0;
1140 int super_mirror
= 0;
1143 const char *match_regstr
= NULL
;
1144 int match_cflags
= REG_EXTENDED
| REG_NOSUB
| REG_NEWLINE
;
1145 regex_t match_reg
, *mreg
= NULL
;
1148 while ((opt
= getopt_long(argc
, argv
, "sxviot:u:df:r:lDc", long_options
,
1149 &option_index
)) != -1) {
1165 tree_location
= arg_strtou64(optarg
);
1168 fs_location
= arg_strtou64(optarg
);
1171 super_mirror
= arg_strtou64(optarg
);
1172 if (super_mirror
>= BTRFS_SUPER_MIRROR_MAX
) {
1173 fprintf(stderr
, "Super mirror not "
1182 root_objectid
= arg_strtou64(optarg
);
1191 match_cflags
|= REG_ICASE
;
1193 /* long option without single letter alternative */
1195 match_regstr
= optarg
;
1201 usage(cmd_restore_usage
);
1205 if (!list_roots
&& optind
+ 1 >= argc
)
1206 usage(cmd_restore_usage
);
1207 else if (list_roots
&& optind
>= argc
)
1208 usage(cmd_restore_usage
);
1210 if ((ret
= check_mounted(argv
[optind
])) < 0) {
1211 fprintf(stderr
, "Could not check mount status: %s\n",
1215 fprintf(stderr
, "%s is currently mounted. Aborting.\n", argv
[optind
]);
1219 root
= open_fs(argv
[optind
], tree_location
, super_mirror
, list_roots
);
1226 if (fs_location
!= 0) {
1227 free_extent_buffer(root
->node
);
1228 root
->node
= read_tree_block(root
, fs_location
, root
->leafsize
, 0);
1230 fprintf(stderr
, "Failed to read fs location\n");
1235 memset(path_name
, 0, 4096);
1237 strncpy(dir_name
, argv
[optind
+ 1], sizeof dir_name
);
1238 dir_name
[sizeof dir_name
- 1] = 0;
1240 /* Strip the trailing / on the dir name */
1241 len
= strlen(dir_name
);
1242 while (len
&& dir_name
[--len
] == '/') {
1243 dir_name
[len
] = '\0';
1246 if (root_objectid
!= 0) {
1247 struct btrfs_root
*orig_root
= root
;
1249 key
.objectid
= root_objectid
;
1250 key
.type
= BTRFS_ROOT_ITEM_KEY
;
1251 key
.offset
= (u64
)-1;
1252 root
= btrfs_read_fs_root(orig_root
->fs_info
, &key
);
1254 fprintf(stderr
, "Error reading root\n");
1264 ret
= find_first_dir(root
, &key
.objectid
);
1268 key
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
1272 ret
= regcomp(&match_reg
, match_regstr
, match_cflags
);
1274 regerror(ret
, &match_reg
, reg_err
, sizeof(reg_err
));
1275 fprintf(stderr
, "Regex compile failed: %s\n", reg_err
);
1282 printf("This is a dry-run, no files are going to be restored\n");
1284 ret
= search_dir(root
, &key
, dir_name
, "", mreg
);