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 (ext4_xattr_tree,
36 static struct ext4_xattr_item *
37 ext4_xattr_item_alloc(uint8_t name_index,
41 struct ext4_xattr_item *item;
42 item = malloc(sizeof(struct ext4_xattr_item) +
47 item->name_index = name_index;
48 item->name = (char *)(item + 1);
49 item->name_len = name_len;
53 memset(&item->node, 0, sizeof(item->node));
54 memcpy(item->name, name, name_len);
60 ext4_xattr_item_alloc_data(struct ext4_xattr_item *item,
65 ext4_assert(!item->data);
66 data = malloc(data_size);
71 memcpy(data, orig_data, data_size);
74 item->data_size = data_size;
79 ext4_xattr_item_free_data(struct ext4_xattr_item *item)
81 ext4_assert(item->data);
88 ext4_xattr_item_resize_data(struct ext4_xattr_item *item,
91 if (new_data_size != item->data_size) {
93 new_data = realloc(item->data, new_data_size);
97 item->data = new_data;
98 item->data_size = new_data_size;
104 ext4_xattr_item_free(struct ext4_xattr_item *item)
107 ext4_xattr_item_free_data(item);
113 static void *ext4_xattr_entry_data(struct ext4_xattr_ref *xattr_ref,
114 struct ext4_xattr_entry *entry,
119 struct ext4_xattr_ibody_header *header;
120 struct ext4_xattr_entry *first_entry;
121 uint16_t inode_size = ext4_get16(&xattr_ref->fs->sb,
123 header = EXT4_XATTR_IHDR(xattr_ref->inode_ref->inode);
124 first_entry = EXT4_XATTR_IFIRST(header);
126 ret = (void *)((char *)first_entry + to_le16(entry->e_value_offs));
127 if ((char *)ret + EXT4_XATTR_SIZE(to_le32(entry->e_value_size))
128 - (char *)xattr_ref->inode_ref->inode >
133 uint32_t block_size =
134 ext4_sb_get_block_size(&xattr_ref->fs->sb);
135 ret = (void *)((char *)xattr_ref->block.data +
136 to_le16(entry->e_value_offs));
137 if ((char *)ret + EXT4_XATTR_SIZE(to_le32(entry->e_value_size))
138 - (char *)xattr_ref->block.data >
145 static int ext4_xattr_block_fetch(struct ext4_xattr_ref *xattr_ref)
150 struct ext4_xattr_entry *entry = NULL;
152 ext4_assert(xattr_ref->block.data);
153 entry = EXT4_XATTR_BFIRST(&xattr_ref->block);
155 size_rem = ext4_sb_get_block_size(&xattr_ref->fs->sb);
156 for(;size_rem > 0 && !EXT4_XATTR_IS_LAST_ENTRY(entry);
157 entry = EXT4_XATTR_NEXT(entry),
158 size_rem -= EXT4_XATTR_LEN(entry->e_name_len)) {
159 struct ext4_xattr_item *item;
160 char *e_name = (char *)(entry + 1);
162 data = ext4_xattr_entry_data(xattr_ref, entry,
169 item = ext4_xattr_item_alloc(entry->e_name_index,
171 (size_t)entry->e_name_len);
176 if (ext4_xattr_item_alloc_data(item,
178 to_le32(entry->e_value_size))
180 ext4_xattr_item_free(item);
184 RB_INSERT(ext4_xattr_tree, &xattr_ref->root, item);
192 static int ext4_xattr_inode_fetch(struct ext4_xattr_ref *xattr_ref)
197 struct ext4_xattr_ibody_header *header = NULL;
198 struct ext4_xattr_entry *entry = NULL;
199 uint16_t inode_size = ext4_get16(&xattr_ref->fs->sb,
202 header = EXT4_XATTR_IHDR(xattr_ref->inode_ref->inode);
203 entry = EXT4_XATTR_IFIRST(header);
205 size_rem = inode_size -
206 EXT4_GOOD_OLD_INODE_SIZE -
207 xattr_ref->inode_ref->inode->extra_isize;
208 for(;size_rem > 0 && !EXT4_XATTR_IS_LAST_ENTRY(entry);
209 entry = EXT4_XATTR_NEXT(entry),
210 size_rem -= EXT4_XATTR_LEN(entry->e_name_len)) {
211 struct ext4_xattr_item *item;
212 char *e_name = (char *)(entry + 1);
214 data = ext4_xattr_entry_data(xattr_ref, entry,
221 item = ext4_xattr_item_alloc(entry->e_name_index,
223 (size_t)entry->e_name_len);
228 if (ext4_xattr_item_alloc_data(item,
230 to_le32(entry->e_value_size))
232 ext4_xattr_item_free(item);
236 RB_INSERT(ext4_xattr_tree, &xattr_ref->root, item);
243 static int ext4_xattr_fetch(struct ext4_xattr_ref *xattr_ref)
246 uint16_t inode_size = ext4_get16(&xattr_ref->fs->sb,
248 if (inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
249 ret = ext4_xattr_inode_fetch(xattr_ref);
255 if (xattr_ref->block_loaded)
256 ret = ext4_xattr_block_fetch(xattr_ref);
258 xattr_ref->dirty = false;
263 ext4_xattr_purge_items(struct ext4_xattr_ref *xattr_ref)
265 struct ext4_xattr_item *item, *save_item;
266 RB_FOREACH_SAFE(item,
270 RB_REMOVE(ext4_xattr_tree, &xattr_ref->root, item);
271 ext4_xattr_item_free(item);
273 xattr_ref->ea_size = 0;
276 int ext4_fs_get_xattr_ref(struct ext4_fs *fs,
277 struct ext4_inode_ref *inode_ref,
278 struct ext4_xattr_ref *ref)
281 uint64_t xattr_block;
282 xattr_block = ext4_inode_get_file_acl(inode_ref->inode,
286 rc = ext4_block_get(fs->bdev,
287 &inode_ref->block, xattr_block);
291 ref->block_loaded = true;
293 ref->block_loaded = false;
295 ref->inode_ref = inode_ref;
298 rc = ext4_xattr_fetch(ref);
300 ext4_xattr_purge_items(ref);
302 ext4_block_set(fs->bdev, &inode_ref->block);
304 ref->block_loaded = false;
310 void ext4_fs_put_xattr_ref(struct ext4_xattr_ref *ref)
312 if (ref->block_loaded) {
313 ext4_block_set(ref->fs->bdev, &ref->block);
314 ref->block_loaded = false;
316 ext4_xattr_purge_items(ref);
317 ref->inode_ref = NULL;