btrfs-progs: treat super.magic as an le64
[platform/upstream/btrfs-progs.git] / restore.c
1 /*
2  * Copyright (C) 2011 Red Hat.  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 #define _XOPEN_SOURCE 500
20 #define _GNU_SOURCE 1
21
22 #include "kerncompat.h"
23
24 #include <ctype.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #include <zlib.h>
31
32 #include "ctree.h"
33 #include "disk-io.h"
34 #include "print-tree.h"
35 #include "transaction.h"
36 #include "list.h"
37 #include "version.h"
38 #include "volumes.h"
39 #include "utils.h"
40
41 static char path_name[4096];
42 static int get_snaps = 0;
43 static int verbose = 0;
44 static int ignore_errors = 0;
45 static int overwrite = 0;
46
47 static int decompress(char *inbuf, char *outbuf, u64 compress_len,
48                       u64 decompress_len)
49 {
50         z_stream strm;
51         int ret;
52
53         memset(&strm, 0, sizeof(strm));
54         ret = inflateInit(&strm);
55         if (ret != Z_OK) {
56                 fprintf(stderr, "inflate init returnd %d\n", ret);
57                 return -1;
58         }
59
60         strm.avail_in = compress_len;
61         strm.next_in = (unsigned char *)inbuf;
62         strm.avail_out = decompress_len;
63         strm.next_out = (unsigned char *)outbuf;
64         ret = inflate(&strm, Z_NO_FLUSH);
65         if (ret != Z_STREAM_END) {
66                 (void)inflateEnd(&strm);
67                 fprintf(stderr, "ret is %d\n", ret);
68                 return -1;
69         }
70
71         (void)inflateEnd(&strm);
72         return 0;
73 }
74
75 int next_leaf(struct btrfs_root *root, struct btrfs_path *path)
76 {
77         int slot;
78         int level = 1;
79         struct extent_buffer *c;
80         struct extent_buffer *next = NULL;
81
82         for (; level < BTRFS_MAX_LEVEL; level++) {
83                 if (path->nodes[level])
84                         break;
85         }
86
87         if (level == BTRFS_MAX_LEVEL)
88                 return 1;
89
90         slot = path->slots[level] + 1;
91
92         while(level < BTRFS_MAX_LEVEL) {
93                 if (!path->nodes[level])
94                         return 1;
95
96                 slot = path->slots[level] + 1;
97                 c = path->nodes[level];
98                 if (slot >= btrfs_header_nritems(c)) {
99                         level++;
100                         if (level == BTRFS_MAX_LEVEL)
101                                 return 1;
102                         continue;
103                 }
104
105                 if (next)
106                         free_extent_buffer(next);
107
108                 if (path->reada)
109                         reada_for_search(root, path, level, slot, 0);
110
111                 next = read_node_slot(root, c, slot);
112                 break;
113         }
114         path->slots[level] = slot;
115         while(1) {
116                 level--;
117                 c = path->nodes[level];
118                 free_extent_buffer(c);
119                 path->nodes[level] = next;
120                 path->slots[level] = 0;
121                 if (!level)
122                         break;
123                 if (path->reada)
124                         reada_for_search(root, path, level, 0, 0);
125                 next = read_node_slot(root, next, 0);
126         }
127         return 0;
128 }
129
130 static int copy_one_inline(int fd, struct btrfs_path *path, u64 pos)
131 {
132         struct extent_buffer *leaf = path->nodes[0];
133         struct btrfs_file_extent_item *fi;
134         char buf[4096];
135         char *outbuf;
136         ssize_t done;
137         unsigned long ptr;
138         int ret;
139         int len;
140         int ram_size;
141         int compress;
142
143         fi = btrfs_item_ptr(leaf, path->slots[0],
144                             struct btrfs_file_extent_item);
145         ptr = btrfs_file_extent_inline_start(fi);
146         len = btrfs_file_extent_inline_item_len(leaf,
147                                         btrfs_item_nr(leaf, path->slots[0]));
148         read_extent_buffer(leaf, buf, ptr, len);
149
150         compress = btrfs_file_extent_compression(leaf, fi);
151         if (compress == BTRFS_COMPRESS_NONE) {
152                 done = pwrite(fd, buf, len, pos);
153                 if (done < len) {
154                         fprintf(stderr, "Short inline write, wanted %d, did "
155                                 "%zd: %d\n", len, done, errno);
156                         return -1;
157                 }
158                 return 0;
159         }
160
161         ram_size = btrfs_file_extent_ram_bytes(leaf, fi);
162         outbuf = malloc(ram_size);
163         if (!outbuf) {
164                 fprintf(stderr, "No memory\n");
165                 return -1;
166         }
167
168         ret = decompress(buf, outbuf, len, ram_size);
169         if (ret) {
170                 free(outbuf);
171                 return ret;
172         }
173
174         done = pwrite(fd, outbuf, ram_size, pos);
175         free(outbuf);
176         if (done < len) {
177                 fprintf(stderr, "Short compressed inline write, wanted %d, "
178                         "did %zd: %d\n", ram_size, done, errno);
179                 return -1;
180         }
181
182         return 0;
183 }
184
185 static int copy_one_extent(struct btrfs_root *root, int fd,
186                            struct extent_buffer *leaf,
187                            struct btrfs_file_extent_item *fi, u64 pos)
188 {
189         struct btrfs_multi_bio *multi = NULL;
190         struct btrfs_device *device;
191         char *inbuf, *outbuf = NULL;
192         ssize_t done, total = 0;
193         u64 bytenr;
194         u64 ram_size;
195         u64 disk_size;
196         u64 length;
197         u64 size_left;
198         u64 dev_bytenr;
199         u64 count = 0;
200         int compress;
201         int ret;
202         int dev_fd;
203
204         compress = btrfs_file_extent_compression(leaf, fi);
205         bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
206         disk_size = btrfs_file_extent_disk_num_bytes(leaf, fi);
207         ram_size = btrfs_file_extent_ram_bytes(leaf, fi);
208         size_left = disk_size;
209
210         /* we found a hole */
211         if (disk_size == 0)
212                 return 0;
213
214         inbuf = malloc(disk_size);
215         if (!inbuf) {
216                 fprintf(stderr, "No memory\n");
217                 return -1;
218         }
219
220         if (compress != BTRFS_COMPRESS_NONE) {
221                 outbuf = malloc(ram_size);
222                 if (!outbuf) {
223                         fprintf(stderr, "No memory\n");
224                         free(inbuf);
225                         return -1;
226                 }
227         }
228 again:
229         length = size_left;
230         ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
231                               bytenr, &length, &multi, 0);
232         if (ret) {
233                 free(inbuf);
234                 free(outbuf);
235                 fprintf(stderr, "Error mapping block %d\n", ret);
236                 return ret;
237         }
238         device = multi->stripes[0].dev;
239         dev_fd = device->fd;
240         device->total_ios++;
241         dev_bytenr = multi->stripes[0].physical;
242         kfree(multi);
243
244         if (size_left < length)
245                 length = size_left;
246         size_left -= length;
247
248         done = pread(dev_fd, inbuf+count, length, dev_bytenr);
249         if (done < length) {
250                 free(inbuf);
251                 free(outbuf);
252                 fprintf(stderr, "Short read %d\n", errno);
253                 return -1;
254         }
255
256         count += length;
257         bytenr += length;
258         if (size_left)
259                 goto again;
260
261
262         if (compress == BTRFS_COMPRESS_NONE) {
263                 while (total < ram_size) {
264                         done = pwrite(fd, inbuf+total, ram_size-total,
265                                       pos+total);
266                         if (done < 0) {
267                                 free(inbuf);
268                                 fprintf(stderr, "Error writing: %d %s\n", errno, strerror(errno));
269                                 return -1;
270                         }
271                         total += done;
272                 }
273                 free(inbuf);
274                 return 0;
275         }
276
277         ret = decompress(inbuf, outbuf, disk_size, ram_size);
278         free(inbuf);
279         if (ret) {
280                 free(outbuf);
281                 return ret;
282         }
283
284         while (total < ram_size) {
285                 done = pwrite(fd, outbuf+total, ram_size-total, pos+total);
286                 if (done < 0) {
287                         free(outbuf);
288                         fprintf(stderr, "Error writing: %d %s\n", errno, strerror(errno));
289                         return -1;
290                 }
291                 total += done;
292         }
293         free(outbuf);
294
295         return 0;
296 }
297
298 static int ask_to_continue(const char *file)
299 {
300         char buf[2];
301         char *ret;
302
303         printf("We seem to be looping a lot on %s, do you want to keep going "
304                "on ? (y/N): ", file);
305 again:
306         ret = fgets(buf, 2, stdin);
307         if (*ret == '\n' || tolower(*ret) == 'n')
308                 return 1;
309         if (tolower(*ret) != 'y') {
310                 printf("Please enter either 'y' or 'n': ");
311                 goto again;
312         }
313
314         return 0;
315 }
316
317
318 static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key,
319                      const char *file)
320 {
321         struct extent_buffer *leaf;
322         struct btrfs_path *path;
323         struct btrfs_file_extent_item *fi;
324         struct btrfs_inode_item *inode_item;
325         struct btrfs_key found_key;
326         int ret;
327         int extent_type;
328         int compression;
329         int loops = 0;
330         u64 found_size = 0;
331
332         path = btrfs_alloc_path();
333         if (!path) {
334                 fprintf(stderr, "Ran out of memory\n");
335                 return -1;
336         }
337         path->skip_locking = 1;
338
339         ret = btrfs_lookup_inode(NULL, root, path, key, 0);
340         if (ret == 0) {
341                 inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
342                                     struct btrfs_inode_item);
343                 found_size = btrfs_inode_size(path->nodes[0], inode_item);
344         }
345         btrfs_release_path(root, path);
346
347         key->offset = 0;
348         key->type = BTRFS_EXTENT_DATA_KEY;
349
350         ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
351         if (ret < 0) {
352                 fprintf(stderr, "Error searching %d\n", ret);
353                 btrfs_free_path(path);
354                 return ret;
355         }
356
357         leaf = path->nodes[0];
358         while (!leaf) {
359                 ret = next_leaf(root, path);
360                 if (ret < 0) {
361                         fprintf(stderr, "Error getting next leaf %d\n",
362                                 ret);
363                         btrfs_free_path(path);
364                         return ret;
365                 } else if (ret > 0) {
366                         /* No more leaves to search */
367                         btrfs_free_path(path);
368                         return 0;
369                 }
370                 leaf = path->nodes[0];
371         }
372
373         while (1) {
374                 if (loops++ >= 1024) {
375                         ret = ask_to_continue(file);
376                         if (ret)
377                                 break;
378                         loops = 0;
379                 }
380                 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
381                         do {
382                                 ret = next_leaf(root, path);
383                                 if (ret < 0) {
384                                         fprintf(stderr, "Error searching %d\n", ret);
385                                         btrfs_free_path(path);
386                                         return ret;
387                                 } else if (ret) {
388                                         /* No more leaves to search */
389                                         btrfs_free_path(path);
390                                         goto set_size;
391                                 }
392                                 leaf = path->nodes[0];
393                         } while (!leaf);
394                         continue;
395                 }
396                 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
397                 if (found_key.objectid != key->objectid)
398                         break;
399                 if (found_key.type != key->type)
400                         break;
401                 fi = btrfs_item_ptr(leaf, path->slots[0],
402                                     struct btrfs_file_extent_item);
403                 extent_type = btrfs_file_extent_type(leaf, fi);
404                 compression = btrfs_file_extent_compression(leaf, fi);
405                 if (compression >= BTRFS_COMPRESS_LAST) {
406                         fprintf(stderr, "Don't support compression yet %d\n",
407                                 compression);
408                         btrfs_free_path(path);
409                         return -1;
410                 }
411
412                 if (extent_type == BTRFS_FILE_EXTENT_PREALLOC)
413                         goto next;
414                 if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
415                         ret = copy_one_inline(fd, path, found_key.offset);
416                         if (ret) {
417                                 btrfs_free_path(path);
418                                 return -1;
419                         }
420                 } else if (extent_type == BTRFS_FILE_EXTENT_REG) {
421                         ret = copy_one_extent(root, fd, leaf, fi,
422                                               found_key.offset);
423                         if (ret) {
424                                 btrfs_free_path(path);
425                                 return ret;
426                         }
427                 } else {
428                         printf("Weird extent type %d\n", extent_type);
429                 }
430 next:
431                 path->slots[0]++;
432         }
433
434         btrfs_free_path(path);
435 set_size:
436         if (found_size) {
437                 ret = ftruncate(fd, (loff_t)found_size);
438                 if (ret)
439                         return ret;
440         }
441         return 0;
442 }
443
444 static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
445                       const char *dir)
446 {
447         struct btrfs_path *path;
448         struct extent_buffer *leaf;
449         struct btrfs_dir_item *dir_item;
450         struct btrfs_key found_key, location;
451         char filename[BTRFS_NAME_LEN + 1];
452         unsigned long name_ptr;
453         int name_len;
454         int ret;
455         int fd;
456         int loops = 0;
457         u8 type;
458
459         path = btrfs_alloc_path();
460         if (!path) {
461                 fprintf(stderr, "Ran out of memory\n");
462                 return -1;
463         }
464         path->skip_locking = 1;
465
466         key->offset = 0;
467         key->type = BTRFS_DIR_INDEX_KEY;
468
469         ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
470         if (ret < 0) {
471                 fprintf(stderr, "Error searching %d\n", ret);
472                 btrfs_free_path(path);
473                 return ret;
474         }
475
476         leaf = path->nodes[0];
477         while (!leaf) {
478                 if (verbose > 1)
479                         printf("No leaf after search, looking for the next "
480                                "leaf\n");
481                 ret = next_leaf(root, path);
482                 if (ret < 0) {
483                         fprintf(stderr, "Error getting next leaf %d\n",
484                                 ret);
485                         btrfs_free_path(path);
486                         return ret;
487                 } else if (ret > 0) {
488                         /* No more leaves to search */
489                         if (verbose)
490                                 printf("Reached the end of the tree looking "
491                                        "for the directory\n");
492                         btrfs_free_path(path);
493                         return 0;
494                 }
495                 leaf = path->nodes[0];
496         }
497
498         while (leaf) {
499                 if (loops++ >= 1024) {
500                         printf("We have looped trying to restore files in %s "
501                                "too many times to be making progress, "
502                                "stopping\n", dir);
503                         break;
504                 }
505
506                 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
507                         do {
508                                 ret = next_leaf(root, path);
509                                 if (ret < 0) {
510                                         fprintf(stderr, "Error searching %d\n",
511                                                 ret);
512                                         btrfs_free_path(path);
513                                         return ret;
514                                 } else if (ret > 0) {
515                                         /* No more leaves to search */
516                                         if (verbose)
517                                                 printf("Reached the end of "
518                                                        "the tree searching the"
519                                                        " directory\n");
520                                         btrfs_free_path(path);
521                                         return 0;
522                                 }
523                                 leaf = path->nodes[0];
524                         } while (!leaf);
525                         continue;
526                 }
527                 btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
528                 if (found_key.objectid != key->objectid) {
529                         if (verbose > 1)
530                                 printf("Found objectid=%Lu, key=%Lu\n",
531                                        found_key.objectid, key->objectid);
532                         break;
533                 }
534                 if (found_key.type != key->type) {
535                         if (verbose > 1)
536                                 printf("Found type=%u, want=%u\n",
537                                        found_key.type, key->type);
538                         break;
539                 }
540                 dir_item = btrfs_item_ptr(leaf, path->slots[0],
541                                           struct btrfs_dir_item);
542                 name_ptr = (unsigned long)(dir_item + 1);
543                 name_len = btrfs_dir_name_len(leaf, dir_item);
544                 read_extent_buffer(leaf, filename, name_ptr, name_len);
545                 filename[name_len] = '\0';
546                 type = btrfs_dir_type(leaf, dir_item);
547                 btrfs_dir_item_key_to_cpu(leaf, dir_item, &location);
548
549                 snprintf(path_name, 4096, "%s/%s", dir, filename);
550
551
552                 /*
553                  * At this point we're only going to restore directories and
554                  * files, no symlinks or anything else.
555                  */
556                 if (type == BTRFS_FT_REG_FILE) {
557                         if (!overwrite) {
558                                 static int warn = 0;
559                                 struct stat st;
560
561                                 ret = stat(path_name, &st);
562                                 if (!ret) {
563                                         loops = 0;
564                                         if (verbose || !warn)
565                                                 printf("Skipping existing file"
566                                                        " %s\n", path_name);
567                                         if (warn)
568                                                 goto next;
569                                         printf("If you wish to overwrite use "
570                                                "the -o option to overwrite\n");
571                                         warn = 1;
572                                         goto next;
573                                 }
574                                 ret = 0;
575                         }
576                         if (verbose)
577                                 printf("Restoring %s\n", path_name);
578                         fd = open(path_name, O_CREAT|O_WRONLY, 0644);
579                         if (fd < 0) {
580                                 fprintf(stderr, "Error creating %s: %d\n",
581                                         path_name, errno);
582                                 if (ignore_errors)
583                                         goto next;
584                                 btrfs_free_path(path);
585                                 return -1;
586                         }
587                         loops = 0;
588                         ret = copy_file(root, fd, &location, path_name);
589                         close(fd);
590                         if (ret) {
591                                 if (ignore_errors)
592                                         goto next;
593                                 btrfs_free_path(path);
594                                 return ret;
595                         }
596                 } else if (type == BTRFS_FT_DIR) {
597                         struct btrfs_root *search_root = root;
598                         char *dir = strdup(path_name);
599
600                         if (!dir) {
601                                 fprintf(stderr, "Ran out of memory\n");
602                                 btrfs_free_path(path);
603                                 return -1;
604                         }
605
606                         if (location.type == BTRFS_ROOT_ITEM_KEY) {
607                                 /*
608                                  * If we are a snapshot and this is the index
609                                  * object to ourselves just skip it.
610                                  */
611                                 if (location.objectid ==
612                                     root->root_key.objectid) {
613                                         free(dir);
614                                         goto next;
615                                 }
616
617                                 search_root = btrfs_read_fs_root(root->fs_info,
618                                                                  &location);
619                                 if (IS_ERR(search_root)) {
620                                         free(dir);
621                                         fprintf(stderr, "Error reading "
622                                                 "subvolume %s: %lu\n",
623                                                 path_name,
624                                                 PTR_ERR(search_root));
625                                         if (ignore_errors)
626                                                 goto next;
627                                         return PTR_ERR(search_root);
628                                 }
629
630                                 /*
631                                  * A subvolume will have a key.offset of 0, a
632                                  * snapshot will have key.offset of a transid.
633                                  */
634                                 if (search_root->root_key.offset != 0 &&
635                                     get_snaps == 0) {
636                                         free(dir);
637                                         printf("Skipping snapshot %s\n",
638                                                filename);
639                                         goto next;
640                                 }
641                                 location.objectid = BTRFS_FIRST_FREE_OBJECTID;
642                         }
643
644                         if (verbose)
645                                 printf("Restoring %s\n", path_name);
646
647                         errno = 0;
648                         ret = mkdir(path_name, 0755);
649                         if (ret && errno != EEXIST) {
650                                 free(dir);
651                                 fprintf(stderr, "Error mkdiring %s: %d\n",
652                                         path_name, errno);
653                                 if (ignore_errors)
654                                         goto next;
655                                 btrfs_free_path(path);
656                                 return -1;
657                         }
658                         loops = 0;
659                         ret = search_dir(search_root, &location, dir);
660                         free(dir);
661                         if (ret) {
662                                 if (ignore_errors)
663                                         goto next;
664                                 btrfs_free_path(path);
665                                 return ret;
666                         }
667                 }
668 next:
669                 path->slots[0]++;
670         }
671
672         if (verbose)
673                 printf("Done searching %s\n", dir);
674         btrfs_free_path(path);
675         return 0;
676 }
677
678 static void usage()
679 {
680         fprintf(stderr, "Usage: restore [-svio] [-t disk offset] <device> "
681                 "<directory>\n");
682 }
683
684 static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror)
685 {
686         struct btrfs_root *root;
687         u64 bytenr;
688         int i;
689
690         for (i = super_mirror; i < BTRFS_SUPER_MIRROR_MAX; i++) {
691                 bytenr = btrfs_sb_offset(i);
692                 root = open_ctree_recovery(dev, bytenr, root_location);
693                 if (root)
694                         return root;
695                 fprintf(stderr, "Could not open root, trying backup super\n");
696         }
697
698         return NULL;
699 }
700
701 static int find_first_dir(struct btrfs_root *root, u64 *objectid)
702 {
703         struct btrfs_path *path;
704         struct btrfs_key found_key;
705         struct btrfs_key key;
706         int ret = -1;
707         int i;
708
709         key.objectid = 0;
710         key.type = BTRFS_DIR_INDEX_KEY;
711         key.offset = 0;
712
713         path = btrfs_alloc_path();
714         if (!path) {
715                 fprintf(stderr, "Ran out of memory\n");
716                 goto out;
717         }
718
719         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
720         if (ret < 0) {
721                 fprintf(stderr, "Error searching %d\n", ret);
722                 goto out;
723         }
724
725         if (!path->nodes[0]) {
726                 fprintf(stderr, "No leaf!\n");
727                 goto out;
728         }
729 again:
730         for (i = path->slots[0];
731              i < btrfs_header_nritems(path->nodes[0]); i++) {
732                 btrfs_item_key_to_cpu(path->nodes[0], &found_key, i);
733                 if (found_key.type != key.type)
734                         continue;
735
736                 printf("Using objectid %Lu for first dir\n",
737                        found_key.objectid);
738                 *objectid = found_key.objectid;
739                 ret = 0;
740                 goto out;
741         }
742         do {
743                 ret = next_leaf(root, path);
744                 if (ret < 0) {
745                         fprintf(stderr, "Error getting next leaf %d\n",
746                                 ret);
747                         goto out;
748                 } else if (ret > 0) {
749                         fprintf(stderr, "No more leaves\n");
750                         goto out;
751                 }
752         } while (!path->nodes[0]);
753         if (path->nodes[0])
754                 goto again;
755         printf("Couldn't find a dir index item\n");
756 out:
757         btrfs_free_path(path);
758         return ret;
759 }
760
761 int main(int argc, char **argv)
762 {
763         struct btrfs_root *root;
764         struct btrfs_key key;
765         char dir_name[128];
766         u64 tree_location = 0;
767         u64 fs_location = 0;
768         int len;
769         int ret;
770         int opt;
771         int super_mirror = 0;
772         int find_dir = 0;
773
774         while ((opt = getopt(argc, argv, "sviot:u:df:")) != -1) {
775                 switch (opt) {
776                         case 's':
777                                 get_snaps = 1;
778                                 break;
779                         case 'v':
780                                 verbose++;
781                                 break;
782                         case 'i':
783                                 ignore_errors = 1;
784                                 break;
785                         case 'o':
786                                 overwrite = 1;
787                                 break;
788                         case 't':
789                                 errno = 0;
790                                 tree_location = (u64)strtoll(optarg, NULL, 10);
791                                 if (errno != 0) {
792                                         fprintf(stderr, "Tree location not valid\n");
793                                         exit(1);
794                                 }
795                                 break;
796                         case 'f':
797                                 errno = 0;
798                                 fs_location = (u64)strtoll(optarg, NULL, 10);
799                                 if (errno != 0) {
800                                         fprintf(stderr, "Fs location not valid\n");
801                                         exit(1);
802                                 }
803                                 break;
804                         case 'u':
805                                 errno = 0;
806                                 super_mirror = (int)strtol(optarg, NULL, 10);
807                                 if (errno != 0 ||
808                                     super_mirror >= BTRFS_SUPER_MIRROR_MAX) {
809                                         fprintf(stderr, "Super mirror not "
810                                                 "valid\n");
811                                         exit(1);
812                                 }
813                                 break;
814                         case 'd':
815                                 find_dir = 1;
816                                 break;
817                         default:
818                                 usage();
819                                 exit(1);
820                 }
821         }
822
823         if (optind + 1 >= argc) {
824                 usage();
825                 exit(1);
826         }
827
828         if ((ret = check_mounted(argv[optind])) < 0) {
829                 fprintf(stderr, "Could not check mount status: %s\n",
830                         strerror(ret));
831                 return ret;
832         } else if (ret) {
833                 fprintf(stderr, "%s is currently mounted.  Aborting.\n", argv[optind]);
834                 return -EBUSY;
835         }
836
837         root = open_fs(argv[optind], tree_location, super_mirror);
838         if (root == NULL)
839                 return 1;
840
841         if (fs_location != 0) {
842                 free_extent_buffer(root->node);
843                 root->node = read_tree_block(root, fs_location, 4096, 0);
844                 if (!root->node) {
845                         fprintf(stderr, "Failed to read fs location\n");
846                         goto out;
847                 }
848         }
849
850         printf("Root objectid is %Lu\n", root->objectid);
851
852         memset(path_name, 0, 4096);
853
854         strncpy(dir_name, argv[optind + 1], sizeof dir_name);
855         dir_name[sizeof dir_name - 1] = 0;
856
857         /* Strip the trailing / on the dir name */
858         len = strlen(dir_name);
859         while (len && dir_name[--len] == '/') {
860                 dir_name[len] = '\0';
861         }
862
863         if (find_dir) {
864                 ret = find_first_dir(root, &key.objectid);
865                 if (ret)
866                         goto out;
867         } else {
868                 key.objectid = BTRFS_FIRST_FREE_OBJECTID;
869         }
870
871         ret = search_dir(root->fs_info->fs_root, &key, dir_name);
872
873 out:
874         close_ctree(root);
875         return ret;
876 }