1 #include "ext4_config.h"
2 #include "ext4_types.h"
4 #include "ext4_errno.h"
5 #include "ext4_blockdev.h"
6 #include "ext4_super.h"
7 #include "ext4_debug.h"
8 #include "ext4_block_group.h"
9 #include "ext4_balloc.h"
10 #include "ext4_inode.h"
11 #include "ext4_extent.h"
16 static int ext4_xattr_item_cmp(struct ext4_xattr_item *a,
17 struct ext4_xattr_item *b)
20 result = a->name_index - b->name_index;
24 result = a->name_len - b->name_len;
28 return memcmp(a->name, b->name, a->name_len);
31 RB_GENERATE_INTERNAL(ext4_xattr_tree,
37 static struct ext4_xattr_item *
38 ext4_xattr_item_alloc(uint8_t name_index,
42 struct ext4_xattr_item *item;
43 item = malloc(sizeof(struct ext4_xattr_item) +
48 item->name_index = name_index;
49 item->name = (char *)(item + 1);
50 item->name_len = name_len;
54 memset(&item->node, 0, sizeof(item->node));
55 memcpy(item->name, name, name_len);
61 ext4_xattr_item_alloc_data(struct ext4_xattr_item *item,
66 ext4_assert(!item->data);
67 data = malloc(data_size);
72 memcpy(data, orig_data, data_size);
75 item->data_size = data_size;
80 ext4_xattr_item_free_data(struct ext4_xattr_item *item)
82 ext4_assert(item->data);
89 ext4_xattr_item_resize_data(struct ext4_xattr_item *item,
92 if (new_data_size != item->data_size) {
94 new_data = realloc(item->data, new_data_size);
98 item->data = new_data;
99 item->data_size = new_data_size;
105 ext4_xattr_item_free(struct ext4_xattr_item *item)
108 ext4_xattr_item_free_data(item);
114 static void *ext4_xattr_entry_data(struct ext4_xattr_ref *xattr_ref,
115 struct ext4_xattr_entry *entry,
120 struct ext4_xattr_ibody_header *header;
121 struct ext4_xattr_entry *first_entry;
122 uint16_t inode_size = ext4_get16(&xattr_ref->fs->sb,
124 header = EXT4_XATTR_IHDR(xattr_ref->inode_ref->inode);
125 first_entry = EXT4_XATTR_IFIRST(header);
127 ret = (void *)((char *)first_entry + to_le16(entry->e_value_offs));
128 if ((char *)ret + EXT4_XATTR_SIZE(to_le32(entry->e_value_size))
129 - (char *)xattr_ref->inode_ref->inode >
134 uint32_t block_size =
135 ext4_sb_get_block_size(&xattr_ref->fs->sb);
136 ret = (void *)((char *)xattr_ref->block.data +
137 to_le16(entry->e_value_offs));
138 if ((char *)ret + EXT4_XATTR_SIZE(to_le32(entry->e_value_size))
139 - (char *)xattr_ref->block.data >
146 static int ext4_xattr_block_fetch(struct ext4_xattr_ref *xattr_ref)
151 struct ext4_xattr_entry *entry = NULL;
153 ext4_assert(xattr_ref->block.data);
154 entry = EXT4_XATTR_BFIRST(&xattr_ref->block);
156 size_rem = ext4_sb_get_block_size(&xattr_ref->fs->sb);
157 for(;size_rem > 0 && !EXT4_XATTR_IS_LAST_ENTRY(entry);
158 entry = EXT4_XATTR_NEXT(entry),
159 size_rem -= EXT4_XATTR_LEN(entry->e_name_len)) {
160 struct ext4_xattr_item *item;
161 char *e_name = (char *)(entry + 1);
163 data = ext4_xattr_entry_data(xattr_ref, entry,
170 item = ext4_xattr_item_alloc(entry->e_name_index,
172 (size_t)entry->e_name_len);
177 if (ext4_xattr_item_alloc_data(item,
179 to_le32(entry->e_value_size))
181 ext4_xattr_item_free(item);
185 RB_INSERT(ext4_xattr_tree, &xattr_ref->root, item);
193 static int ext4_xattr_inode_fetch(struct ext4_xattr_ref *xattr_ref)
198 struct ext4_xattr_ibody_header *header = NULL;
199 struct ext4_xattr_entry *entry = NULL;
200 uint16_t inode_size = ext4_get16(&xattr_ref->fs->sb,
203 header = EXT4_XATTR_IHDR(xattr_ref->inode_ref->inode);
204 entry = EXT4_XATTR_IFIRST(header);
206 size_rem = inode_size -
207 EXT4_GOOD_OLD_INODE_SIZE -
208 xattr_ref->inode_ref->inode->extra_isize;
209 for(;size_rem > 0 && !EXT4_XATTR_IS_LAST_ENTRY(entry);
210 entry = EXT4_XATTR_NEXT(entry),
211 size_rem -= EXT4_XATTR_LEN(entry->e_name_len)) {
212 struct ext4_xattr_item *item;
213 char *e_name = (char *)(entry + 1);
215 data = ext4_xattr_entry_data(xattr_ref, entry,
222 item = ext4_xattr_item_alloc(entry->e_name_index,
224 (size_t)entry->e_name_len);
229 if (ext4_xattr_item_alloc_data(item,
231 to_le32(entry->e_value_size))
233 ext4_xattr_item_free(item);
237 RB_INSERT(ext4_xattr_tree, &xattr_ref->root, item);
244 static int ext4_xattr_fetch(struct ext4_xattr_ref *xattr_ref)
247 uint16_t inode_size = ext4_get16(&xattr_ref->fs->sb,
249 if (inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
250 ret = ext4_xattr_inode_fetch(xattr_ref);
256 if (xattr_ref->block_loaded)
257 ret = ext4_xattr_block_fetch(xattr_ref);
259 xattr_ref->dirty = false;
264 ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref)
266 struct ext4_xattr_item *item, *save_item;
267 RB_FOREACH_SAFE(item,
271 RB_REMOVE(ext4_xattr_tree, &xattr_ref->root, item);
272 ext4_xattr_item_free(item);
274 xattr_ref->ea_size = 0;
277 int ext4_fs_get_xattr_ref(struct ext4_fs *fs,
278 struct ext4_inode_ref *inode_ref,
279 struct ext4_xattr_ref *ref)
282 uint64_t xattr_block;
283 xattr_block = ext4_inode_get_file_acl(inode_ref->inode,
287 rc = ext4_block_get(fs->bdev,
288 &inode_ref->block, xattr_block);
292 ref->block_loaded = true;
294 ref->block_loaded = false;
296 ref->inode_ref = inode_ref;
299 rc = ext4_xattr_fetch(ref);
301 ext4_xattr_purge_items(ref);
303 ext4_block_set(fs->bdev, &inode_ref->block);
305 ref->block_loaded = false;
311 void ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref)
313 if (ref->block_loaded) {
314 ext4_block_set(ref->fs->bdev, &ref->block);
315 ref->block_loaded = false;
317 ext4_xattr_purge_items(ref);
318 ref->inode_ref = NULL;