Home | History | Annotate | Download | only in ext2fs
      1 /*
      2  * ext_attr.c --- extended attribute blocks
      3  *
      4  * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher (at) computer.org>
      5  *
      6  * Copyright (C) 2002 Theodore Ts'o.
      7  *
      8  * %Begin-Header%
      9  * This file may be redistributed under the terms of the GNU Library
     10  * General Public License, version 2.
     11  * %End-Header%
     12  */
     13 
     14 #include "config.h"
     15 #include <stdio.h>
     16 #if HAVE_UNISTD_H
     17 #include <unistd.h>
     18 #endif
     19 #include <string.h>
     20 #include <time.h>
     21 
     22 #include "ext2_fs.h"
     23 #include "ext2_ext_attr.h"
     24 #include "ext4_acl.h"
     25 
     26 #include "ext2fs.h"
     27 
     28 static errcode_t read_ea_inode_hash(ext2_filsys fs, ext2_ino_t ino, __u32 *hash)
     29 {
     30 	struct ext2_inode inode;
     31 	errcode_t retval;
     32 
     33 	retval = ext2fs_read_inode(fs, ino, &inode);
     34 	if (retval)
     35 		return retval;
     36 	*hash = ext2fs_get_ea_inode_hash(&inode);
     37 	return 0;
     38 }
     39 
     40 #define NAME_HASH_SHIFT 5
     41 #define VALUE_HASH_SHIFT 16
     42 
     43 /*
     44  * ext2_xattr_hash_entry()
     45  *
     46  * Compute the hash of an extended attribute.
     47  */
     48 __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data)
     49 {
     50 	__u32 hash = 0;
     51 	char *name = ((char *) entry) + sizeof(struct ext2_ext_attr_entry);
     52 	int n;
     53 
     54 	for (n = 0; n < entry->e_name_len; n++) {
     55 		hash = (hash << NAME_HASH_SHIFT) ^
     56 		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
     57 		       *name++;
     58 	}
     59 
     60 	/* The hash needs to be calculated on the data in little-endian. */
     61 	if (entry->e_value_inum == 0 && entry->e_value_size != 0) {
     62 		__u32 *value = (__u32 *)data;
     63 		for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >>
     64 			 EXT2_EXT_ATTR_PAD_BITS; n; n--) {
     65 			hash = (hash << VALUE_HASH_SHIFT) ^
     66 			       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
     67 			       ext2fs_le32_to_cpu(*value++);
     68 		}
     69 	}
     70 
     71 	return hash;
     72 }
     73 
     74 /*
     75  * ext2fs_ext_attr_hash_entry2()
     76  *
     77  * Compute the hash of an extended attribute.
     78  * This version of the function supports hashing entries that reference
     79  * external inodes (ea_inode feature).
     80  */
     81 errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs,
     82 				      struct ext2_ext_attr_entry *entry,
     83 				      void *data, __u32 *hash)
     84 {
     85 	*hash = ext2fs_ext_attr_hash_entry(entry, data);
     86 
     87 	if (entry->e_value_inum) {
     88 		__u32 ea_inode_hash;
     89 		errcode_t retval;
     90 
     91 		retval = read_ea_inode_hash(fs, entry->e_value_inum,
     92 					    &ea_inode_hash);
     93 		if (retval)
     94 			return retval;
     95 
     96 		*hash = (*hash << VALUE_HASH_SHIFT) ^
     97 			(*hash >> (8*sizeof(*hash) - VALUE_HASH_SHIFT)) ^
     98 			ea_inode_hash;
     99 	}
    100 	return 0;
    101 }
    102 
    103 #undef NAME_HASH_SHIFT
    104 #undef VALUE_HASH_SHIFT
    105 
    106 #define BLOCK_HASH_SHIFT 16
    107 
    108 /* Mirrors ext4_xattr_rehash() implementation in kernel. */
    109 void ext2fs_ext_attr_block_rehash(struct ext2_ext_attr_header *header,
    110 				  struct ext2_ext_attr_entry *end)
    111 {
    112 	struct ext2_ext_attr_entry *here;
    113 	__u32 hash = 0;
    114 
    115 	here = (struct ext2_ext_attr_entry *)(header+1);
    116 	while (here < end && !EXT2_EXT_IS_LAST_ENTRY(here)) {
    117 		if (!here->e_hash) {
    118 			/* Block is not shared if an entry's hash value == 0 */
    119 			hash = 0;
    120 			break;
    121 		}
    122 		hash = (hash << BLOCK_HASH_SHIFT) ^
    123 		       (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^
    124 		       here->e_hash;
    125 		here = EXT2_EXT_ATTR_NEXT(here);
    126 	}
    127 	header->h_hash = hash;
    128 }
    129 
    130 #undef BLOCK_HASH_SHIFT
    131 
    132 __u32 ext2fs_get_ea_inode_hash(struct ext2_inode *inode)
    133 {
    134 	return inode->i_atime;
    135 }
    136 
    137 void ext2fs_set_ea_inode_hash(struct ext2_inode *inode, __u32 hash)
    138 {
    139 	inode->i_atime = hash;
    140 }
    141 
    142 __u64 ext2fs_get_ea_inode_ref(struct ext2_inode *inode)
    143 {
    144 	return ((__u64)inode->i_ctime << 32) | inode->osd1.linux1.l_i_version;
    145 }
    146 
    147 void ext2fs_set_ea_inode_ref(struct ext2_inode *inode, __u64 ref_count)
    148 {
    149 	inode->i_ctime = (__u32)(ref_count >> 32);
    150 	inode->osd1.linux1.l_i_version = (__u32)ref_count;
    151 }
    152 
    153 static errcode_t check_ext_attr_header(struct ext2_ext_attr_header *header)
    154 {
    155 	if ((header->h_magic != EXT2_EXT_ATTR_MAGIC_v1 &&
    156 	     header->h_magic != EXT2_EXT_ATTR_MAGIC) ||
    157 	    header->h_blocks != 1)
    158 		return EXT2_ET_BAD_EA_HEADER;
    159 
    160 	return 0;
    161 }
    162 
    163 errcode_t ext2fs_read_ext_attr3(ext2_filsys fs, blk64_t block, void *buf,
    164 				ext2_ino_t inum)
    165 {
    166 	int		csum_failed = 0;
    167 	errcode_t	retval;
    168 
    169 	retval = io_channel_read_blk64(fs->io, block, 1, buf);
    170 	if (retval)
    171 		return retval;
    172 
    173 	if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
    174 	    !ext2fs_ext_attr_block_csum_verify(fs, inum, block, buf))
    175 		csum_failed = 1;
    176 
    177 #ifdef WORDS_BIGENDIAN
    178 	ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
    179 #endif
    180 
    181 	retval = check_ext_attr_header(buf);
    182 	if (retval == 0 && csum_failed)
    183 		retval = EXT2_ET_EXT_ATTR_CSUM_INVALID;
    184 
    185 	return retval;
    186 }
    187 
    188 errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf)
    189 {
    190 	return ext2fs_read_ext_attr3(fs, block, buf, 0);
    191 }
    192 
    193 errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
    194 {
    195 	return ext2fs_read_ext_attr2(fs, block, buf);
    196 }
    197 
    198 errcode_t ext2fs_write_ext_attr3(ext2_filsys fs, blk64_t block, void *inbuf,
    199 				 ext2_ino_t inum)
    200 {
    201 	errcode_t	retval;
    202 	char		*write_buf;
    203 
    204 #ifdef WORDS_BIGENDIAN
    205 	retval = ext2fs_get_mem(fs->blocksize, &write_buf);
    206 	if (retval)
    207 		return retval;
    208 	ext2fs_swap_ext_attr(write_buf, inbuf, fs->blocksize, 1);
    209 #else
    210 	write_buf = (char *) inbuf;
    211 #endif
    212 
    213 	retval = ext2fs_ext_attr_block_csum_set(fs, inum, block,
    214 			(struct ext2_ext_attr_header *)write_buf);
    215 	if (retval)
    216 		return retval;
    217 
    218 	retval = io_channel_write_blk64(fs->io, block, 1, write_buf);
    219 #ifdef WORDS_BIGENDIAN
    220 	ext2fs_free_mem(&write_buf);
    221 #endif
    222 	if (!retval)
    223 		ext2fs_mark_changed(fs);
    224 	return retval;
    225 }
    226 
    227 errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, void *inbuf)
    228 {
    229 	return ext2fs_write_ext_attr3(fs, block, inbuf, 0);
    230 }
    231 
    232 errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
    233 {
    234 	return ext2fs_write_ext_attr2(fs, block, inbuf);
    235 }
    236 
    237 /*
    238  * This function adjusts the reference count of the EA block.
    239  */
    240 errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk,
    241 				    char *block_buf, int adjust,
    242 				    __u32 *newcount, ext2_ino_t inum)
    243 {
    244 	errcode_t	retval;
    245 	struct ext2_ext_attr_header *header;
    246 	char	*buf = 0;
    247 
    248 	if ((blk >= ext2fs_blocks_count(fs->super)) ||
    249 	    (blk < fs->super->s_first_data_block))
    250 		return EXT2_ET_BAD_EA_BLOCK_NUM;
    251 
    252 	if (!block_buf) {
    253 		retval = ext2fs_get_mem(fs->blocksize, &buf);
    254 		if (retval)
    255 			return retval;
    256 		block_buf = buf;
    257 	}
    258 
    259 	retval = ext2fs_read_ext_attr3(fs, blk, block_buf, inum);
    260 	if (retval)
    261 		goto errout;
    262 
    263 	header = (struct ext2_ext_attr_header *) block_buf;
    264 	header->h_refcount += adjust;
    265 	if (newcount)
    266 		*newcount = header->h_refcount;
    267 
    268 	retval = ext2fs_write_ext_attr3(fs, blk, block_buf, inum);
    269 	if (retval)
    270 		goto errout;
    271 
    272 errout:
    273 	if (buf)
    274 		ext2fs_free_mem(&buf);
    275 	return retval;
    276 }
    277 
    278 errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
    279 				    char *block_buf, int adjust,
    280 				    __u32 *newcount)
    281 {
    282 	return ext2fs_adjust_ea_refcount3(fs, blk, block_buf, adjust,
    283 					  newcount, 0);
    284 }
    285 
    286 errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
    287 					char *block_buf, int adjust,
    288 					__u32 *newcount)
    289 {
    290 	return ext2fs_adjust_ea_refcount2(fs, blk, block_buf, adjust,
    291 					  newcount);
    292 }
    293 
    294 /* Manipulate the contents of extended attribute regions */
    295 struct ext2_xattr {
    296 	char *name;
    297 	void *value;
    298 	unsigned int value_len;
    299 	ext2_ino_t ea_ino;
    300 };
    301 
    302 struct ext2_xattr_handle {
    303 	errcode_t magic;
    304 	ext2_filsys fs;
    305 	struct ext2_xattr *attrs;
    306 	int capacity;
    307 	int count;
    308 	int ibody_count;
    309 	ext2_ino_t ino;
    310 	unsigned int flags;
    311 };
    312 
    313 static errcode_t ext2fs_xattrs_expand(struct ext2_xattr_handle *h,
    314 				      unsigned int expandby)
    315 {
    316 	struct ext2_xattr *new_attrs;
    317 	errcode_t err;
    318 
    319 	err = ext2fs_get_arrayzero(h->capacity + expandby,
    320 				   sizeof(struct ext2_xattr), &new_attrs);
    321 	if (err)
    322 		return err;
    323 
    324 	memcpy(new_attrs, h->attrs, h->capacity * sizeof(struct ext2_xattr));
    325 	ext2fs_free_mem(&h->attrs);
    326 	h->capacity += expandby;
    327 	h->attrs = new_attrs;
    328 
    329 	return 0;
    330 }
    331 
    332 struct ea_name_index {
    333 	int index;
    334 	const char *name;
    335 };
    336 
    337 /* Keep these names sorted in order of decreasing specificity. */
    338 static struct ea_name_index ea_names[] = {
    339 	{3, "system.posix_acl_default"},
    340 	{2, "system.posix_acl_access"},
    341 	{8, "system.richacl"},
    342 	{6, "security."},
    343 	{4, "trusted."},
    344 	{7, "system."},
    345 	{1, "user."},
    346 	{0, NULL},
    347 };
    348 
    349 static const char *find_ea_prefix(int index)
    350 {
    351 	struct ea_name_index *e;
    352 
    353 	for (e = ea_names; e->name; e++)
    354 		if (e->index == index)
    355 			return e->name;
    356 
    357 	return NULL;
    358 }
    359 
    360 static int find_ea_index(const char *fullname, const char **name, int *index)
    361 {
    362 	struct ea_name_index *e;
    363 
    364 	for (e = ea_names; e->name; e++) {
    365 		if (strncmp(fullname, e->name, strlen(e->name)) == 0) {
    366 			*name = fullname + strlen(e->name);
    367 			*index = e->index;
    368 			return 1;
    369 		}
    370 	}
    371 	return 0;
    372 }
    373 
    374 errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino,
    375 			       struct ext2_inode_large *inode)
    376 {
    377 	struct ext2_ext_attr_header *header;
    378 	void *block_buf = NULL;
    379 	blk64_t blk;
    380 	errcode_t err;
    381 	struct ext2_inode_large i;
    382 
    383 	/* Read inode? */
    384 	if (inode == NULL) {
    385 		err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&i,
    386 					     sizeof(struct ext2_inode_large));
    387 		if (err)
    388 			return err;
    389 		inode = &i;
    390 	}
    391 
    392 	/* Do we already have an EA block? */
    393 	blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
    394 	if (blk == 0)
    395 		return 0;
    396 
    397 	/* Find block, zero it, write back */
    398 	if ((blk < fs->super->s_first_data_block) ||
    399 	    (blk >= ext2fs_blocks_count(fs->super))) {
    400 		err = EXT2_ET_BAD_EA_BLOCK_NUM;
    401 		goto out;
    402 	}
    403 
    404 	err = ext2fs_get_mem(fs->blocksize, &block_buf);
    405 	if (err)
    406 		goto out;
    407 
    408 	err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino);
    409 	if (err)
    410 		goto out2;
    411 
    412 	/* We only know how to deal with v2 EA blocks */
    413 	header = (struct ext2_ext_attr_header *) block_buf;
    414 	if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
    415 		err = EXT2_ET_BAD_EA_HEADER;
    416 		goto out2;
    417 	}
    418 
    419 	header->h_refcount--;
    420 	err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino);
    421 	if (err)
    422 		goto out2;
    423 
    424 	/* Erase link to block */
    425 	ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, 0);
    426 	if (header->h_refcount == 0)
    427 		ext2fs_block_alloc_stats2(fs, blk, -1);
    428 	err = ext2fs_iblk_sub_blocks(fs, (struct ext2_inode *)inode, 1);
    429 	if (err)
    430 		goto out2;
    431 
    432 	/* Write inode? */
    433 	if (inode == &i) {
    434 		err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&i,
    435 					      sizeof(struct ext2_inode_large));
    436 		if (err)
    437 			goto out2;
    438 	}
    439 
    440 out2:
    441 	ext2fs_free_mem(&block_buf);
    442 out:
    443 	return err;
    444 }
    445 
    446 static errcode_t prep_ea_block_for_write(ext2_filsys fs, ext2_ino_t ino,
    447 					 struct ext2_inode_large *inode)
    448 {
    449 	struct ext2_ext_attr_header *header;
    450 	void *block_buf = NULL;
    451 	blk64_t blk, goal;
    452 	errcode_t err;
    453 
    454 	/* Do we already have an EA block? */
    455 	blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
    456 	if (blk != 0) {
    457 		if ((blk < fs->super->s_first_data_block) ||
    458 		    (blk >= ext2fs_blocks_count(fs->super))) {
    459 			err = EXT2_ET_BAD_EA_BLOCK_NUM;
    460 			goto out;
    461 		}
    462 
    463 		err = ext2fs_get_mem(fs->blocksize, &block_buf);
    464 		if (err)
    465 			goto out;
    466 
    467 		err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino);
    468 		if (err)
    469 			goto out2;
    470 
    471 		/* We only know how to deal with v2 EA blocks */
    472 		header = (struct ext2_ext_attr_header *) block_buf;
    473 		if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
    474 			err = EXT2_ET_BAD_EA_HEADER;
    475 			goto out2;
    476 		}
    477 
    478 		/* Single-user block.  We're done here. */
    479 		if (header->h_refcount == 1)
    480 			goto out2;
    481 
    482 		/* We need to CoW the block. */
    483 		header->h_refcount--;
    484 		err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino);
    485 		if (err)
    486 			goto out2;
    487 	} else {
    488 		/* No block, we must increment i_blocks */
    489 		err = ext2fs_iblk_add_blocks(fs, (struct ext2_inode *)inode,
    490 					     1);
    491 		if (err)
    492 			goto out;
    493 	}
    494 
    495 	/* Allocate a block */
    496 	goal = ext2fs_find_inode_goal(fs, ino, (struct ext2_inode *)inode, 0);
    497 	err = ext2fs_alloc_block2(fs, goal, NULL, &blk);
    498 	if (err)
    499 		goto out2;
    500 	ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, blk);
    501 out2:
    502 	if (block_buf)
    503 		ext2fs_free_mem(&block_buf);
    504 out:
    505 	return err;
    506 }
    507 
    508 
    509 static inline int
    510 posix_acl_xattr_count(size_t size)
    511 {
    512         if (size < sizeof(posix_acl_xattr_header))
    513                 return -1;
    514         size -= sizeof(posix_acl_xattr_header);
    515         if (size % sizeof(posix_acl_xattr_entry))
    516                 return -1;
    517         return size / sizeof(posix_acl_xattr_entry);
    518 }
    519 
    520 /*
    521  * The lgetxattr function returns data formatted in the POSIX extended
    522  * attribute format.  The on-disk format uses a more compact encoding.
    523  * See the ext4_acl_to_disk in fs/ext4/acl.c.
    524  */
    525 static errcode_t convert_posix_acl_to_disk_buffer(const void *value, size_t size,
    526 						  void *out_buf, size_t *size_out)
    527 {
    528 	const posix_acl_xattr_header *header =
    529 		(const posix_acl_xattr_header*) value;
    530 	const posix_acl_xattr_entry *end, *entry =
    531 		(const posix_acl_xattr_entry *)(header+1);
    532 	ext4_acl_header *ext_acl;
    533 	size_t s;
    534 	char *e;
    535 
    536 	int count;
    537 
    538 	if (!value)
    539 		return EINVAL;
    540 	if (size < sizeof(posix_acl_xattr_header))
    541 		return ENOMEM;
    542 	if (header->a_version != ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION))
    543 		return EINVAL;
    544 
    545 	count = posix_acl_xattr_count(size);
    546 	ext_acl = out_buf;
    547 	ext_acl->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION);
    548 
    549 	if (count <= 0)
    550 		return EINVAL;
    551 
    552 	e = (char *) out_buf + sizeof(ext4_acl_header);
    553 	s = sizeof(ext4_acl_header);
    554 	for (end = entry + count; entry != end;entry++) {
    555 		ext4_acl_entry *disk_entry = (ext4_acl_entry*) e;
    556 		disk_entry->e_tag = ext2fs_cpu_to_le16(entry->e_tag);
    557 		disk_entry->e_perm = ext2fs_cpu_to_le16(entry->e_perm);
    558 
    559 		switch(entry->e_tag) {
    560 			case ACL_USER_OBJ:
    561 			case ACL_GROUP_OBJ:
    562 			case ACL_MASK:
    563 			case ACL_OTHER:
    564 				e += sizeof(ext4_acl_entry_short);
    565 				s += sizeof(ext4_acl_entry_short);
    566 				break;
    567 			case ACL_USER:
    568 			case ACL_GROUP:
    569 				disk_entry->e_id =  ext2fs_cpu_to_le32(entry->e_id);
    570 				e += sizeof(ext4_acl_entry);
    571 				s += sizeof(ext4_acl_entry);
    572 				break;
    573 		}
    574 	}
    575 	*size_out = s;
    576 	return 0;
    577 }
    578 
    579 static errcode_t convert_disk_buffer_to_posix_acl(const void *value, size_t size,
    580 						  void **out_buf, size_t *size_out)
    581 {
    582 	posix_acl_xattr_header *header;
    583 	posix_acl_xattr_entry *entry;
    584 	const ext4_acl_header *ext_acl = (const ext4_acl_header *) value;
    585 	errcode_t err;
    586 	const char *cp;
    587 	char *out;
    588 
    589 	if ((!value) ||
    590 	    (size < sizeof(ext4_acl_header)) ||
    591 	    (ext_acl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION)))
    592 		return EINVAL;
    593 
    594 	err = ext2fs_get_mem(size * 2, &out);
    595 	if (err)
    596 		return err;
    597 
    598 	header = (posix_acl_xattr_header *) out;
    599 	header->a_version = ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION);
    600 	entry = (posix_acl_xattr_entry *) (out + sizeof(posix_acl_xattr_header));
    601 
    602 	cp = (const char *) value + sizeof(ext4_acl_header);
    603 	size -= sizeof(ext4_acl_header);
    604 
    605 	while (size > 0) {
    606 		const ext4_acl_entry *disk_entry = (const ext4_acl_entry *) cp;
    607 
    608 		entry->e_tag = ext2fs_le16_to_cpu(disk_entry->e_tag);
    609 		entry->e_perm = ext2fs_le16_to_cpu(disk_entry->e_perm);
    610 
    611 		switch(entry->e_tag) {
    612 			case ACL_USER_OBJ:
    613 			case ACL_GROUP_OBJ:
    614 			case ACL_MASK:
    615 			case ACL_OTHER:
    616 				entry->e_id = 0;
    617 				cp += sizeof(ext4_acl_entry_short);
    618 				size -= sizeof(ext4_acl_entry_short);
    619 				break;
    620 			case ACL_USER:
    621 			case ACL_GROUP:
    622 				entry->e_id = ext2fs_le32_to_cpu(disk_entry->e_id);
    623 				cp += sizeof(ext4_acl_entry);
    624 				size -= sizeof(ext4_acl_entry);
    625 				break;
    626 		default:
    627 			ext2fs_free_mem(&out);
    628 			return EINVAL;
    629 			break;
    630 		}
    631 		entry++;
    632 	}
    633 	*out_buf = out;
    634 	*size_out = ((char *) entry - out);
    635 	return 0;
    636 }
    637 
    638 static errcode_t
    639 write_xattrs_to_buffer(ext2_filsys fs, struct ext2_xattr *attrs, int count,
    640 		       void *entries_start, unsigned int storage_size,
    641 		       unsigned int value_offset_correction, int write_hash)
    642 {
    643 	struct ext2_xattr *x;
    644 	struct ext2_ext_attr_entry *e = entries_start;
    645 	char *end = (char *) entries_start + storage_size;
    646 	const char *shortname;
    647 	unsigned int value_size;
    648 	int idx, ret;
    649 	errcode_t err;
    650 
    651 	memset(entries_start, 0, storage_size);
    652 	for (x = attrs; x < attrs + count; x++) {
    653 		/* Calculate index and shortname position */
    654 		shortname = x->name;
    655 		ret = find_ea_index(x->name, &shortname, &idx);
    656 
    657 		value_size = ((x->value_len + EXT2_EXT_ATTR_PAD - 1) /
    658 			      EXT2_EXT_ATTR_PAD) * EXT2_EXT_ATTR_PAD;
    659 
    660 		/* Fill out e appropriately */
    661 		e->e_name_len = strlen(shortname);
    662 		e->e_name_index = (ret ? idx : 0);
    663 
    664 		e->e_value_size = x->value_len;
    665 		e->e_value_inum = x->ea_ino;
    666 
    667 		/* Store name */
    668 		memcpy((char *)e + sizeof(*e), shortname, e->e_name_len);
    669 		if (x->ea_ino) {
    670 			e->e_value_offs = 0;
    671 		} else {
    672 			end -= value_size;
    673 			e->e_value_offs = end - (char *) entries_start +
    674 						value_offset_correction;
    675 			memcpy(end, x->value, e->e_value_size);
    676 		}
    677 
    678 		if (write_hash || x->ea_ino) {
    679 			err = ext2fs_ext_attr_hash_entry2(fs, e,
    680 							  x->ea_ino ? 0 : end,
    681 							  &e->e_hash);
    682 			if (err)
    683 				return err;
    684 		} else
    685 			e->e_hash = 0;
    686 
    687 		e = EXT2_EXT_ATTR_NEXT(e);
    688 		*(__u32 *)e = 0;
    689 	}
    690 	return 0;
    691 }
    692 
    693 errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle)
    694 {
    695 	ext2_filsys fs = handle->fs;
    696 	const unsigned int inode_size = EXT2_INODE_SIZE(fs->super);
    697 	struct ext2_inode_large *inode;
    698 	char *start, *block_buf = NULL;
    699 	struct ext2_ext_attr_header *header;
    700 	__u32 ea_inode_magic;
    701 	blk64_t blk;
    702 	unsigned int storage_size;
    703 	unsigned int i;
    704 	errcode_t err;
    705 
    706 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
    707 	i = inode_size;
    708 	if (i < sizeof(*inode))
    709 		i = sizeof(*inode);
    710 	err = ext2fs_get_memzero(i, &inode);
    711 	if (err)
    712 		return err;
    713 
    714 	err = ext2fs_read_inode_full(fs, handle->ino, EXT2_INODE(inode),
    715 				     inode_size);
    716 	if (err)
    717 		goto out;
    718 
    719 	/* If extra_isize isn't set, we need to set it now */
    720 	if (inode->i_extra_isize == 0 &&
    721 	    inode_size > EXT2_GOOD_OLD_INODE_SIZE) {
    722 		char *p = (char *)inode;
    723 		size_t extra = fs->super->s_want_extra_isize;
    724 
    725 		if (extra == 0)
    726 			extra = sizeof(__u32);
    727 		memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra);
    728 		inode->i_extra_isize = extra;
    729 	}
    730 	if (inode->i_extra_isize & 3) {
    731 		err = EXT2_ET_INODE_CORRUPTED;
    732 		goto out;
    733 	}
    734 
    735 	/* Does the inode have space for EA? */
    736 	if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
    737 	    inode_size <= EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize +
    738 								sizeof(__u32))
    739 		goto write_ea_block;
    740 
    741 	/* Write the inode EA */
    742 	ea_inode_magic = EXT2_EXT_ATTR_MAGIC;
    743 	memcpy(((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    744 	       inode->i_extra_isize, &ea_inode_magic, sizeof(__u32));
    745 	storage_size = inode_size - EXT2_GOOD_OLD_INODE_SIZE -
    746 				inode->i_extra_isize - sizeof(__u32);
    747 	start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    748 				inode->i_extra_isize + sizeof(__u32);
    749 
    750 	err = write_xattrs_to_buffer(fs, handle->attrs, handle->ibody_count,
    751 				     start, storage_size, 0, 0);
    752 	if (err)
    753 		goto out;
    754 write_ea_block:
    755 	/* Are we done? */
    756 	if (handle->ibody_count == handle->count &&
    757 	    !ext2fs_file_acl_block(fs, EXT2_INODE(inode)))
    758 		goto skip_ea_block;
    759 
    760 	/* Write the EA block */
    761 	err = ext2fs_get_memzero(fs->blocksize, &block_buf);
    762 	if (err)
    763 		goto out;
    764 
    765 	storage_size = fs->blocksize - sizeof(struct ext2_ext_attr_header);
    766 	start = block_buf + sizeof(struct ext2_ext_attr_header);
    767 
    768 	err = write_xattrs_to_buffer(fs, handle->attrs + handle->ibody_count,
    769 				     handle->count - handle->ibody_count, start,
    770 				     storage_size, start - block_buf, 1);
    771 	if (err)
    772 		goto out2;
    773 
    774 	/* Write a header on the EA block */
    775 	header = (struct ext2_ext_attr_header *) block_buf;
    776 	header->h_magic = EXT2_EXT_ATTR_MAGIC;
    777 	header->h_refcount = 1;
    778 	header->h_blocks = 1;
    779 
    780 	/* Get a new block for writing */
    781 	err = prep_ea_block_for_write(fs, handle->ino, inode);
    782 	if (err)
    783 		goto out2;
    784 
    785 	/* Finally, write the new EA block */
    786 	blk = ext2fs_file_acl_block(fs, EXT2_INODE(inode));
    787 	err = ext2fs_write_ext_attr3(fs, blk, block_buf, handle->ino);
    788 	if (err)
    789 		goto out2;
    790 
    791 skip_ea_block:
    792 	blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
    793 	if (!block_buf && blk) {
    794 		/* xattrs shrunk, free the block */
    795 		err = ext2fs_free_ext_attr(fs, handle->ino, inode);
    796 		if (err)
    797 			goto out;
    798 	}
    799 
    800 	/* Write the inode */
    801 	err = ext2fs_write_inode_full(fs, handle->ino, EXT2_INODE(inode),
    802 				      inode_size);
    803 	if (err)
    804 		goto out2;
    805 
    806 out2:
    807 	ext2fs_free_mem(&block_buf);
    808 out:
    809 	ext2fs_free_mem(&inode);
    810 	return err;
    811 }
    812 
    813 static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
    814 					 struct ext2_inode_large *inode,
    815 					 struct ext2_ext_attr_entry *entries,
    816 					 unsigned int storage_size,
    817 					 char *value_start)
    818 {
    819 	struct ext2_xattr *x;
    820 	struct ext2_ext_attr_entry *entry, *end;
    821 	const char *prefix;
    822 	unsigned int remain, prefix_len;
    823 	errcode_t err;
    824 	unsigned int values_size = storage_size +
    825 			((char *)entries - value_start);
    826 
    827 	/* find the end */
    828 	end = entries;
    829 	remain = storage_size;
    830 	while (remain >= sizeof(struct ext2_ext_attr_entry) &&
    831 	       !EXT2_EXT_IS_LAST_ENTRY(end)) {
    832 
    833 		/* header eats this space */
    834 		remain -= sizeof(struct ext2_ext_attr_entry);
    835 
    836 		/* is attribute name valid? */
    837 		if (EXT2_EXT_ATTR_SIZE(end->e_name_len) > remain)
    838 			return EXT2_ET_EA_BAD_NAME_LEN;
    839 
    840 		/* attribute len eats this space */
    841 		remain -= EXT2_EXT_ATTR_SIZE(end->e_name_len);
    842 		end = EXT2_EXT_ATTR_NEXT(end);
    843 	}
    844 
    845 	entry = entries;
    846 	remain = storage_size;
    847 	while (remain >= sizeof(struct ext2_ext_attr_entry) &&
    848 	       !EXT2_EXT_IS_LAST_ENTRY(entry)) {
    849 
    850 		/* Allocate space for more attrs? */
    851 		if (handle->count == handle->capacity) {
    852 			err = ext2fs_xattrs_expand(handle, 4);
    853 			if (err)
    854 				return err;
    855 		}
    856 
    857 		x = handle->attrs + handle->count;
    858 
    859 		/* header eats this space */
    860 		remain -= sizeof(struct ext2_ext_attr_entry);
    861 
    862 		/* attribute len eats this space */
    863 		remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
    864 
    865 		/* Extract name */
    866 		prefix = find_ea_prefix(entry->e_name_index);
    867 		prefix_len = (prefix ? strlen(prefix) : 0);
    868 		err = ext2fs_get_memzero(entry->e_name_len + prefix_len + 1,
    869 					 &x->name);
    870 		if (err)
    871 			return err;
    872 		if (prefix)
    873 			memcpy(x->name, prefix, prefix_len);
    874 		if (entry->e_name_len)
    875 			memcpy(x->name + prefix_len,
    876 			       (char *)entry + sizeof(*entry),
    877 			       entry->e_name_len);
    878 
    879 		/* Check & copy value */
    880 		if (!ext2fs_has_feature_ea_inode(handle->fs->super) &&
    881 		    entry->e_value_inum != 0)
    882 			return EXT2_ET_BAD_EA_BLOCK_NUM;
    883 
    884 		if (entry->e_value_inum == 0) {
    885 			if (entry->e_value_size > remain)
    886 				return EXT2_ET_EA_BAD_VALUE_SIZE;
    887 
    888 			if (entry->e_value_offs + entry->e_value_size > values_size)
    889 				return EXT2_ET_EA_BAD_VALUE_OFFSET;
    890 
    891 			if (entry->e_value_size > 0 &&
    892 			    value_start + entry->e_value_offs <
    893 			    (char *)end + sizeof(__u32))
    894 				return EXT2_ET_EA_BAD_VALUE_OFFSET;
    895 
    896 			remain -= entry->e_value_size;
    897 
    898 			err = ext2fs_get_mem(entry->e_value_size, &x->value);
    899 			if (err)
    900 				return err;
    901 			memcpy(x->value, value_start + entry->e_value_offs,
    902 			       entry->e_value_size);
    903 		} else {
    904 			struct ext2_inode *ea_inode;
    905 			ext2_file_t ea_file;
    906 
    907 			if (entry->e_value_offs != 0)
    908 				return EXT2_ET_EA_BAD_VALUE_OFFSET;
    909 
    910 			if (entry->e_value_size > (64 * 1024))
    911 				return EXT2_ET_EA_BAD_VALUE_SIZE;
    912 
    913 			err = ext2fs_get_mem(entry->e_value_size, &x->value);
    914 			if (err)
    915 				return err;
    916 
    917 			err = ext2fs_file_open(handle->fs, entry->e_value_inum,
    918 					       0, &ea_file);
    919 			if (err)
    920 				return err;
    921 
    922 			ea_inode = ext2fs_file_get_inode(ea_file);
    923 			if ((ea_inode->i_flags & EXT4_INLINE_DATA_FL) ||
    924 			    !(ea_inode->i_flags & EXT4_EA_INODE_FL) ||
    925 			    ea_inode->i_links_count == 0)
    926 				err = EXT2_ET_EA_INODE_CORRUPTED;
    927 			else if (ext2fs_file_get_size(ea_file) !=
    928 			    entry->e_value_size)
    929 				err = EXT2_ET_EA_BAD_VALUE_SIZE;
    930 			else
    931 				err = ext2fs_file_read(ea_file, x->value,
    932 						       entry->e_value_size, 0);
    933 			ext2fs_file_close(ea_file);
    934 			if (err)
    935 				return err;
    936 		}
    937 
    938 		x->ea_ino = entry->e_value_inum;
    939 		x->value_len = entry->e_value_size;
    940 
    941 		/* e_hash may be 0 in older inode's ea */
    942 		if (entry->e_hash != 0) {
    943 			__u32 hash;
    944 			void *data = (entry->e_value_inum != 0) ?
    945 					0 : value_start + entry->e_value_offs;
    946 
    947 			err = ext2fs_ext_attr_hash_entry2(handle->fs, entry,
    948 							  data, &hash);
    949 			if (err)
    950 				return err;
    951 			if (entry->e_hash != hash) {
    952 				struct ext2_inode child;
    953 
    954 				/* Check whether this is an old Lustre-style
    955 				 * ea_inode reference.
    956 				 */
    957 				err = ext2fs_read_inode(handle->fs,
    958 							entry->e_value_inum,
    959 							&child);
    960 				if (err)
    961 					return err;
    962 				if (child.i_mtime != handle->ino ||
    963 				    child.i_generation != inode->i_generation)
    964 					return EXT2_ET_BAD_EA_HASH;
    965 			}
    966 		}
    967 
    968 		handle->count++;
    969 		entry = EXT2_EXT_ATTR_NEXT(entry);
    970 	}
    971 
    972 	return 0;
    973 }
    974 
    975 static void xattrs_free_keys(struct ext2_xattr_handle *h)
    976 {
    977 	struct ext2_xattr *a = h->attrs;
    978 	int i;
    979 
    980 	for (i = 0; i < h->capacity; i++) {
    981 		if (a[i].name)
    982 			ext2fs_free_mem(&a[i].name);
    983 		if (a[i].value)
    984 			ext2fs_free_mem(&a[i].value);
    985 	}
    986 	h->count = 0;
    987 	h->ibody_count = 0;
    988 }
    989 
    990 errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle)
    991 {
    992 	struct ext2_inode_large *inode;
    993 	struct ext2_ext_attr_header *header;
    994 	__u32 ea_inode_magic;
    995 	unsigned int storage_size;
    996 	char *start, *block_buf = NULL;
    997 	blk64_t blk;
    998 	size_t i;
    999 	errcode_t err;
   1000 
   1001 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
   1002 	i = EXT2_INODE_SIZE(handle->fs->super);
   1003 	if (i < sizeof(*inode))
   1004 		i = sizeof(*inode);
   1005 	err = ext2fs_get_memzero(i, &inode);
   1006 	if (err)
   1007 		return err;
   1008 
   1009 	err = ext2fs_read_inode_full(handle->fs, handle->ino,
   1010 				     (struct ext2_inode *)inode,
   1011 				     EXT2_INODE_SIZE(handle->fs->super));
   1012 	if (err)
   1013 		goto out;
   1014 
   1015 	xattrs_free_keys(handle);
   1016 
   1017 	/* Does the inode have space for EA? */
   1018 	if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
   1019 	    EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
   1020 						  inode->i_extra_isize +
   1021 						  sizeof(__u32))
   1022 		goto read_ea_block;
   1023 	if (inode->i_extra_isize & 3) {
   1024 		err = EXT2_ET_INODE_CORRUPTED;
   1025 		goto out;
   1026 	}
   1027 
   1028 	/* Look for EA in the inode */
   1029 	memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
   1030 	       inode->i_extra_isize, sizeof(__u32));
   1031 	if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) {
   1032 		storage_size = EXT2_INODE_SIZE(handle->fs->super) -
   1033 			EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize -
   1034 			sizeof(__u32);
   1035 		start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
   1036 			inode->i_extra_isize + sizeof(__u32);
   1037 
   1038 		err = read_xattrs_from_buffer(handle, inode,
   1039 					(struct ext2_ext_attr_entry *) start,
   1040 					storage_size, start);
   1041 		if (err)
   1042 			goto out;
   1043 
   1044 		handle->ibody_count = handle->count;
   1045 	}
   1046 
   1047 read_ea_block:
   1048 	/* Look for EA in a separate EA block */
   1049 	blk = ext2fs_file_acl_block(handle->fs, (struct ext2_inode *)inode);
   1050 	if (blk != 0) {
   1051 		if ((blk < handle->fs->super->s_first_data_block) ||
   1052 		    (blk >= ext2fs_blocks_count(handle->fs->super))) {
   1053 			err = EXT2_ET_BAD_EA_BLOCK_NUM;
   1054 			goto out;
   1055 		}
   1056 
   1057 		err = ext2fs_get_mem(handle->fs->blocksize, &block_buf);
   1058 		if (err)
   1059 			goto out;
   1060 
   1061 		err = ext2fs_read_ext_attr3(handle->fs, blk, block_buf,
   1062 					    handle->ino);
   1063 		if (err)
   1064 			goto out3;
   1065 
   1066 		/* We only know how to deal with v2 EA blocks */
   1067 		header = (struct ext2_ext_attr_header *) block_buf;
   1068 		if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
   1069 			err = EXT2_ET_BAD_EA_HEADER;
   1070 			goto out3;
   1071 		}
   1072 
   1073 		/* Read EAs */
   1074 		storage_size = handle->fs->blocksize -
   1075 			sizeof(struct ext2_ext_attr_header);
   1076 		start = block_buf + sizeof(struct ext2_ext_attr_header);
   1077 		err = read_xattrs_from_buffer(handle, inode,
   1078 					(struct ext2_ext_attr_entry *) start,
   1079 					storage_size, block_buf);
   1080 		if (err)
   1081 			goto out3;
   1082 
   1083 		ext2fs_free_mem(&block_buf);
   1084 	}
   1085 
   1086 	ext2fs_free_mem(&block_buf);
   1087 	ext2fs_free_mem(&inode);
   1088 	return 0;
   1089 
   1090 out3:
   1091 	ext2fs_free_mem(&block_buf);
   1092 out:
   1093 	ext2fs_free_mem(&inode);
   1094 	return err;
   1095 }
   1096 
   1097 errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h,
   1098 				int (*func)(char *name, char *value,
   1099 					    size_t value_len, void *data),
   1100 				void *data)
   1101 {
   1102 	struct ext2_xattr *x;
   1103 	int dirty = 0;
   1104 	int ret;
   1105 
   1106 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
   1107 	for (x = h->attrs; x < h->attrs + h->count; x++) {
   1108 		ret = func(x->name, x->value, x->value_len, data);
   1109 		if (ret & XATTR_CHANGED)
   1110 			dirty = 1;
   1111 		if (ret & XATTR_ABORT)
   1112 			break;
   1113 	}
   1114 
   1115 	if (dirty)
   1116 		return ext2fs_xattrs_write(h);
   1117 	return 0;
   1118 }
   1119 
   1120 errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key,
   1121 			   void **value, size_t *value_len)
   1122 {
   1123 	struct ext2_xattr *x;
   1124 	char *val;
   1125 	errcode_t err;
   1126 
   1127 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
   1128 	for (x = h->attrs; x < h->attrs + h->count; x++) {
   1129 		if (strcmp(x->name, key))
   1130 			continue;
   1131 
   1132 		if (!(h->flags & XATTR_HANDLE_FLAG_RAW) &&
   1133 		    ((strcmp(key, "system.posix_acl_default") == 0) ||
   1134 		     (strcmp(key, "system.posix_acl_access") == 0))) {
   1135 			err = convert_disk_buffer_to_posix_acl(x->value, x->value_len,
   1136 							       value, value_len);
   1137 			return err;
   1138 		} else {
   1139 			err = ext2fs_get_mem(x->value_len, &val);
   1140 			if (err)
   1141 				return err;
   1142 			memcpy(val, x->value, x->value_len);
   1143 			*value = val;
   1144 			*value_len = x->value_len;
   1145 			return 0;
   1146 		}
   1147 	}
   1148 
   1149 	return EXT2_ET_EA_KEY_NOT_FOUND;
   1150 }
   1151 
   1152 errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino,
   1153 				      size_t *size)
   1154 {
   1155 	struct ext2_ext_attr_entry *entry;
   1156 	struct ext2_inode_large *inode;
   1157 	__u32 ea_inode_magic;
   1158 	unsigned int minoff;
   1159 	char *start;
   1160 	size_t i;
   1161 	errcode_t err;
   1162 
   1163 	i = EXT2_INODE_SIZE(fs->super);
   1164 	if (i < sizeof(*inode))
   1165 		i = sizeof(*inode);
   1166 	err = ext2fs_get_memzero(i, &inode);
   1167 	if (err)
   1168 		return err;
   1169 
   1170 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)inode,
   1171 				     EXT2_INODE_SIZE(fs->super));
   1172 	if (err)
   1173 		goto out;
   1174 
   1175 	/* Does the inode have size for EA? */
   1176 	if (EXT2_INODE_SIZE(fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
   1177 						  inode->i_extra_isize +
   1178 						  sizeof(__u32)) {
   1179 		err = EXT2_ET_INLINE_DATA_NO_SPACE;
   1180 		goto out;
   1181 	}
   1182 
   1183 	minoff = EXT2_INODE_SIZE(fs->super) - sizeof(*inode) - sizeof(__u32);
   1184 	memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
   1185 	       inode->i_extra_isize, sizeof(__u32));
   1186 	if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) {
   1187 		/* has xattrs.  calculate the size */
   1188 		start= ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
   1189 			inode->i_extra_isize + sizeof(__u32);
   1190 		entry = (struct ext2_ext_attr_entry *) start;
   1191 		while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
   1192 			if (!entry->e_value_inum && entry->e_value_size) {
   1193 				unsigned int offs = entry->e_value_offs;
   1194 				if (offs < minoff)
   1195 					minoff = offs;
   1196 			}
   1197 			entry = EXT2_EXT_ATTR_NEXT(entry);
   1198 		}
   1199 		*size = minoff - ((char *)entry - (char *)start) - sizeof(__u32);
   1200 	} else {
   1201 		/* no xattr.  return a maximum size */
   1202 		*size = EXT2_EXT_ATTR_SIZE(minoff -
   1203 					   EXT2_EXT_ATTR_LEN(strlen("data")) -
   1204 					   EXT2_EXT_ATTR_ROUND - sizeof(__u32));
   1205 	}
   1206 
   1207 out:
   1208 	ext2fs_free_mem(&inode);
   1209 	return err;
   1210 }
   1211 
   1212 static errcode_t xattr_create_ea_inode(ext2_filsys fs, const void *value,
   1213 				       size_t value_len, ext2_ino_t *ea_ino)
   1214 {
   1215 	struct ext2_inode inode;
   1216 	ext2_ino_t ino;
   1217 	ext2_file_t file;
   1218 	__u32 hash;
   1219 	errcode_t ret;
   1220 
   1221 	ret = ext2fs_new_inode(fs, 0, 0, 0, &ino);
   1222 	if (ret)
   1223 		return ret;
   1224 
   1225 	memset(&inode, 0, sizeof(inode));
   1226 	inode.i_flags |= EXT4_EA_INODE_FL;
   1227 	if (ext2fs_has_feature_extents(fs->super))
   1228 		inode.i_flags |= EXT4_EXTENTS_FL;
   1229 	inode.i_size = 0;
   1230 	inode.i_mode = LINUX_S_IFREG | 0600;
   1231 	inode.i_links_count = 1;
   1232 	ret = ext2fs_write_new_inode(fs, ino, &inode);
   1233 	if (ret)
   1234 		return ret;
   1235 	/*
   1236 	 * ref_count and hash utilize inode's i_*time fields.
   1237 	 * ext2fs_write_new_inode() call above initializes these fields with
   1238 	 * current time. That's why ref count and hash updates are done
   1239 	 * separately below.
   1240 	 */
   1241 	ext2fs_set_ea_inode_ref(&inode, 1);
   1242 	hash = ext2fs_crc32c_le(fs->csum_seed, value, value_len);
   1243 	ext2fs_set_ea_inode_hash(&inode, hash);
   1244 
   1245 	ret = ext2fs_write_inode(fs, ino, &inode);
   1246 	if (ret)
   1247 		return ret;
   1248 
   1249 	ret = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file);
   1250 	if (ret)
   1251 		return ret;
   1252 	ret = ext2fs_file_write(file, value, value_len, NULL);
   1253 	ext2fs_file_close(file);
   1254 	if (ret)
   1255 		return ret;
   1256 
   1257 	ext2fs_inode_alloc_stats2(fs, ino, 1 /* inuse */, 0 /* isdir */);
   1258 
   1259 	*ea_ino = ino;
   1260 	return 0;
   1261 }
   1262 
   1263 static errcode_t xattr_inode_dec_ref(ext2_filsys fs, ext2_ino_t ino)
   1264 {
   1265 	struct ext2_inode_large inode;
   1266 	__u64 ref_count;
   1267 	errcode_t ret;
   1268 
   1269 	ret = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1270 				     sizeof(inode));
   1271 	if (ret)
   1272 		goto out;
   1273 
   1274 	ref_count = ext2fs_get_ea_inode_ref(EXT2_INODE(&inode));
   1275 	ref_count--;
   1276 	ext2fs_set_ea_inode_ref(EXT2_INODE(&inode), ref_count);
   1277 
   1278 	if (ref_count)
   1279 		goto write_out;
   1280 
   1281 	inode.i_links_count = 0;
   1282 	inode.i_dtime = fs->now ? fs->now : time(0);
   1283 
   1284 	ret = ext2fs_free_ext_attr(fs, ino, &inode);
   1285 	if (ret)
   1286 		goto write_out;
   1287 
   1288 	if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) {
   1289 		ret = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL,
   1290 				   0, ~0ULL);
   1291 		if (ret)
   1292 			goto out;
   1293 	}
   1294 
   1295 	ext2fs_inode_alloc_stats2(fs, ino, -1 /* inuse */, 0 /* is_dir */);
   1296 
   1297 write_out:
   1298 	ret = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode,
   1299 				      sizeof(inode));
   1300 out:
   1301 	return ret;
   1302 }
   1303 
   1304 static errcode_t xattr_update_entry(ext2_filsys fs, struct ext2_xattr *x,
   1305 				    const char *name, const void *value,
   1306 				    size_t value_len, int in_inode)
   1307 {
   1308 	ext2_ino_t ea_ino = 0;
   1309 	void *new_value = NULL;
   1310 	char *new_name = NULL;
   1311 	int name_len;
   1312 	errcode_t ret;
   1313 
   1314 	if (!x->name) {
   1315 		name_len = strlen(name);
   1316 		ret = ext2fs_get_mem(name_len + 1, &new_name);
   1317 		if (ret)
   1318 			goto fail;
   1319 		memcpy(new_name, name, name_len + 1);
   1320 	}
   1321 
   1322 	ret = ext2fs_get_mem(value_len, &new_value);
   1323 	if (ret)
   1324 		goto fail;
   1325 	memcpy(new_value, value, value_len);
   1326 
   1327 	if (in_inode) {
   1328 		ret = xattr_create_ea_inode(fs, value, value_len, &ea_ino);
   1329 		if (ret)
   1330 			goto fail;
   1331 	}
   1332 
   1333 	if (x->ea_ino) {
   1334 		ret = xattr_inode_dec_ref(fs, x->ea_ino);
   1335 		if (ret)
   1336 			goto fail;
   1337 	}
   1338 
   1339 	if (!x->name)
   1340 		x->name = new_name;
   1341 
   1342 	if (x->value)
   1343 		ext2fs_free_mem(&x->value);
   1344 	x->value = new_value;
   1345 	x->value_len = value_len;
   1346 	x->ea_ino = ea_ino;
   1347 	return 0;
   1348 fail:
   1349 	if (new_name)
   1350 		ext2fs_free_mem(&new_name);
   1351 	if (new_value)
   1352 		ext2fs_free_mem(&new_value);
   1353 	if (ea_ino)
   1354 		xattr_inode_dec_ref(fs, ea_ino);
   1355 	return ret;
   1356 }
   1357 
   1358 static int xattr_find_position(struct ext2_xattr *attrs, int count,
   1359 			       const char *name)
   1360 {
   1361 	struct ext2_xattr *x;
   1362 	int i;
   1363 	const char *shortname, *x_shortname;
   1364 	int name_idx, x_name_idx;
   1365 	int shortname_len, x_shortname_len;
   1366 
   1367 	find_ea_index(name, &shortname, &name_idx);
   1368 	shortname_len = strlen(shortname);
   1369 
   1370 	for (i = 0, x = attrs; i < count; i++, x++) {
   1371 		find_ea_index(x->name, &x_shortname, &x_name_idx);
   1372 		if (name_idx < x_name_idx)
   1373 			break;
   1374 		if (name_idx > x_name_idx)
   1375 			continue;
   1376 
   1377 		x_shortname_len = strlen(x_shortname);
   1378 		if (shortname_len < x_shortname_len)
   1379 			break;
   1380 		if (shortname_len > x_shortname_len)
   1381 			continue;
   1382 
   1383 		if (memcmp(shortname, x_shortname, shortname_len) <= 0)
   1384 			break;
   1385 	}
   1386 	return i;
   1387 }
   1388 
   1389 static errcode_t xattr_array_update(struct ext2_xattr_handle *h,
   1390 				    const char *name,
   1391 				    const void *value, size_t value_len,
   1392 				    int ibody_free, int block_free,
   1393 				    int old_idx, int in_inode)
   1394 {
   1395 	struct ext2_xattr tmp;
   1396 	int add_to_ibody;
   1397 	int needed;
   1398 	int name_len, name_idx;
   1399 	const char *shortname;
   1400 	int new_idx;
   1401 	int ret;
   1402 
   1403 	find_ea_index(name, &shortname, &name_idx);
   1404 	name_len = strlen(shortname);
   1405 
   1406 	needed = EXT2_EXT_ATTR_LEN(name_len);
   1407 	if (!in_inode)
   1408 		needed += EXT2_EXT_ATTR_SIZE(value_len);
   1409 
   1410 	if (old_idx >= 0 && old_idx < h->ibody_count) {
   1411 		ibody_free += EXT2_EXT_ATTR_LEN(name_len);
   1412 		if (!h->attrs[old_idx].ea_ino)
   1413 			ibody_free += EXT2_EXT_ATTR_SIZE(
   1414 						h->attrs[old_idx].value_len);
   1415 	}
   1416 
   1417 	if (needed <= ibody_free) {
   1418 		if (old_idx < 0) {
   1419 			new_idx = h->ibody_count;
   1420 			add_to_ibody = 1;
   1421 			goto add_new;
   1422 		}
   1423 
   1424 		/* Update the existing entry. */
   1425 		ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name,
   1426 					 value, value_len, in_inode);
   1427 		if (ret)
   1428 			return ret;
   1429 		if (h->ibody_count <= old_idx) {
   1430 			/* Move entry from block to the end of ibody. */
   1431 			tmp = h->attrs[old_idx];
   1432 			memmove(h->attrs + h->ibody_count + 1,
   1433 				h->attrs + h->ibody_count,
   1434 				(old_idx - h->ibody_count) * sizeof(*h->attrs));
   1435 			h->attrs[h->ibody_count] = tmp;
   1436 			h->ibody_count++;
   1437 		}
   1438 		return 0;
   1439 	}
   1440 
   1441 	if (h->ibody_count <= old_idx) {
   1442 		block_free += EXT2_EXT_ATTR_LEN(name_len);
   1443 		if (!h->attrs[old_idx].ea_ino)
   1444 			block_free +=
   1445 				EXT2_EXT_ATTR_SIZE(h->attrs[old_idx].value_len);
   1446 	}
   1447 
   1448 	if (needed > block_free)
   1449 		return EXT2_ET_EA_NO_SPACE;
   1450 
   1451 	if (old_idx >= 0) {
   1452 		/* Update the existing entry. */
   1453 		ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name,
   1454 					 value, value_len, in_inode);
   1455 		if (ret)
   1456 			return ret;
   1457 		if (old_idx < h->ibody_count) {
   1458 			/*
   1459 			 * Move entry from ibody to the block. Note that
   1460 			 * entries in the block are sorted.
   1461 			 */
   1462 			new_idx = xattr_find_position(h->attrs + h->ibody_count,
   1463 				h->count - h->ibody_count, name);
   1464 			new_idx += h->ibody_count - 1;
   1465 			tmp = h->attrs[old_idx];
   1466 			memmove(h->attrs + old_idx, h->attrs + old_idx + 1,
   1467 				(new_idx - old_idx) * sizeof(*h->attrs));
   1468 			h->attrs[new_idx] = tmp;
   1469 			h->ibody_count--;
   1470 		}
   1471 		return 0;
   1472 	}
   1473 
   1474 	new_idx = xattr_find_position(h->attrs + h->ibody_count,
   1475 				      h->count - h->ibody_count, name);
   1476 	new_idx += h->ibody_count;
   1477 	add_to_ibody = 0;
   1478 
   1479 add_new:
   1480 	if (h->count == h->capacity) {
   1481 		ret = ext2fs_xattrs_expand(h, 4);
   1482 		if (ret)
   1483 			return ret;
   1484 	}
   1485 
   1486 	ret = xattr_update_entry(h->fs, &h->attrs[h->count], name, value,
   1487 				 value_len, in_inode);
   1488 	if (ret)
   1489 		return ret;
   1490 
   1491 	tmp = h->attrs[h->count];
   1492 	memmove(h->attrs + new_idx + 1, h->attrs + new_idx,
   1493 		(h->count - new_idx)*sizeof(*h->attrs));
   1494 	h->attrs[new_idx] = tmp;
   1495 	if (add_to_ibody)
   1496 		h->ibody_count++;
   1497 	h->count++;
   1498 	return 0;
   1499 }
   1500 
   1501 static int space_used(struct ext2_xattr *attrs, int count)
   1502 {
   1503 	int total = 0;
   1504 	struct ext2_xattr *x;
   1505 	const char *shortname;
   1506 	int i, len, name_idx;
   1507 
   1508 	for (i = 0, x = attrs; i < count; i++, x++) {
   1509 		find_ea_index(x->name, &shortname, &name_idx);
   1510 		len = strlen(shortname);
   1511 		total += EXT2_EXT_ATTR_LEN(len);
   1512 		if (!x->ea_ino)
   1513 			total += EXT2_EXT_ATTR_SIZE(x->value_len);
   1514 	}
   1515 	return total;
   1516 }
   1517 
   1518 /*
   1519  * The minimum size of EA value when you start storing it in an external inode
   1520  * size of block - size of header - size of 1 entry - 4 null bytes
   1521  */
   1522 #define EXT4_XATTR_MIN_LARGE_EA_SIZE(b)	\
   1523 	((b) - EXT2_EXT_ATTR_LEN(3) - sizeof(struct ext2_ext_attr_header) - 4)
   1524 
   1525 errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *h,
   1526 			   const char *name,
   1527 			   const void *value,
   1528 			   size_t value_len)
   1529 {
   1530 	ext2_filsys fs = h->fs;
   1531 	const int inode_size = EXT2_INODE_SIZE(fs->super);
   1532 	struct ext2_inode_large *inode = NULL;
   1533 	struct ext2_xattr *x;
   1534 	char *new_value;
   1535 	int ibody_free, block_free;
   1536 	int in_inode = 0;
   1537 	int old_idx = -1;
   1538 	int extra_isize;
   1539 	errcode_t ret;
   1540 
   1541 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
   1542 
   1543 	ret = ext2fs_get_mem(value_len, &new_value);
   1544 	if (ret)
   1545 		return ret;
   1546 	if (!(h->flags & XATTR_HANDLE_FLAG_RAW) &&
   1547 	    ((strcmp(name, "system.posix_acl_default") == 0) ||
   1548 	     (strcmp(name, "system.posix_acl_access") == 0))) {
   1549 		ret = convert_posix_acl_to_disk_buffer(value, value_len,
   1550 						       new_value, &value_len);
   1551 		if (ret)
   1552 			goto out;
   1553 	} else
   1554 		memcpy(new_value, value, value_len);
   1555 
   1556 	/* Imitate kernel behavior by skipping update if value is the same. */
   1557 	for (x = h->attrs; x < h->attrs + h->count; x++) {
   1558 		if (!strcmp(x->name, name)) {
   1559 			if (!x->ea_ino && x->value_len == value_len &&
   1560 			    !memcmp(x->value, new_value, value_len)) {
   1561 				ret = 0;
   1562 				goto out;
   1563 			}
   1564 			old_idx = x - h->attrs;
   1565 			break;
   1566 		}
   1567 	}
   1568 
   1569 	ret = ext2fs_get_memzero(inode_size, &inode);
   1570 	if (ret)
   1571 		goto out;
   1572 	ret = ext2fs_read_inode_full(fs, h->ino,
   1573 				     (struct ext2_inode *)inode,
   1574 				     inode_size);
   1575 	if (ret)
   1576 		goto out;
   1577 	if (inode_size > EXT2_GOOD_OLD_INODE_SIZE) {
   1578 		extra_isize = inode->i_extra_isize;
   1579 		if (extra_isize == 0) {
   1580 			extra_isize = fs->super->s_want_extra_isize;
   1581 			if (extra_isize == 0)
   1582 				extra_isize = sizeof(__u32);
   1583 		}
   1584 		ibody_free = inode_size - EXT2_GOOD_OLD_INODE_SIZE;
   1585 		ibody_free -= extra_isize;
   1586 		/* Extended attribute magic and final null entry. */
   1587 		ibody_free -= sizeof(__u32) * 2;
   1588 		ibody_free -= space_used(h->attrs, h->ibody_count);
   1589 	} else
   1590 		ibody_free = 0;
   1591 
   1592 	/* Inline data can only go to ibody. */
   1593 	if (strcmp(name, "system.data") == 0) {
   1594 		if (h->ibody_count <= old_idx) {
   1595 			ret = EXT2_ET_FILESYSTEM_CORRUPTED;
   1596 			goto out;
   1597 		}
   1598 		ret = xattr_array_update(h, name, value, value_len, ibody_free,
   1599 					 0 /* block_free */, old_idx,
   1600 					 0 /* in_inode */);
   1601 		if (ret)
   1602 			goto out;
   1603 		goto write_out;
   1604 	}
   1605 
   1606 	block_free = fs->blocksize;
   1607 	block_free -= sizeof(struct ext2_ext_attr_header);
   1608 	/* Final null entry. */
   1609 	block_free -= sizeof(__u32);
   1610 	block_free -= space_used(h->attrs + h->ibody_count,
   1611 				 h->count - h->ibody_count);
   1612 
   1613 	if (ext2fs_has_feature_ea_inode(fs->super) &&
   1614 	    value_len > EXT4_XATTR_MIN_LARGE_EA_SIZE(fs->blocksize))
   1615 		in_inode = 1;
   1616 
   1617 	ret = xattr_array_update(h, name, value, value_len, ibody_free,
   1618 				 block_free, old_idx, in_inode);
   1619 	if (ret == EXT2_ET_EA_NO_SPACE && !in_inode &&
   1620 	    ext2fs_has_feature_ea_inode(fs->super))
   1621 		ret = xattr_array_update(h, name, value, value_len, ibody_free,
   1622 				 block_free, old_idx, 1 /* in_inode */);
   1623 	if (ret)
   1624 		goto out;
   1625 
   1626 write_out:
   1627 	ret = ext2fs_xattrs_write(h);
   1628 out:
   1629 	if (inode)
   1630 		ext2fs_free_mem(&inode);
   1631 	ext2fs_free_mem(&new_value);
   1632 	return ret;
   1633 }
   1634 
   1635 errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle,
   1636 			      const char *key)
   1637 {
   1638 	struct ext2_xattr *x;
   1639 	struct ext2_xattr *end = handle->attrs + handle->count;
   1640 
   1641 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
   1642 	for (x = handle->attrs; x < end; x++) {
   1643 		if (strcmp(x->name, key) == 0) {
   1644 			ext2fs_free_mem(&x->name);
   1645 			ext2fs_free_mem(&x->value);
   1646 			if (x->ea_ino)
   1647 				xattr_inode_dec_ref(handle->fs, x->ea_ino);
   1648 			memmove(x, x + 1, (end - x - 1)*sizeof(*x));
   1649 			memset(end - 1, 0, sizeof(*end));
   1650 			if (x < handle->attrs + handle->ibody_count)
   1651 				handle->ibody_count--;
   1652 			handle->count--;
   1653 			return ext2fs_xattrs_write(handle);
   1654 		}
   1655 	}
   1656 
   1657 	/* no key found, success! */
   1658 	return 0;
   1659 }
   1660 
   1661 errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino,
   1662 			     struct ext2_xattr_handle **handle)
   1663 {
   1664 	struct ext2_xattr_handle *h;
   1665 	errcode_t err;
   1666 
   1667 	if (!ext2fs_has_feature_xattr(fs->super) &&
   1668 	    !ext2fs_has_feature_inline_data(fs->super))
   1669 		return EXT2_ET_MISSING_EA_FEATURE;
   1670 
   1671 	err = ext2fs_get_memzero(sizeof(*h), &h);
   1672 	if (err)
   1673 		return err;
   1674 
   1675 	h->magic = EXT2_ET_MAGIC_EA_HANDLE;
   1676 	h->capacity = 4;
   1677 	err = ext2fs_get_arrayzero(h->capacity, sizeof(struct ext2_xattr),
   1678 				   &h->attrs);
   1679 	if (err) {
   1680 		ext2fs_free_mem(&h);
   1681 		return err;
   1682 	}
   1683 	h->count = 0;
   1684 	h->ino = ino;
   1685 	h->fs = fs;
   1686 	*handle = h;
   1687 	return 0;
   1688 }
   1689 
   1690 errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle)
   1691 {
   1692 	struct ext2_xattr_handle *h = *handle;
   1693 
   1694 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
   1695 	xattrs_free_keys(h);
   1696 	ext2fs_free_mem(&h->attrs);
   1697 	ext2fs_free_mem(handle);
   1698 	return 0;
   1699 }
   1700 
   1701 errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count)
   1702 {
   1703 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
   1704 	*count = handle->count;
   1705 	return 0;
   1706 }
   1707 
   1708 errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle,
   1709 			      unsigned int *new_flags, unsigned int *old_flags)
   1710 {
   1711 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
   1712 	if (old_flags)
   1713 		*old_flags = handle->flags;
   1714 	if (new_flags)
   1715 		handle->flags = *new_flags;
   1716 	return 0;
   1717 }
   1718