1a8daad2308ec277700a746cc03d89ff01ee3720
[platform/upstream/btrfs-progs.git] / dir-item.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "kerncompat.h"
4 #include "radix-tree.h"
5 #include "ctree.h"
6 #include "disk-io.h"
7 #include "hash.h"
8 #include "transaction.h"
9
10 int insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root
11                             *root, struct btrfs_path *path, struct btrfs_key
12                             *cpu_key, u32 data_size)
13 {
14         int overflow;
15         int ret;
16
17         ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
18         overflow = btrfs_key_overflow(cpu_key);
19
20         while(ret == -EEXIST && overflow < BTRFS_KEY_OVERFLOW_MAX) {
21                 overflow++;
22                 btrfs_set_key_overflow(cpu_key, overflow);
23                 btrfs_release_path(root, path);
24                 ret = btrfs_insert_empty_item(trans, root, path, cpu_key,
25                                               data_size);
26         }
27         return ret;
28 }
29
30 int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
31                           *root, char *name, int name_len, u64 dir,
32                           struct btrfs_key *location, u8 type)
33 {
34         int ret = 0;
35         struct btrfs_path path;
36         struct btrfs_dir_item *dir_item;
37         char *name_ptr;
38         struct btrfs_key key;
39         u32 data_size;
40
41         key.objectid = dir;
42         key.flags = 0;
43         btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
44         if (name_len == 1 && *name == '.')
45                 key.offset = 1;
46         else if (name_len == 2 && name[0] == '.' && name[1] == '.')
47                 key.offset = 2;
48         else
49                 ret = btrfs_name_hash(name, name_len, &key.offset);
50         BUG_ON(ret);
51         btrfs_init_path(&path);
52         data_size = sizeof(*dir_item) + name_len;
53         ret = insert_with_overflow(trans, root, &path, &key, data_size);
54         if (ret)
55                 goto out;
56
57         dir_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0],
58                                   struct btrfs_dir_item);
59         btrfs_cpu_key_to_disk(&dir_item->location, location);
60         btrfs_set_dir_type(dir_item, type);
61         btrfs_set_dir_flags(dir_item, 0);
62         btrfs_set_dir_name_len(dir_item, name_len);
63         name_ptr = (char *)(dir_item + 1);
64         memcpy(name_ptr, name, name_len);
65 out:
66         btrfs_release_path(root, &path);
67         return ret;
68 }
69
70 int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
71                           *root, struct btrfs_path *path, u64 dir, char *name,
72                           int name_len, int mod)
73 {
74         int ret;
75         struct btrfs_key key;
76         int ins_len = mod < 0 ? -1 : 0;
77         int cow = mod != 0;
78
79         key.objectid = dir;
80         key.flags = 0;
81         btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
82         ret = btrfs_name_hash(name, name_len, &key.offset);
83         BUG_ON(ret);
84         ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
85         return ret;
86 }
87
88 int btrfs_match_dir_item_name(struct btrfs_root *root,
89                               struct btrfs_path *path, char
90                               *name, int name_len)
91 {
92         struct btrfs_dir_item *dir_item;
93         char *name_ptr;
94
95         dir_item = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0],
96                                   struct btrfs_dir_item);
97         if (btrfs_dir_name_len(dir_item) != name_len)
98                 return 0;
99         name_ptr = (char *)(dir_item + 1);
100         if (memcmp(name_ptr, name, name_len))
101                 return 0;
102         return 1;
103 }