btrfs-progs: remove NULL-ptr judge before free for btrfs-progs
[platform/upstream/btrfs-progs.git] / btrfs-list.c
1 /*
2  * Copyright (C) 2010 Oracle.  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 _GNU_SOURCE
20 #include <sys/ioctl.h>
21 #include <sys/mount.h>
22 #include "ioctl.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <dirent.h>
30 #include <libgen.h>
31 #include "ctree.h"
32 #include "transaction.h"
33 #include "utils.h"
34 #include <uuid/uuid.h>
35 #include "btrfs-list.h"
36
37 #define BTRFS_LIST_NFILTERS_INCREASE    (2 * BTRFS_LIST_FILTER_MAX)
38 #define BTRFS_LIST_NCOMPS_INCREASE      (2 * BTRFS_LIST_COMP_MAX)
39
40 /* we store all the roots we find in an rbtree so that we can
41  * search for them later.
42  */
43 struct root_lookup {
44         struct rb_root root;
45 };
46
47 static struct {
48         char    *name;
49         char    *column_name;
50         int     need_print;
51 } btrfs_list_columns[] = {
52         {
53                 .name           = "ID",
54                 .column_name    = "ID",
55                 .need_print     = 0,
56         },
57         {
58                 .name           = "gen",
59                 .column_name    = "Gen",
60                 .need_print     = 0,
61         },
62         {
63                 .name           = "cgen",
64                 .column_name    = "CGen",
65                 .need_print     = 0,
66         },
67         {
68                 .name           = "parent",
69                 .column_name    = "Parent",
70                 .need_print     = 0,
71         },
72         {
73                 .name           = "top level",
74                 .column_name    = "Top Level",
75                 .need_print     = 0,
76         },
77         {
78                 .name           = "otime",
79                 .column_name    = "OTime",
80                 .need_print     = 0,
81         },
82         {
83                 .name           = "parent_uuid",
84                 .column_name    = "Parent UUID",
85                 .need_print     = 0,
86         },
87         {
88                 .name           = "uuid",
89                 .column_name    = "UUID",
90                 .need_print     = 0,
91         },
92         {
93                 .name           = "path",
94                 .column_name    = "Path",
95                 .need_print     = 0,
96         },
97         {
98                 .name           = NULL,
99                 .column_name    = NULL,
100                 .need_print     = 0,
101         },
102 };
103
104 static btrfs_list_filter_func all_filter_funcs[];
105 static btrfs_list_comp_func all_comp_funcs[];
106
107 void btrfs_list_setup_print_column(enum btrfs_list_column_enum column)
108 {
109         int i;
110
111         BUG_ON(column < 0 || column > BTRFS_LIST_ALL);
112
113         if (column < BTRFS_LIST_ALL) {
114                 btrfs_list_columns[column].need_print = 1;
115                 return;
116         }
117
118         for (i = 0; i < BTRFS_LIST_ALL; i++)
119                 btrfs_list_columns[i].need_print = 1;
120 }
121
122 static void root_lookup_init(struct root_lookup *tree)
123 {
124         tree->root.rb_node = NULL;
125 }
126
127 static int comp_entry_with_rootid(struct root_info *entry1,
128                                   struct root_info *entry2,
129                                   int is_descending)
130 {
131         int ret;
132
133         if (entry1->root_id > entry2->root_id)
134                 ret = 1;
135         else if (entry1->root_id < entry2->root_id)
136                 ret = -1;
137         else
138                 ret = 0;
139
140         return is_descending ? -ret : ret;
141 }
142
143 static int comp_entry_with_gen(struct root_info *entry1,
144                                struct root_info *entry2,
145                                int is_descending)
146 {
147         int ret;
148
149         if (entry1->gen > entry2->gen)
150                 ret = 1;
151         else if (entry1->gen < entry2->gen)
152                 ret = -1;
153         else
154                 ret = 0;
155
156         return is_descending ? -ret : ret;
157 }
158
159 static int comp_entry_with_ogen(struct root_info *entry1,
160                                 struct root_info *entry2,
161                                 int is_descending)
162 {
163         int ret;
164
165         if (entry1->ogen > entry2->ogen)
166                 ret = 1;
167         else if (entry1->ogen < entry2->ogen)
168                 ret = -1;
169         else
170                 ret = 0;
171
172         return is_descending ? -ret : ret;
173 }
174
175 static int comp_entry_with_path(struct root_info *entry1,
176                                 struct root_info *entry2,
177                                 int is_descending)
178 {
179         int ret;
180
181         if (strcmp(entry1->full_path, entry2->full_path) > 0)
182                 ret = 1;
183         else if (strcmp(entry1->full_path, entry2->full_path) < 0)
184                 ret = -1;
185         else
186                 ret = 0;
187
188         return is_descending ? -ret : ret;
189 }
190
191 static btrfs_list_comp_func all_comp_funcs[] = {
192         [BTRFS_LIST_COMP_ROOTID]        = comp_entry_with_rootid,
193         [BTRFS_LIST_COMP_OGEN]          = comp_entry_with_ogen,
194         [BTRFS_LIST_COMP_GEN]           = comp_entry_with_gen,
195         [BTRFS_LIST_COMP_PATH]          = comp_entry_with_path,
196 };
197
198 static char *all_sort_items[] = {
199         [BTRFS_LIST_COMP_ROOTID]        = "rootid",
200         [BTRFS_LIST_COMP_OGEN]          = "ogen",
201         [BTRFS_LIST_COMP_GEN]           = "gen",
202         [BTRFS_LIST_COMP_PATH]          = "path",
203         [BTRFS_LIST_COMP_MAX]           = NULL,
204 };
205
206 static int  btrfs_list_get_sort_item(char *sort_name)
207 {
208         int i;
209
210         for (i = 0; i < BTRFS_LIST_COMP_MAX; i++) {
211                 if (strcmp(sort_name, all_sort_items[i]) == 0)
212                         return i;
213         }
214         return -1;
215 }
216
217 struct btrfs_list_comparer_set *btrfs_list_alloc_comparer_set(void)
218 {
219         struct btrfs_list_comparer_set *set;
220         int size;
221
222         size = sizeof(struct btrfs_list_comparer_set) +
223                BTRFS_LIST_NCOMPS_INCREASE * sizeof(struct btrfs_list_comparer);
224         set = malloc(size);
225         if (!set) {
226                 fprintf(stderr, "memory allocation failed\n");
227                 exit(1);
228         }
229
230         memset(set, 0, size);
231         set->total = BTRFS_LIST_NCOMPS_INCREASE;
232
233         return set;
234 }
235
236 void btrfs_list_free_comparer_set(struct btrfs_list_comparer_set *comp_set)
237 {
238         free(comp_set);
239 }
240
241 static int btrfs_list_setup_comparer(struct btrfs_list_comparer_set **comp_set,
242                 enum btrfs_list_comp_enum comparer, int is_descending)
243 {
244         struct btrfs_list_comparer_set *set = *comp_set;
245         int size;
246
247         BUG_ON(!set);
248         BUG_ON(comparer >= BTRFS_LIST_COMP_MAX);
249         BUG_ON(set->ncomps > set->total);
250
251         if (set->ncomps == set->total) {
252                 size = set->total + BTRFS_LIST_NCOMPS_INCREASE;
253                 size = sizeof(*set) + size * sizeof(struct btrfs_list_comparer);
254                 set = realloc(set, size);
255                 if (!set) {
256                         fprintf(stderr, "memory allocation failed\n");
257                         exit(1);
258                 }
259
260                 memset(&set->comps[set->total], 0,
261                        BTRFS_LIST_NCOMPS_INCREASE *
262                        sizeof(struct btrfs_list_comparer));
263                 set->total += BTRFS_LIST_NCOMPS_INCREASE;
264                 *comp_set = set;
265         }
266
267         BUG_ON(set->comps[set->ncomps].comp_func);
268
269         set->comps[set->ncomps].comp_func = all_comp_funcs[comparer];
270         set->comps[set->ncomps].is_descending = is_descending;
271         set->ncomps++;
272         return 0;
273 }
274
275 static int sort_comp(struct root_info *entry1, struct root_info *entry2,
276                      struct btrfs_list_comparer_set *set)
277 {
278         int rootid_compared = 0;
279         int i, ret = 0;
280
281         if (!set || !set->ncomps)
282                 goto comp_rootid;
283
284         for (i = 0; i < set->ncomps; i++) {
285                 if (!set->comps[i].comp_func)
286                         break;
287
288                 ret = set->comps[i].comp_func(entry1, entry2,
289                                               set->comps[i].is_descending);
290                 if (ret)
291                         return ret;
292
293                 if (set->comps[i].comp_func == comp_entry_with_rootid)
294                         rootid_compared = 1;
295         }
296
297         if (!rootid_compared) {
298 comp_rootid:
299                 ret = comp_entry_with_rootid(entry1, entry2, 0);
300         }
301
302         return ret;
303 }
304
305 static int sort_tree_insert(struct root_lookup *sort_tree,
306                             struct root_info *ins,
307                             struct btrfs_list_comparer_set *comp_set)
308 {
309         struct rb_node **p = &sort_tree->root.rb_node;
310         struct rb_node *parent = NULL;
311         struct root_info *curr;
312         int ret;
313
314         while (*p) {
315                 parent = *p;
316                 curr = rb_entry(parent, struct root_info, sort_node);
317
318                 ret = sort_comp(ins, curr, comp_set);
319                 if (ret < 0)
320                         p = &(*p)->rb_left;
321                 else if (ret > 0)
322                         p = &(*p)->rb_right;
323                 else
324                         return -EEXIST;
325         }
326
327         rb_link_node(&ins->sort_node, parent, p);
328         rb_insert_color(&ins->sort_node, &sort_tree->root);
329         return 0;
330 }
331
332 /*
333  * insert a new root into the tree.  returns the existing root entry
334  * if one is already there.  Both root_id and ref_tree are used
335  * as the key
336  */
337 static int root_tree_insert(struct root_lookup *root_tree,
338                             struct root_info *ins)
339 {
340         struct rb_node **p = &root_tree->root.rb_node;
341         struct rb_node * parent = NULL;
342         struct root_info *curr;
343         int ret;
344
345         while(*p) {
346                 parent = *p;
347                 curr = rb_entry(parent, struct root_info, rb_node);
348
349                 ret = comp_entry_with_rootid(ins, curr, 0);
350                 if (ret < 0)
351                         p = &(*p)->rb_left;
352                 else if (ret > 0)
353                         p = &(*p)->rb_right;
354                 else
355                         return -EEXIST;
356         }
357
358         rb_link_node(&ins->rb_node, parent, p);
359         rb_insert_color(&ins->rb_node, &root_tree->root);
360         return 0;
361 }
362
363 /*
364  * find a given root id in the tree.  We return the smallest one,
365  * rb_next can be used to move forward looking for more if required
366  */
367 static struct root_info *root_tree_search(struct root_lookup *root_tree,
368                                           u64 root_id)
369 {
370         struct rb_node *n = root_tree->root.rb_node;
371         struct root_info *entry;
372         struct root_info tmp;
373         int ret;
374
375         tmp.root_id = root_id;
376
377         while(n) {
378                 entry = rb_entry(n, struct root_info, rb_node);
379
380                 ret = comp_entry_with_rootid(&tmp, entry, 0);
381                 if (ret < 0)
382                         n = n->rb_left;
383                 else if (ret > 0)
384                         n = n->rb_right;
385                 else
386                         return entry;
387         }
388         return NULL;
389 }
390
391 static int update_root(struct root_lookup *root_lookup,
392                        u64 root_id, u64 ref_tree, u64 root_offset, u64 flags,
393                        u64 dir_id, char *name, int name_len, u64 ogen, u64 gen,
394                        time_t ot, void *uuid, void *puuid)
395 {
396         struct root_info *ri;
397
398         ri = root_tree_search(root_lookup, root_id);
399         if (!ri || ri->root_id != root_id)
400                 return -ENOENT;
401         if (name && name_len > 0) {
402                 free(ri->name);
403
404                 ri->name = malloc(name_len + 1);
405                 if (!ri->name) {
406                         fprintf(stderr, "memory allocation failed\n");
407                         exit(1);
408                 }
409                 strncpy(ri->name, name, name_len);
410                 ri->name[name_len] = 0;
411         }
412         if (ref_tree)
413                 ri->ref_tree = ref_tree;
414         if (root_offset)
415                 ri->root_offset = root_offset;
416         if (flags)
417                 ri->flags = flags;
418         if (dir_id)
419                 ri->dir_id = dir_id;
420         if (gen)
421                 ri->gen = gen;
422         if (ogen)
423                 ri->ogen = ogen;
424         if (!ri->ogen && root_offset)
425                 ri->ogen = root_offset;
426         if (ot)
427                 ri->otime = ot;
428         if (uuid)
429                 memcpy(&ri->uuid, uuid, BTRFS_UUID_SIZE);
430         if (puuid)
431                 memcpy(&ri->puuid, puuid, BTRFS_UUID_SIZE);
432
433         return 0;
434 }
435
436 /*
437  * add_root - update the existed root, or allocate a new root and insert it
438  *            into the lookup tree.
439  * root_id: object id of the root
440  * ref_tree: object id of the referring root.
441  * root_offset: offset value of the root'key
442  * dir_id: inode id of the directory in ref_tree where this root can be found.
443  * name: the name of root_id in that directory
444  * name_len: the length of name
445  * ogen: the original generation of the root
446  * gen: the current generation of the root
447  * ot: the original time(create time) of the root
448  * uuid: uuid of the root
449  * puuid: uuid of the root parent if any
450  */
451 static int add_root(struct root_lookup *root_lookup,
452                     u64 root_id, u64 ref_tree, u64 root_offset, u64 flags,
453                     u64 dir_id, char *name, int name_len, u64 ogen, u64 gen,
454                     time_t ot, void *uuid, void *puuid)
455 {
456         struct root_info *ri;
457         int ret;
458
459         ret = update_root(root_lookup, root_id, ref_tree, root_offset, flags,
460                           dir_id, name, name_len, ogen, gen, ot, uuid, puuid);
461         if (!ret)
462                 return 0;
463
464         ri = malloc(sizeof(*ri));
465         if (!ri) {
466                 printf("memory allocation failed\n");
467                 exit(1);
468         }
469         memset(ri, 0, sizeof(*ri));
470         ri->root_id = root_id;
471
472         if (name && name_len > 0) {
473                 ri->name = malloc(name_len + 1);
474                 if (!ri->name) {
475                         fprintf(stderr, "memory allocation failed\n");
476                         exit(1);
477                 }
478                 strncpy(ri->name, name, name_len);
479                 ri->name[name_len] = 0;
480         }
481         if (ref_tree)
482                 ri->ref_tree = ref_tree;
483         if (dir_id)
484                 ri->dir_id = dir_id;
485         if (root_offset)
486                 ri->root_offset = root_offset;
487         if (flags)
488                 ri->flags = flags;
489         if (gen)
490                 ri->gen = gen;
491         if (ogen)
492                 ri->ogen = ogen;
493         if (!ri->ogen && root_offset)
494                 ri->ogen = root_offset;
495         if (ot)
496                 ri->otime = ot;
497
498         if (uuid)
499                 memcpy(&ri->uuid, uuid, BTRFS_UUID_SIZE);
500
501         if (puuid)
502                 memcpy(&ri->puuid, puuid, BTRFS_UUID_SIZE);
503
504         ret = root_tree_insert(root_lookup, ri);
505         if (ret) {
506                 printf("failed to insert tree %llu\n", (unsigned long long)root_id);
507                 exit(1);
508         }
509         return 0;
510 }
511
512 static void __free_root_info(struct rb_node *node)
513 {
514         struct root_info *ri;
515
516         ri = rb_entry(node, struct root_info, rb_node);
517         free(ri->name);
518         free(ri->path);
519         free(ri->full_path);
520         free(ri);
521 }
522
523 static inline void __free_all_subvolumn(struct root_lookup *root_tree)
524 {
525         rb_free_nodes(&root_tree->root, __free_root_info);
526 }
527
528 /*
529  * for a given root_info, search through the root_lookup tree to construct
530  * the full path name to it.
531  *
532  * This can't be called until all the root_info->path fields are filled
533  * in by lookup_ino_path
534  */
535 static int resolve_root(struct root_lookup *rl, struct root_info *ri,
536                        u64 top_id)
537 {
538         char *full_path = NULL;
539         int len = 0;
540         struct root_info *found;
541
542         /*
543          * we go backwards from the root_info object and add pathnames
544          * from parent directories as we go.
545          */
546         found = ri;
547         while (1) {
548                 char *tmp;
549                 u64 next;
550                 int add_len;
551
552                 /*
553                  * ref_tree = 0 indicates the subvolumes
554                  * has been deleted.
555                  */
556                 if (!found->ref_tree) {
557                         free(full_path);
558                         return -ENOENT;
559                 }
560
561                 add_len = strlen(found->path);
562
563                 if (full_path) {
564                         /* room for / and for null */
565                         tmp = malloc(add_len + 2 + len);
566                         if (!tmp) {
567                                 perror("malloc failed");
568                                 exit(1);
569                         }
570                         memcpy(tmp + add_len + 1, full_path, len);
571                         tmp[add_len] = '/';
572                         memcpy(tmp, found->path, add_len);
573                         tmp [add_len + len + 1] = '\0';
574                         free(full_path);
575                         full_path = tmp;
576                         len += add_len + 1;
577                 } else {
578                         full_path = strdup(found->path);
579                         len = add_len;
580                 }
581
582                 next = found->ref_tree;
583
584                 if (next == top_id) {
585                         ri->top_id = top_id;
586                         break;
587                 }
588
589                 /*
590                 * if the ref_tree = BTRFS_FS_TREE_OBJECTID,
591                 * we are at the top
592                 */
593                 if (next == BTRFS_FS_TREE_OBJECTID) {
594                         ri->top_id = next;
595                         break;
596                 }
597
598                 /*
599                 * if the ref_tree wasn't in our tree of roots, the
600                 * subvolume was deleted.
601                 */
602                 found = root_tree_search(rl, next);
603                 if (!found) {
604                         free(full_path);
605                         return -ENOENT;
606                 }
607         }
608
609         ri->full_path = full_path;
610
611         return 0;
612 }
613
614 /*
615  * for a single root_info, ask the kernel to give us a path name
616  * inside it's ref_root for the dir_id where it lives.
617  *
618  * This fills in root_info->path with the path to the directory and and
619  * appends this root's name.
620  */
621 static int lookup_ino_path(int fd, struct root_info *ri)
622 {
623         struct btrfs_ioctl_ino_lookup_args args;
624         int ret, e;
625
626         if (ri->path)
627                 return 0;
628
629         if (!ri->ref_tree)
630                 return -ENOENT;
631
632         memset(&args, 0, sizeof(args));
633         args.treeid = ri->ref_tree;
634         args.objectid = ri->dir_id;
635
636         ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
637         e = errno;
638         if (ret) {
639                 if (e == ENOENT) {
640                         ri->ref_tree = 0;
641                         return -ENOENT;
642                 }
643                 fprintf(stderr, "ERROR: Failed to lookup path for root %llu - %s\n",
644                         (unsigned long long)ri->ref_tree,
645                         strerror(e));
646                 return ret;
647         }
648
649         if (args.name[0]) {
650                 /*
651                  * we're in a subdirectory of ref_tree, the kernel ioctl
652                  * puts a / in there for us
653                  */
654                 ri->path = malloc(strlen(ri->name) + strlen(args.name) + 1);
655                 if (!ri->path) {
656                         perror("malloc failed");
657                         exit(1);
658                 }
659                 strcpy(ri->path, args.name);
660                 strcat(ri->path, ri->name);
661         } else {
662                 /* we're at the root of ref_tree */
663                 ri->path = strdup(ri->name);
664                 if (!ri->path) {
665                         perror("strdup failed");
666                         exit(1);
667                 }
668         }
669         return 0;
670 }
671
672 /* finding the generation for a given path is a two step process.
673  * First we use the inode loookup routine to find out the root id
674  *
675  * Then we use the tree search ioctl to scan all the root items for a
676  * given root id and spit out the latest generation we can find
677  */
678 static u64 find_root_gen(int fd)
679 {
680         struct btrfs_ioctl_ino_lookup_args ino_args;
681         int ret;
682         struct btrfs_ioctl_search_args args;
683         struct btrfs_ioctl_search_key *sk = &args.key;
684         struct btrfs_ioctl_search_header sh;
685         unsigned long off = 0;
686         u64 max_found = 0;
687         int i;
688         int e;
689
690         memset(&ino_args, 0, sizeof(ino_args));
691         ino_args.objectid = BTRFS_FIRST_FREE_OBJECTID;
692
693         /* this ioctl fills in ino_args->treeid */
694         ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args);
695         e = errno;
696         if (ret) {
697                 fprintf(stderr, "ERROR: Failed to lookup path for dirid %llu - %s\n",
698                         (unsigned long long)BTRFS_FIRST_FREE_OBJECTID,
699                         strerror(e));
700                 return 0;
701         }
702
703         memset(&args, 0, sizeof(args));
704
705         sk->tree_id = 1;
706
707         /*
708          * there may be more than one ROOT_ITEM key if there are
709          * snapshots pending deletion, we have to loop through
710          * them.
711          */
712         sk->min_objectid = ino_args.treeid;
713         sk->max_objectid = ino_args.treeid;
714         sk->max_type = BTRFS_ROOT_ITEM_KEY;
715         sk->min_type = BTRFS_ROOT_ITEM_KEY;
716         sk->max_offset = (u64)-1;
717         sk->max_transid = (u64)-1;
718         sk->nr_items = 4096;
719
720         while (1) {
721                 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
722                 e = errno;
723                 if (ret < 0) {
724                         fprintf(stderr, "ERROR: can't perform the search - %s\n",
725                                 strerror(e));
726                         return 0;
727                 }
728                 /* the ioctl returns the number of item it found in nr_items */
729                 if (sk->nr_items == 0)
730                         break;
731
732                 off = 0;
733                 for (i = 0; i < sk->nr_items; i++) {
734                         struct btrfs_root_item *item;
735
736                         memcpy(&sh, args.buf + off, sizeof(sh));
737                         off += sizeof(sh);
738                         item = (struct btrfs_root_item *)(args.buf + off);
739                         off += sh.len;
740
741                         sk->min_objectid = sh.objectid;
742                         sk->min_type = sh.type;
743                         sk->min_offset = sh.offset;
744
745                         if (sh.objectid > ino_args.treeid)
746                                 break;
747
748                         if (sh.objectid == ino_args.treeid &&
749                             sh.type == BTRFS_ROOT_ITEM_KEY) {
750                                 max_found = max(max_found,
751                                                 btrfs_root_generation(item));
752                         }
753                 }
754                 if (sk->min_offset < (u64)-1)
755                         sk->min_offset++;
756                 else
757                         break;
758
759                 if (sk->min_type != BTRFS_ROOT_ITEM_KEY)
760                         break;
761                 if (sk->min_objectid != ino_args.treeid)
762                         break;
763         }
764         return max_found;
765 }
766
767 /* pass in a directory id and this will return
768  * the full path of the parent directory inside its
769  * subvolume root.
770  *
771  * It may return NULL if it is in the root, or an ERR_PTR if things
772  * go badly.
773  */
774 static char *__ino_resolve(int fd, u64 dirid)
775 {
776         struct btrfs_ioctl_ino_lookup_args args;
777         int ret;
778         char *full;
779         int e;
780
781         memset(&args, 0, sizeof(args));
782         args.objectid = dirid;
783
784         ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
785         e = errno;
786         if (ret) {
787                 fprintf(stderr, "ERROR: Failed to lookup path for dirid %llu - %s\n",
788                         (unsigned long long)dirid, strerror(e) );
789                 return ERR_PTR(ret);
790         }
791
792         if (args.name[0]) {
793                 /*
794                  * we're in a subdirectory of ref_tree, the kernel ioctl
795                  * puts a / in there for us
796                  */
797                 full = strdup(args.name);
798                 if (!full) {
799                         perror("malloc failed");
800                         return ERR_PTR(-ENOMEM);
801                 }
802         } else {
803                 /* we're at the root of ref_tree */
804                 full = NULL;
805         }
806         return full;
807 }
808
809 /*
810  * simple string builder, returning a new string with both
811  * dirid and name
812  */
813 static char *build_name(char *dirid, char *name)
814 {
815         char *full;
816         if (!dirid)
817                 return strdup(name);
818
819         full = malloc(strlen(dirid) + strlen(name) + 1);
820         if (!full)
821                 return NULL;
822         strcpy(full, dirid);
823         strcat(full, name);
824         return full;
825 }
826
827 /*
828  * given an inode number, this returns the full path name inside the subvolume
829  * to that file/directory.  cache_dirid and cache_name are used to
830  * cache the results so we can avoid tree searches if a later call goes
831  * to the same directory or file name
832  */
833 static char *ino_resolve(int fd, u64 ino, u64 *cache_dirid, char **cache_name)
834
835 {
836         u64 dirid;
837         char *dirname;
838         char *name;
839         char *full;
840         int ret;
841         struct btrfs_ioctl_search_args args;
842         struct btrfs_ioctl_search_key *sk = &args.key;
843         struct btrfs_ioctl_search_header *sh;
844         unsigned long off = 0;
845         int namelen;
846         int e;
847
848         memset(&args, 0, sizeof(args));
849
850         sk->tree_id = 0;
851
852         /*
853          * step one, we search for the inode back ref.  We just use the first
854          * one
855          */
856         sk->min_objectid = ino;
857         sk->max_objectid = ino;
858         sk->max_type = BTRFS_INODE_REF_KEY;
859         sk->max_offset = (u64)-1;
860         sk->min_type = BTRFS_INODE_REF_KEY;
861         sk->max_transid = (u64)-1;
862         sk->nr_items = 1;
863
864         ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
865         e = errno;
866         if (ret < 0) {
867                 fprintf(stderr, "ERROR: can't perform the search - %s\n",
868                         strerror(e));
869                 return NULL;
870         }
871         /* the ioctl returns the number of item it found in nr_items */
872         if (sk->nr_items == 0)
873                 return NULL;
874
875         off = 0;
876         sh = (struct btrfs_ioctl_search_header *)(args.buf + off);
877
878         if (sh->type == BTRFS_INODE_REF_KEY) {
879                 struct btrfs_inode_ref *ref;
880                 dirid = sh->offset;
881
882                 ref = (struct btrfs_inode_ref *)(sh + 1);
883                 namelen = btrfs_stack_inode_ref_name_len(ref);
884
885                 name = (char *)(ref + 1);
886                 name = strndup(name, namelen);
887
888                 /* use our cached value */
889                 if (dirid == *cache_dirid && *cache_name) {
890                         dirname = *cache_name;
891                         goto build;
892                 }
893         } else {
894                 return NULL;
895         }
896         /*
897          * the inode backref gives us the file name and the parent directory id.
898          * From here we use __ino_resolve to get the path to the parent
899          */
900         dirname = __ino_resolve(fd, dirid);
901 build:
902         full = build_name(dirname, name);
903         if (*cache_name && dirname != *cache_name)
904                 free(*cache_name);
905
906         *cache_name = dirname;
907         *cache_dirid = dirid;
908         free(name);
909
910         return full;
911 }
912
913 int btrfs_list_get_default_subvolume(int fd, u64 *default_id)
914 {
915         struct btrfs_ioctl_search_args args;
916         struct btrfs_ioctl_search_key *sk = &args.key;
917         struct btrfs_ioctl_search_header *sh;
918         u64 found = 0;
919         int ret;
920
921         memset(&args, 0, sizeof(args));
922
923         /*
924          * search for a dir item with a name 'default' in the tree of
925          * tree roots, it should point us to a default root
926          */
927         sk->tree_id = 1;
928
929         /* don't worry about ancient format and request only one item */
930         sk->nr_items = 1;
931
932         sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
933         sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
934         sk->max_type = BTRFS_DIR_ITEM_KEY;
935         sk->min_type = BTRFS_DIR_ITEM_KEY;
936         sk->max_offset = (u64)-1;
937         sk->max_transid = (u64)-1;
938
939         ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
940         if (ret < 0)
941                 return ret;
942
943         /* the ioctl returns the number of items it found in nr_items */
944         if (sk->nr_items == 0)
945                 goto out;
946
947         sh = (struct btrfs_ioctl_search_header *)args.buf;
948
949         if (sh->type == BTRFS_DIR_ITEM_KEY) {
950                 struct btrfs_dir_item *di;
951                 int name_len;
952                 char *name;
953
954                 di = (struct btrfs_dir_item *)(sh + 1);
955                 name_len = btrfs_stack_dir_name_len(di);
956                 name = (char *)(di + 1);
957
958                 if (!strncmp("default", name, name_len))
959                         found = btrfs_disk_key_objectid(&di->location);
960         }
961
962 out:
963         *default_id = found;
964         return 0;
965 }
966
967 static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
968 {
969         int ret;
970         struct btrfs_ioctl_search_args args;
971         struct btrfs_ioctl_search_key *sk = &args.key;
972         struct btrfs_ioctl_search_header sh;
973         struct btrfs_root_ref *ref;
974         struct btrfs_root_item *ri;
975         unsigned long off = 0;
976         int name_len;
977         char *name;
978         u64 dir_id;
979         u64 gen = 0;
980         u64 ogen;
981         u64 flags;
982         int i;
983         time_t t;
984         u8 uuid[BTRFS_UUID_SIZE];
985         u8 puuid[BTRFS_UUID_SIZE];
986
987         root_lookup_init(root_lookup);
988         memset(&args, 0, sizeof(args));
989
990         /* search in the tree of tree roots */
991         sk->tree_id = 1;
992
993         /*
994          * set the min and max to backref keys.  The search will
995          * only send back this type of key now.
996          */
997         sk->max_type = BTRFS_ROOT_BACKREF_KEY;
998         sk->min_type = BTRFS_ROOT_ITEM_KEY;
999
1000         sk->min_objectid = BTRFS_FIRST_FREE_OBJECTID;
1001
1002         /*
1003          * set all the other params to the max, we'll take any objectid
1004          * and any trans
1005          */
1006         sk->max_objectid = BTRFS_LAST_FREE_OBJECTID;
1007         sk->max_offset = (u64)-1;
1008         sk->max_transid = (u64)-1;
1009
1010         /* just a big number, doesn't matter much */
1011         sk->nr_items = 4096;
1012
1013         while(1) {
1014                 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
1015                 if (ret < 0)
1016                         return ret;
1017                 /* the ioctl returns the number of item it found in nr_items */
1018                 if (sk->nr_items == 0)
1019                         break;
1020
1021                 off = 0;
1022
1023                 /*
1024                  * for each item, pull the key out of the header and then
1025                  * read the root_ref item it contains
1026                  */
1027                 for (i = 0; i < sk->nr_items; i++) {
1028                         memcpy(&sh, args.buf + off, sizeof(sh));
1029                         off += sizeof(sh);
1030                         if (sh.type == BTRFS_ROOT_BACKREF_KEY) {
1031                                 ref = (struct btrfs_root_ref *)(args.buf + off);
1032                                 name_len = btrfs_stack_root_ref_name_len(ref);
1033                                 name = (char *)(ref + 1);
1034                                 dir_id = btrfs_stack_root_ref_dirid(ref);
1035
1036                                 add_root(root_lookup, sh.objectid, sh.offset,
1037                                          0, 0, dir_id, name, name_len, 0, 0, 0,
1038                                          NULL, NULL);
1039                         } else if (sh.type == BTRFS_ROOT_ITEM_KEY) {
1040                                 ri = (struct btrfs_root_item *)(args.buf + off);
1041                                 gen = btrfs_root_generation(ri);
1042                                 flags = btrfs_root_flags(ri);
1043                                 if(sh.len >
1044                                    sizeof(struct btrfs_root_item_v0)) {
1045                                         t = btrfs_stack_timespec_sec(&ri->otime);
1046                                         ogen = btrfs_root_otransid(ri);
1047                                         memcpy(uuid, ri->uuid, BTRFS_UUID_SIZE);
1048                                         memcpy(puuid, ri->parent_uuid, BTRFS_UUID_SIZE);
1049                                 } else {
1050                                         t = 0;
1051                                         ogen = 0;
1052                                         memset(uuid, 0, BTRFS_UUID_SIZE);
1053                                         memset(puuid, 0, BTRFS_UUID_SIZE);
1054                                 }
1055
1056                                 add_root(root_lookup, sh.objectid, 0,
1057                                          sh.offset, flags, 0, NULL, 0, ogen,
1058                                          gen, t, uuid, puuid);
1059                         }
1060
1061                         off += sh.len;
1062
1063                         /*
1064                          * record the mins in sk so we can make sure the
1065                          * next search doesn't repeat this root
1066                          */
1067                         sk->min_objectid = sh.objectid;
1068                         sk->min_type = sh.type;
1069                         sk->min_offset = sh.offset;
1070                 }
1071                 sk->nr_items = 4096;
1072                 sk->min_offset++;
1073                 if (!sk->min_offset)    /* overflow */
1074                         sk->min_type++;
1075                 else
1076                         continue;
1077
1078                 if (sk->min_type > BTRFS_ROOT_BACKREF_KEY) {
1079                         sk->min_type = BTRFS_ROOT_ITEM_KEY;
1080                         sk->min_objectid++;
1081                 } else
1082                         continue;
1083
1084                 if (sk->min_objectid > sk->max_objectid)
1085                         break;
1086         }
1087
1088         return 0;
1089 }
1090
1091 static int filter_by_rootid(struct root_info *ri, u64 data)
1092 {
1093         return ri->root_id == data;
1094 }
1095
1096 static int filter_snapshot(struct root_info *ri, u64 data)
1097 {
1098         return !!ri->root_offset;
1099 }
1100
1101 static int filter_flags(struct root_info *ri, u64 flags)
1102 {
1103         return ri->flags & flags;
1104 }
1105
1106 static int filter_gen_more(struct root_info *ri, u64 data)
1107 {
1108         return ri->gen >= data;
1109 }
1110
1111 static int filter_gen_less(struct root_info *ri, u64 data)
1112 {
1113         return ri->gen <= data;
1114 }
1115
1116 static int filter_gen_equal(struct root_info  *ri, u64 data)
1117 {
1118         return ri->gen == data;
1119 }
1120
1121 static int filter_cgen_more(struct root_info *ri, u64 data)
1122 {
1123         return ri->ogen >= data;
1124 }
1125
1126 static int filter_cgen_less(struct root_info *ri, u64 data)
1127 {
1128         return ri->ogen <= data;
1129 }
1130
1131 static int filter_cgen_equal(struct root_info *ri, u64 data)
1132 {
1133         return ri->ogen == data;
1134 }
1135
1136 static int filter_topid_equal(struct root_info *ri, u64 data)
1137 {
1138         return ri->top_id == data;
1139 }
1140
1141 static int filter_full_path(struct root_info *ri, u64 data)
1142 {
1143         if (ri->full_path && ri->top_id != data) {
1144                 char *tmp;
1145                 char p[] = "<FS_TREE>";
1146                 int add_len = strlen(p);
1147                 int len = strlen(ri->full_path);
1148
1149                 tmp = malloc(len + add_len + 2);
1150                 if (!tmp) {
1151                         fprintf(stderr, "memory allocation failed\n");
1152                         exit(1);
1153                 }
1154                 memcpy(tmp + add_len + 1, ri->full_path, len);
1155                 tmp[len + add_len + 1] = '\0';
1156                 tmp[add_len] = '/';
1157                 memcpy(tmp, p, add_len);
1158                 free(ri->full_path);
1159                 ri->full_path = tmp;
1160         }
1161         return 1;
1162 }
1163
1164 static int filter_by_parent(struct root_info *ri, u64 data)
1165 {
1166         return !uuid_compare(ri->puuid, (u8 *)(unsigned long)data);
1167 }
1168
1169 static int filter_deleted(struct root_info *ri, u64 data)
1170 {
1171         return ri->deleted;
1172 }
1173
1174 static btrfs_list_filter_func all_filter_funcs[] = {
1175         [BTRFS_LIST_FILTER_ROOTID]              = filter_by_rootid,
1176         [BTRFS_LIST_FILTER_SNAPSHOT_ONLY]       = filter_snapshot,
1177         [BTRFS_LIST_FILTER_FLAGS]               = filter_flags,
1178         [BTRFS_LIST_FILTER_GEN_MORE]            = filter_gen_more,
1179         [BTRFS_LIST_FILTER_GEN_LESS]            = filter_gen_less,
1180         [BTRFS_LIST_FILTER_GEN_EQUAL]           = filter_gen_equal,
1181         [BTRFS_LIST_FILTER_CGEN_MORE]           = filter_cgen_more,
1182         [BTRFS_LIST_FILTER_CGEN_LESS]           = filter_cgen_less,
1183         [BTRFS_LIST_FILTER_CGEN_EQUAL]          = filter_cgen_equal,
1184         [BTRFS_LIST_FILTER_TOPID_EQUAL]         = filter_topid_equal,
1185         [BTRFS_LIST_FILTER_FULL_PATH]           = filter_full_path,
1186         [BTRFS_LIST_FILTER_BY_PARENT]           = filter_by_parent,
1187         [BTRFS_LIST_FILTER_DELETED]             = filter_deleted,
1188 };
1189
1190 struct btrfs_list_filter_set *btrfs_list_alloc_filter_set(void)
1191 {
1192         struct btrfs_list_filter_set *set;
1193         int size;
1194
1195         size = sizeof(struct btrfs_list_filter_set) +
1196                BTRFS_LIST_NFILTERS_INCREASE * sizeof(struct btrfs_list_filter);
1197         set = malloc(size);
1198         if (!set) {
1199                 fprintf(stderr, "memory allocation failed\n");
1200                 exit(1);
1201         }
1202
1203         memset(set, 0, size);
1204         set->total = BTRFS_LIST_NFILTERS_INCREASE;
1205
1206         return set;
1207 }
1208
1209 void btrfs_list_free_filter_set(struct btrfs_list_filter_set *filter_set)
1210 {
1211         free(filter_set);
1212 }
1213
1214 int btrfs_list_setup_filter(struct btrfs_list_filter_set **filter_set,
1215                             enum btrfs_list_filter_enum filter, u64 data)
1216 {
1217         struct btrfs_list_filter_set *set = *filter_set;
1218         int size;
1219
1220         BUG_ON(!set);
1221         BUG_ON(filter >= BTRFS_LIST_FILTER_MAX);
1222         BUG_ON(set->nfilters > set->total);
1223
1224         if (filter == BTRFS_LIST_FILTER_DELETED) {
1225                 set->only_deleted = 1;
1226                 return 0;
1227         }
1228
1229         if (set->nfilters == set->total) {
1230                 size = set->total + BTRFS_LIST_NFILTERS_INCREASE;
1231                 size = sizeof(*set) + size * sizeof(struct btrfs_list_filter);
1232                 set = realloc(set, size);
1233                 if (!set) {
1234                         fprintf(stderr, "memory allocation failed\n");
1235                         exit(1);
1236                 }
1237
1238                 memset(&set->filters[set->total], 0,
1239                        BTRFS_LIST_NFILTERS_INCREASE *
1240                        sizeof(struct btrfs_list_filter));
1241                 set->total += BTRFS_LIST_NFILTERS_INCREASE;
1242                 *filter_set = set;
1243         }
1244
1245         BUG_ON(set->filters[set->nfilters].filter_func);
1246
1247         set->filters[set->nfilters].filter_func = all_filter_funcs[filter];
1248         set->filters[set->nfilters].data = data;
1249         set->nfilters++;
1250         return 0;
1251 }
1252
1253 static int filter_root(struct root_info *ri,
1254                        struct btrfs_list_filter_set *set)
1255 {
1256         int i, ret;
1257
1258         if (!set || !set->nfilters)
1259                 return 1;
1260
1261         if (set->only_deleted && !ri->deleted)
1262                 return 0;
1263
1264         if (!set->only_deleted && ri->deleted)
1265                 return 0;
1266
1267         for (i = 0; i < set->nfilters; i++) {
1268                 if (!set->filters[i].filter_func)
1269                         break;
1270                 ret = set->filters[i].filter_func(ri, set->filters[i].data);
1271                 if (!ret)
1272                         return 0;
1273         }
1274         return 1;
1275 }
1276
1277 static void __filter_and_sort_subvol(struct root_lookup *all_subvols,
1278                                     struct root_lookup *sort_tree,
1279                                     struct btrfs_list_filter_set *filter_set,
1280                                     struct btrfs_list_comparer_set *comp_set,
1281                                     u64 top_id)
1282 {
1283         struct rb_node *n;
1284         struct root_info *entry;
1285         int ret;
1286
1287         root_lookup_init(sort_tree);
1288
1289         n = rb_last(&all_subvols->root);
1290         while (n) {
1291                 entry = rb_entry(n, struct root_info, rb_node);
1292
1293                 ret = resolve_root(all_subvols, entry, top_id);
1294                 if (ret == -ENOENT) {
1295                         entry->full_path = strdup("DELETED");
1296                         entry->deleted = 1;
1297                 }
1298                 ret = filter_root(entry, filter_set);
1299                 if (ret)
1300                         sort_tree_insert(sort_tree, entry, comp_set);
1301                 n = rb_prev(n);
1302         }
1303 }
1304
1305 static int __list_subvol_fill_paths(int fd, struct root_lookup *root_lookup)
1306 {
1307         struct rb_node *n;
1308
1309         n = rb_first(&root_lookup->root);
1310         while (n) {
1311                 struct root_info *entry;
1312                 int ret;
1313                 entry = rb_entry(n, struct root_info, rb_node);
1314                 ret = lookup_ino_path(fd, entry);
1315                 if (ret && ret != -ENOENT)
1316                         return ret;
1317                 n = rb_next(n);
1318         }
1319
1320         return 0;
1321 }
1322
1323 static void print_subvolume_column(struct root_info *subv,
1324                                    enum btrfs_list_column_enum column)
1325 {
1326         char tstr[256];
1327         char uuidparse[BTRFS_UUID_UNPARSED_SIZE];
1328
1329         BUG_ON(column >= BTRFS_LIST_ALL || column < 0);
1330
1331         switch (column) {
1332         case BTRFS_LIST_OBJECTID:
1333                 printf("%llu", subv->root_id);
1334                 break;
1335         case BTRFS_LIST_GENERATION:
1336                 printf("%llu", subv->gen);
1337                 break;
1338         case BTRFS_LIST_OGENERATION:
1339                 printf("%llu", subv->ogen);
1340                 break;
1341         case BTRFS_LIST_PARENT:
1342                 printf("%llu", subv->ref_tree);
1343                 break;
1344         case BTRFS_LIST_TOP_LEVEL:
1345                 printf("%llu", subv->top_id);
1346                 break;
1347         case BTRFS_LIST_OTIME:
1348                 if (subv->otime) {
1349                         struct tm tm;
1350
1351                         localtime_r(&subv->otime, &tm);
1352                         strftime(tstr, 256, "%Y-%m-%d %X", &tm);
1353                 } else
1354                         strcpy(tstr, "-");
1355                 printf("%s", tstr);
1356                 break;
1357         case BTRFS_LIST_UUID:
1358                 if (uuid_is_null(subv->uuid))
1359                         strcpy(uuidparse, "-");
1360                 else
1361                         uuid_unparse(subv->uuid, uuidparse);
1362                 printf("%s", uuidparse);
1363                 break;
1364         case BTRFS_LIST_PUUID:
1365                 if (uuid_is_null(subv->puuid))
1366                         strcpy(uuidparse, "-");
1367                 else
1368                         uuid_unparse(subv->puuid, uuidparse);
1369                 printf("%s", uuidparse);
1370                 break;
1371         case BTRFS_LIST_PATH:
1372                 BUG_ON(!subv->full_path);
1373                 printf("%s", subv->full_path);
1374                 break;
1375         default:
1376                 break;
1377         }
1378 }
1379
1380 static void print_single_volume_info_raw(struct root_info *subv, char *raw_prefix)
1381 {
1382         int i;
1383
1384         for (i = 0; i < BTRFS_LIST_ALL; i++) {
1385                 if (!btrfs_list_columns[i].need_print)
1386                         continue;
1387
1388                 if (raw_prefix)
1389                         printf("%s",raw_prefix);
1390
1391                 print_subvolume_column(subv, i);
1392         }
1393         printf("\n");
1394 }
1395
1396 static void print_single_volume_info_table(struct root_info *subv)
1397 {
1398         int i;
1399
1400         for (i = 0; i < BTRFS_LIST_ALL; i++) {
1401                 if (!btrfs_list_columns[i].need_print)
1402                         continue;
1403
1404                 print_subvolume_column(subv, i);
1405
1406                 if (i != BTRFS_LIST_PATH)
1407                         printf("\t");
1408
1409                 if (i == BTRFS_LIST_TOP_LEVEL)
1410                         printf("\t");
1411         }
1412         printf("\n");
1413 }
1414
1415 static void print_single_volume_info_default(struct root_info *subv)
1416 {
1417         int i;
1418
1419         for (i = 0; i < BTRFS_LIST_ALL; i++) {
1420                 if (!btrfs_list_columns[i].need_print)
1421                         continue;
1422
1423                 printf("%s ", btrfs_list_columns[i].name);
1424                 print_subvolume_column(subv, i);
1425
1426                 if (i != BTRFS_LIST_PATH)
1427                         printf(" ");
1428         }
1429         printf("\n");
1430 }
1431
1432 static void print_all_volume_info_tab_head(void)
1433 {
1434         int i;
1435         int len;
1436         char barrier[20];
1437
1438         for (i = 0; i < BTRFS_LIST_ALL; i++) {
1439                 if (btrfs_list_columns[i].need_print)
1440                         printf("%s\t", btrfs_list_columns[i].name);
1441
1442                 if (i == BTRFS_LIST_ALL-1)
1443                         printf("\n");
1444         }
1445
1446         for (i = 0; i < BTRFS_LIST_ALL; i++) {
1447                 memset(barrier, 0, sizeof(barrier));
1448
1449                 if (btrfs_list_columns[i].need_print) {
1450                         len = strlen(btrfs_list_columns[i].name);
1451                         while (len--)
1452                                 strcat(barrier, "-");
1453
1454                         printf("%s\t", barrier);
1455                 }
1456                 if (i == BTRFS_LIST_ALL-1)
1457                         printf("\n");
1458         }
1459 }
1460
1461 static void print_all_volume_info(struct root_lookup *sorted_tree,
1462                                   int layout, char *raw_prefix)
1463 {
1464         struct rb_node *n;
1465         struct root_info *entry;
1466
1467         if (layout == BTRFS_LIST_LAYOUT_TABLE)
1468                 print_all_volume_info_tab_head();
1469
1470         n = rb_first(&sorted_tree->root);
1471         while (n) {
1472                 entry = rb_entry(n, struct root_info, sort_node);
1473                 switch (layout) {
1474                 case BTRFS_LIST_LAYOUT_DEFAULT:
1475                         print_single_volume_info_default(entry);
1476                         break;
1477                 case BTRFS_LIST_LAYOUT_TABLE:
1478                         print_single_volume_info_table(entry);
1479                         break;
1480                 case BTRFS_LIST_LAYOUT_RAW:
1481                         print_single_volume_info_raw(entry, raw_prefix);
1482                         break;
1483                 }
1484                 n = rb_next(n);
1485         }
1486 }
1487
1488 static int btrfs_list_subvols(int fd, struct root_lookup *root_lookup)
1489 {
1490         int ret;
1491
1492         ret = __list_subvol_search(fd, root_lookup);
1493         if (ret) {
1494                 fprintf(stderr, "ERROR: can't perform the search - %s\n",
1495                                 strerror(errno));
1496                 return ret;
1497         }
1498
1499         /*
1500          * now we have an rbtree full of root_info objects, but we need to fill
1501          * in their path names within the subvol that is referencing each one.
1502          */
1503         ret = __list_subvol_fill_paths(fd, root_lookup);
1504         return ret;
1505 }
1506
1507 int btrfs_list_subvols_print(int fd, struct btrfs_list_filter_set *filter_set,
1508                        struct btrfs_list_comparer_set *comp_set,
1509                        int layout, int full_path, char *raw_prefix)
1510 {
1511         struct root_lookup root_lookup;
1512         struct root_lookup root_sort;
1513         int ret = 0;
1514         u64 top_id = 0;
1515
1516         if (full_path)
1517                 ret = btrfs_list_get_path_rootid(fd, &top_id);
1518         if (ret)
1519                 return ret;
1520
1521         ret = btrfs_list_subvols(fd, &root_lookup);
1522         if (ret)
1523                 return ret;
1524         __filter_and_sort_subvol(&root_lookup, &root_sort, filter_set,
1525                                  comp_set, top_id);
1526
1527         print_all_volume_info(&root_sort, layout, raw_prefix);
1528         __free_all_subvolumn(&root_lookup);
1529
1530         return 0;
1531 }
1532
1533 static char *strdup_or_null(const char *s)
1534 {
1535         if (!s)
1536                 return NULL;
1537         return strdup(s);
1538 }
1539
1540 int btrfs_get_subvol(int fd, struct root_info *the_ri)
1541 {
1542         int ret, rr;
1543         struct root_lookup rl;
1544         struct rb_node *rbn;
1545         struct root_info *ri;
1546         u64 root_id;
1547
1548         ret = btrfs_list_get_path_rootid(fd, &root_id);
1549         if (ret)
1550                 return ret;
1551
1552         ret = btrfs_list_subvols(fd, &rl);
1553         if (ret)
1554                 return ret;
1555
1556         rbn = rb_first(&rl.root);
1557         while(rbn) {
1558                 ri = rb_entry(rbn, struct root_info, rb_node);
1559                 rr = resolve_root(&rl, ri, root_id);
1560                 if (rr == -ENOENT) {
1561                         ret = -ENOENT;
1562                         rbn = rb_next(rbn);
1563                         continue;
1564                 }
1565                 if (!comp_entry_with_rootid(the_ri, ri, 0)) {
1566                         memcpy(the_ri, ri, offsetof(struct root_info, path));
1567                         the_ri->path = strdup_or_null(ri->path);
1568                         the_ri->name = strdup_or_null(ri->name);
1569                         the_ri->full_path = strdup_or_null(ri->full_path);
1570                         ret = 0;
1571                         break;
1572                 }
1573                 rbn = rb_next(rbn);
1574         }
1575         __free_all_subvolumn(&rl);
1576         return ret;
1577 }
1578
1579 static int print_one_extent(int fd, struct btrfs_ioctl_search_header *sh,
1580                             struct btrfs_file_extent_item *item,
1581                             u64 found_gen, u64 *cache_dirid,
1582                             char **cache_dir_name, u64 *cache_ino,
1583                             char **cache_full_name)
1584 {
1585         u64 len = 0;
1586         u64 disk_start = 0;
1587         u64 disk_offset = 0;
1588         u8 type;
1589         int compressed = 0;
1590         int flags = 0;
1591         char *name = NULL;
1592
1593         if (sh->objectid == *cache_ino) {
1594                 name = *cache_full_name;
1595         } else if (*cache_full_name) {
1596                 free(*cache_full_name);
1597                 *cache_full_name = NULL;
1598         }
1599         if (!name) {
1600                 name = ino_resolve(fd, sh->objectid, cache_dirid,
1601                                    cache_dir_name);
1602                 *cache_full_name = name;
1603                 *cache_ino = sh->objectid;
1604         }
1605         if (!name)
1606                 return -EIO;
1607
1608         type = btrfs_stack_file_extent_type(item);
1609         compressed = btrfs_stack_file_extent_compression(item);
1610
1611         if (type == BTRFS_FILE_EXTENT_REG ||
1612             type == BTRFS_FILE_EXTENT_PREALLOC) {
1613                 disk_start = btrfs_stack_file_extent_disk_bytenr(item);
1614                 disk_offset = btrfs_stack_file_extent_offset(item);
1615                 len = btrfs_stack_file_extent_num_bytes(item);
1616         } else if (type == BTRFS_FILE_EXTENT_INLINE) {
1617                 disk_start = 0;
1618                 disk_offset = 0;
1619                 len = btrfs_stack_file_extent_ram_bytes(item);
1620         } else {
1621                 printf("unhandled extent type %d for inode %llu "
1622                        "file offset %llu gen %llu\n",
1623                         type,
1624                         (unsigned long long)sh->objectid,
1625                         (unsigned long long)sh->offset,
1626                         (unsigned long long)found_gen);
1627
1628                 return -EIO;
1629         }
1630         printf("inode %llu file offset %llu len %llu disk start %llu "
1631                "offset %llu gen %llu flags ",
1632                (unsigned long long)sh->objectid,
1633                (unsigned long long)sh->offset,
1634                (unsigned long long)len,
1635                (unsigned long long)disk_start,
1636                (unsigned long long)disk_offset,
1637                (unsigned long long)found_gen);
1638
1639         if (compressed) {
1640                 printf("COMPRESS");
1641                 flags++;
1642         }
1643         if (type == BTRFS_FILE_EXTENT_PREALLOC) {
1644                 printf("%sPREALLOC", flags ? "|" : "");
1645                 flags++;
1646         }
1647         if (type == BTRFS_FILE_EXTENT_INLINE) {
1648                 printf("%sINLINE", flags ? "|" : "");
1649                 flags++;
1650         }
1651         if (!flags)
1652                 printf("NONE");
1653
1654         printf(" %s\n", name);
1655         return 0;
1656 }
1657
1658 int btrfs_list_find_updated_files(int fd, u64 root_id, u64 oldest_gen)
1659 {
1660         int ret;
1661         struct btrfs_ioctl_search_args args;
1662         struct btrfs_ioctl_search_key *sk = &args.key;
1663         struct btrfs_ioctl_search_header sh;
1664         struct btrfs_file_extent_item *item;
1665         unsigned long off = 0;
1666         u64 found_gen;
1667         u64 max_found = 0;
1668         int i;
1669         int e;
1670         u64 cache_dirid = 0;
1671         u64 cache_ino = 0;
1672         char *cache_dir_name = NULL;
1673         char *cache_full_name = NULL;
1674         struct btrfs_file_extent_item backup;
1675
1676         memset(&backup, 0, sizeof(backup));
1677         memset(&args, 0, sizeof(args));
1678
1679         sk->tree_id = root_id;
1680
1681         /*
1682          * set all the other params to the max, we'll take any objectid
1683          * and any trans
1684          */
1685         sk->max_objectid = (u64)-1;
1686         sk->max_offset = (u64)-1;
1687         sk->max_transid = (u64)-1;
1688         sk->max_type = BTRFS_EXTENT_DATA_KEY;
1689         sk->min_transid = oldest_gen;
1690         /* just a big number, doesn't matter much */
1691         sk->nr_items = 4096;
1692
1693         max_found = find_root_gen(fd);
1694         while(1) {
1695                 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
1696                 e = errno;
1697                 if (ret < 0) {
1698                         fprintf(stderr, "ERROR: can't perform the search- %s\n",
1699                                 strerror(e));
1700                         break;
1701                 }
1702                 /* the ioctl returns the number of item it found in nr_items */
1703                 if (sk->nr_items == 0)
1704                         break;
1705
1706                 off = 0;
1707
1708                 /*
1709                  * for each item, pull the key out of the header and then
1710                  * read the root_ref item it contains
1711                  */
1712                 for (i = 0; i < sk->nr_items; i++) {
1713                         memcpy(&sh, args.buf + off, sizeof(sh));
1714                         off += sizeof(sh);
1715
1716                         /*
1717                          * just in case the item was too big, pass something other
1718                          * than garbage
1719                          */
1720                         if (sh.len == 0)
1721                                 item = &backup;
1722                         else
1723                                 item = (struct btrfs_file_extent_item *)(args.buf +
1724                                                                  off);
1725                         found_gen = btrfs_stack_file_extent_generation(item);
1726                         if (sh.type == BTRFS_EXTENT_DATA_KEY &&
1727                             found_gen >= oldest_gen) {
1728                                 print_one_extent(fd, &sh, item, found_gen,
1729                                                  &cache_dirid, &cache_dir_name,
1730                                                  &cache_ino, &cache_full_name);
1731                         }
1732                         off += sh.len;
1733
1734                         /*
1735                          * record the mins in sk so we can make sure the
1736                          * next search doesn't repeat this root
1737                          */
1738                         sk->min_objectid = sh.objectid;
1739                         sk->min_offset = sh.offset;
1740                         sk->min_type = sh.type;
1741                 }
1742                 sk->nr_items = 4096;
1743                 if (sk->min_offset < (u64)-1)
1744                         sk->min_offset++;
1745                 else if (sk->min_objectid < (u64)-1) {
1746                         sk->min_objectid++;
1747                         sk->min_offset = 0;
1748                         sk->min_type = 0;
1749                 } else
1750                         break;
1751         }
1752         free(cache_dir_name);
1753         free(cache_full_name);
1754         printf("transid marker was %llu\n", (unsigned long long)max_found);
1755         return ret;
1756 }
1757
1758 char *btrfs_list_path_for_root(int fd, u64 root)
1759 {
1760         struct root_lookup root_lookup;
1761         struct rb_node *n;
1762         char *ret_path = NULL;
1763         int ret;
1764         u64 top_id;
1765
1766         ret = btrfs_list_get_path_rootid(fd, &top_id);
1767         if (ret)
1768                 return ERR_PTR(ret);
1769
1770         ret = __list_subvol_search(fd, &root_lookup);
1771         if (ret < 0)
1772                 return ERR_PTR(ret);
1773
1774         ret = __list_subvol_fill_paths(fd, &root_lookup);
1775         if (ret < 0)
1776                 return ERR_PTR(ret);
1777
1778         n = rb_last(&root_lookup.root);
1779         while (n) {
1780                 struct root_info *entry;
1781
1782                 entry = rb_entry(n, struct root_info, rb_node);
1783                 ret = resolve_root(&root_lookup, entry, top_id);
1784                 if (ret == -ENOENT && entry->root_id == root) {
1785                         ret_path = NULL;
1786                         break;
1787                 }
1788                 if (entry->root_id == root) {
1789                         ret_path = entry->full_path;
1790                         entry->full_path = NULL;
1791                 }
1792
1793                 n = rb_prev(n);
1794         }
1795         __free_all_subvolumn(&root_lookup);
1796
1797         return ret_path;
1798 }
1799
1800 int btrfs_list_parse_sort_string(char *opt_arg,
1801                                  struct btrfs_list_comparer_set **comps)
1802 {
1803         int order;
1804         int flag;
1805         char *p;
1806         char **ptr_argv;
1807         int what_to_sort;
1808
1809         while ((p = strtok(opt_arg, ",")) != NULL) {
1810                 flag = 0;
1811                 ptr_argv = all_sort_items;
1812
1813                 while (*ptr_argv) {
1814                         if (strcmp(*ptr_argv, p) == 0) {
1815                                 flag = 1;
1816                                 break;
1817                         } else {
1818                                 p++;
1819                                 if (strcmp(*ptr_argv, p) == 0) {
1820                                         flag = 1;
1821                                         p--;
1822                                         break;
1823                                 }
1824                                 p--;
1825                         }
1826                         ptr_argv++;
1827                 }
1828
1829                 if (flag == 0)
1830                         return -1;
1831
1832                 else {
1833                         if (*p == '+') {
1834                                 order = 0;
1835                                 p++;
1836                         } else if (*p == '-') {
1837                                 order = 1;
1838                                 p++;
1839                         } else
1840                                 order = 0;
1841
1842                         what_to_sort = btrfs_list_get_sort_item(p);
1843                         btrfs_list_setup_comparer(comps, what_to_sort, order);
1844                 }
1845                 opt_arg = NULL;
1846         }
1847
1848         return 0;
1849 }
1850
1851 /*
1852  * This function is used to parse the argument of filter condition.
1853  *
1854  * type is the filter object.
1855  */
1856 int btrfs_list_parse_filter_string(char *opt_arg,
1857                                    struct btrfs_list_filter_set **filters,
1858                                    enum btrfs_list_filter_enum type)
1859 {
1860
1861         u64 arg;
1862         char *ptr_parse_end = NULL;
1863         char *ptr_opt_arg_end = opt_arg + strlen(opt_arg);
1864
1865         switch (*(opt_arg++)) {
1866         case '+':
1867                 arg = (u64)strtol(opt_arg, &ptr_parse_end, 10);
1868                 type += 2;
1869                 if (ptr_parse_end != ptr_opt_arg_end)
1870                         return -1;
1871
1872                 btrfs_list_setup_filter(filters, type, arg);
1873                 break;
1874         case '-':
1875                 arg = (u64)strtoll(opt_arg, &ptr_parse_end, 10);
1876                 type += 1;
1877                 if (ptr_parse_end != ptr_opt_arg_end)
1878                         return -1;
1879
1880                 btrfs_list_setup_filter(filters, type, arg);
1881                 break;
1882         default:
1883                 opt_arg--;
1884                 arg = (u64)strtoll(opt_arg, &ptr_parse_end, 10);
1885
1886                 if (ptr_parse_end != ptr_opt_arg_end)
1887                         return -1;
1888                 btrfs_list_setup_filter(filters, type, arg);
1889                 break;
1890         }
1891
1892         return 0;
1893 }
1894
1895 int btrfs_list_get_path_rootid(int fd, u64 *treeid)
1896 {
1897         int  ret;
1898         struct btrfs_ioctl_ino_lookup_args args;
1899
1900         memset(&args, 0, sizeof(args));
1901         args.objectid = BTRFS_FIRST_FREE_OBJECTID;
1902
1903         ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
1904         if (ret < 0) {
1905                 fprintf(stderr,
1906                         "ERROR: can't perform the search -%s\n",
1907                         strerror(errno));
1908                 return ret;
1909         }
1910         *treeid = args.treeid;
1911         return 0;
1912 }