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 
     25 #include "ext2fs.h"
     26 
     27 #define NAME_HASH_SHIFT 5
     28 #define VALUE_HASH_SHIFT 16
     29 
     30 /*
     31  * ext2_xattr_hash_entry()
     32  *
     33  * Compute the hash of an extended attribute.
     34  */
     35 __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data)
     36 {
     37 	__u32 hash = 0;
     38 	char *name = ((char *) entry) + sizeof(struct ext2_ext_attr_entry);
     39 	int n;
     40 
     41 	for (n = 0; n < entry->e_name_len; n++) {
     42 		hash = (hash << NAME_HASH_SHIFT) ^
     43 		       (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^
     44 		       *name++;
     45 	}
     46 
     47 	/* The hash needs to be calculated on the data in little-endian. */
     48 	if (entry->e_value_block == 0 && entry->e_value_size != 0) {
     49 		__u32 *value = (__u32 *)data;
     50 		for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >>
     51 			 EXT2_EXT_ATTR_PAD_BITS; n; n--) {
     52 			hash = (hash << VALUE_HASH_SHIFT) ^
     53 			       (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^
     54 			       ext2fs_le32_to_cpu(*value++);
     55 		}
     56 	}
     57 
     58 	return hash;
     59 }
     60 
     61 static errcode_t check_ext_attr_header(struct ext2_ext_attr_header *header)
     62 {
     63 	if ((header->h_magic != EXT2_EXT_ATTR_MAGIC_v1 &&
     64 	     header->h_magic != EXT2_EXT_ATTR_MAGIC) ||
     65 	    header->h_blocks != 1)
     66 		return EXT2_ET_BAD_EA_HEADER;
     67 
     68 	return 0;
     69 }
     70 
     71 #undef NAME_HASH_SHIFT
     72 #undef VALUE_HASH_SHIFT
     73 
     74 errcode_t ext2fs_read_ext_attr3(ext2_filsys fs, blk64_t block, void *buf,
     75 				ext2_ino_t inum)
     76 {
     77 	int		csum_failed = 0;
     78 	errcode_t	retval;
     79 
     80 	retval = io_channel_read_blk64(fs->io, block, 1, buf);
     81 	if (retval)
     82 		return retval;
     83 
     84 	if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) &&
     85 	    !ext2fs_ext_attr_block_csum_verify(fs, inum, block, buf))
     86 		csum_failed = 1;
     87 
     88 #ifdef WORDS_BIGENDIAN
     89 	ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1);
     90 #endif
     91 
     92 	retval = check_ext_attr_header(buf);
     93 	if (retval == 0 && csum_failed)
     94 		retval = EXT2_ET_EXT_ATTR_CSUM_INVALID;
     95 
     96 	return retval;
     97 }
     98 
     99 errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf)
    100 {
    101 	return ext2fs_read_ext_attr3(fs, block, buf, 0);
    102 }
    103 
    104 errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf)
    105 {
    106 	return ext2fs_read_ext_attr2(fs, block, buf);
    107 }
    108 
    109 errcode_t ext2fs_write_ext_attr3(ext2_filsys fs, blk64_t block, void *inbuf,
    110 				 ext2_ino_t inum)
    111 {
    112 	errcode_t	retval;
    113 	char		*write_buf;
    114 
    115 #ifdef WORDS_BIGENDIAN
    116 	retval = ext2fs_get_mem(fs->blocksize, &write_buf);
    117 	if (retval)
    118 		return retval;
    119 	ext2fs_swap_ext_attr(write_buf, inbuf, fs->blocksize, 1);
    120 #else
    121 	write_buf = (char *) inbuf;
    122 #endif
    123 
    124 	retval = ext2fs_ext_attr_block_csum_set(fs, inum, block,
    125 			(struct ext2_ext_attr_header *)write_buf);
    126 	if (retval)
    127 		return retval;
    128 
    129 	retval = io_channel_write_blk64(fs->io, block, 1, write_buf);
    130 #ifdef WORDS_BIGENDIAN
    131 	ext2fs_free_mem(&write_buf);
    132 #endif
    133 	if (!retval)
    134 		ext2fs_mark_changed(fs);
    135 	return retval;
    136 }
    137 
    138 errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, void *inbuf)
    139 {
    140 	return ext2fs_write_ext_attr3(fs, block, inbuf, 0);
    141 }
    142 
    143 errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf)
    144 {
    145 	return ext2fs_write_ext_attr2(fs, block, inbuf);
    146 }
    147 
    148 /*
    149  * This function adjusts the reference count of the EA block.
    150  */
    151 errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk,
    152 				    char *block_buf, int adjust,
    153 				    __u32 *newcount, ext2_ino_t inum)
    154 {
    155 	errcode_t	retval;
    156 	struct ext2_ext_attr_header *header;
    157 	char	*buf = 0;
    158 
    159 	if ((blk >= ext2fs_blocks_count(fs->super)) ||
    160 	    (blk < fs->super->s_first_data_block))
    161 		return EXT2_ET_BAD_EA_BLOCK_NUM;
    162 
    163 	if (!block_buf) {
    164 		retval = ext2fs_get_mem(fs->blocksize, &buf);
    165 		if (retval)
    166 			return retval;
    167 		block_buf = buf;
    168 	}
    169 
    170 	retval = ext2fs_read_ext_attr3(fs, blk, block_buf, inum);
    171 	if (retval)
    172 		goto errout;
    173 
    174 	header = (struct ext2_ext_attr_header *) block_buf;
    175 	header->h_refcount += adjust;
    176 	if (newcount)
    177 		*newcount = header->h_refcount;
    178 
    179 	retval = ext2fs_write_ext_attr3(fs, blk, block_buf, inum);
    180 	if (retval)
    181 		goto errout;
    182 
    183 errout:
    184 	if (buf)
    185 		ext2fs_free_mem(&buf);
    186 	return retval;
    187 }
    188 
    189 errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk,
    190 				    char *block_buf, int adjust,
    191 				    __u32 *newcount)
    192 {
    193 	return ext2fs_adjust_ea_refcount3(fs, blk, block_buf, adjust,
    194 					  newcount, 0);
    195 }
    196 
    197 errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk,
    198 					char *block_buf, int adjust,
    199 					__u32 *newcount)
    200 {
    201 	return ext2fs_adjust_ea_refcount2(fs, blk, block_buf, adjust,
    202 					  newcount);
    203 }
    204 
    205 /* Manipulate the contents of extended attribute regions */
    206 struct ext2_xattr {
    207 	char *name;
    208 	void *value;
    209 	size_t value_len;
    210 };
    211 
    212 struct ext2_xattr_handle {
    213 	errcode_t magic;
    214 	ext2_filsys fs;
    215 	struct ext2_xattr *attrs;
    216 	size_t length, count;
    217 	ext2_ino_t ino;
    218 	int dirty;
    219 };
    220 
    221 static errcode_t ext2fs_xattrs_expand(struct ext2_xattr_handle *h,
    222 				      unsigned int expandby)
    223 {
    224 	struct ext2_xattr *new_attrs;
    225 	errcode_t err;
    226 
    227 	err = ext2fs_get_arrayzero(h->length + expandby,
    228 				   sizeof(struct ext2_xattr), &new_attrs);
    229 	if (err)
    230 		return err;
    231 
    232 	memcpy(new_attrs, h->attrs, h->length * sizeof(struct ext2_xattr));
    233 	ext2fs_free_mem(&h->attrs);
    234 	h->length += expandby;
    235 	h->attrs = new_attrs;
    236 
    237 	return 0;
    238 }
    239 
    240 struct ea_name_index {
    241 	int index;
    242 	const char *name;
    243 };
    244 
    245 /* Keep these names sorted in order of decreasing specificity. */
    246 static struct ea_name_index ea_names[] = {
    247 	{3, "system.posix_acl_default"},
    248 	{2, "system.posix_acl_access"},
    249 	{8, "system.richacl"},
    250 	{6, "security."},
    251 	{4, "trusted."},
    252 	{7, "system."},
    253 	{1, "user."},
    254 	{0, NULL},
    255 };
    256 
    257 static int find_ea_index(char *fullname, char **name, int *index);
    258 
    259 /* Push empty attributes to the end and inlinedata to the front. */
    260 static int attr_compare(const void *a, const void *b)
    261 {
    262 	const struct ext2_xattr *xa = a, *xb = b;
    263 	char *xa_suffix, *xb_suffix;
    264 	int xa_idx, xb_idx;
    265 	int cmp;
    266 
    267 	if (xa->name == NULL)
    268 		return +1;
    269 	else if (xb->name == NULL)
    270 		return -1;
    271 	else if (!strcmp(xa->name, "system.data"))
    272 		return -1;
    273 	else if (!strcmp(xb->name, "system.data"))
    274 		return +1;
    275 
    276 	/*
    277 	 * Duplicate the kernel's sorting algorithm because xattr blocks
    278 	 * require sorted keys.
    279 	 */
    280 	xa_suffix = xa->name;
    281 	xb_suffix = xb->name;
    282 	xa_idx = xb_idx = 0;
    283 	find_ea_index(xa->name, &xa_suffix, &xa_idx);
    284 	find_ea_index(xb->name, &xb_suffix, &xb_idx);
    285 	cmp = xa_idx - xb_idx;
    286 	if (cmp)
    287 		return cmp;
    288 	cmp = strlen(xa_suffix) - strlen(xb_suffix);
    289 	if (cmp)
    290 		return cmp;
    291 	cmp = strcmp(xa_suffix, xb_suffix);
    292 	return cmp;
    293 }
    294 
    295 static const char *find_ea_prefix(int index)
    296 {
    297 	struct ea_name_index *e;
    298 
    299 	for (e = ea_names; e->name; e++)
    300 		if (e->index == index)
    301 			return e->name;
    302 
    303 	return NULL;
    304 }
    305 
    306 static int find_ea_index(char *fullname, char **name, int *index)
    307 {
    308 	struct ea_name_index *e;
    309 
    310 	for (e = ea_names; e->name; e++) {
    311 		if (memcmp(fullname, e->name, strlen(e->name)) == 0) {
    312 			*name = (char *)fullname + strlen(e->name);
    313 			*index = e->index;
    314 			return 1;
    315 		}
    316 	}
    317 	return 0;
    318 }
    319 
    320 errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino,
    321 			       struct ext2_inode_large *inode)
    322 {
    323 	struct ext2_ext_attr_header *header;
    324 	void *block_buf = NULL;
    325 	blk64_t blk;
    326 	errcode_t err;
    327 	struct ext2_inode_large i;
    328 
    329 	/* Read inode? */
    330 	if (inode == NULL) {
    331 		err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&i,
    332 					     sizeof(struct ext2_inode_large));
    333 		if (err)
    334 			return err;
    335 		inode = &i;
    336 	}
    337 
    338 	/* Do we already have an EA block? */
    339 	blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
    340 	if (blk == 0)
    341 		return 0;
    342 
    343 	/* Find block, zero it, write back */
    344 	if ((blk < fs->super->s_first_data_block) ||
    345 	    (blk >= ext2fs_blocks_count(fs->super))) {
    346 		err = EXT2_ET_BAD_EA_BLOCK_NUM;
    347 		goto out;
    348 	}
    349 
    350 	err = ext2fs_get_mem(fs->blocksize, &block_buf);
    351 	if (err)
    352 		goto out;
    353 
    354 	err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino);
    355 	if (err)
    356 		goto out2;
    357 
    358 	/* We only know how to deal with v2 EA blocks */
    359 	header = (struct ext2_ext_attr_header *) block_buf;
    360 	if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
    361 		err = EXT2_ET_BAD_EA_HEADER;
    362 		goto out2;
    363 	}
    364 
    365 	header->h_refcount--;
    366 	err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino);
    367 	if (err)
    368 		goto out2;
    369 
    370 	/* Erase link to block */
    371 	ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, 0);
    372 	if (header->h_refcount == 0)
    373 		ext2fs_block_alloc_stats2(fs, blk, -1);
    374 	err = ext2fs_iblk_sub_blocks(fs, (struct ext2_inode *)inode, 1);
    375 	if (err)
    376 		goto out2;
    377 
    378 	/* Write inode? */
    379 	if (inode == &i) {
    380 		err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&i,
    381 					      sizeof(struct ext2_inode_large));
    382 		if (err)
    383 			goto out2;
    384 	}
    385 
    386 out2:
    387 	ext2fs_free_mem(&block_buf);
    388 out:
    389 	return err;
    390 }
    391 
    392 static errcode_t prep_ea_block_for_write(ext2_filsys fs, ext2_ino_t ino,
    393 					 struct ext2_inode_large *inode)
    394 {
    395 	struct ext2_ext_attr_header *header;
    396 	void *block_buf = NULL;
    397 	blk64_t blk, goal;
    398 	errcode_t err;
    399 
    400 	/* Do we already have an EA block? */
    401 	blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode);
    402 	if (blk != 0) {
    403 		if ((blk < fs->super->s_first_data_block) ||
    404 		    (blk >= ext2fs_blocks_count(fs->super))) {
    405 			err = EXT2_ET_BAD_EA_BLOCK_NUM;
    406 			goto out;
    407 		}
    408 
    409 		err = ext2fs_get_mem(fs->blocksize, &block_buf);
    410 		if (err)
    411 			goto out;
    412 
    413 		err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino);
    414 		if (err)
    415 			goto out2;
    416 
    417 		/* We only know how to deal with v2 EA blocks */
    418 		header = (struct ext2_ext_attr_header *) block_buf;
    419 		if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
    420 			err = EXT2_ET_BAD_EA_HEADER;
    421 			goto out2;
    422 		}
    423 
    424 		/* Single-user block.  We're done here. */
    425 		if (header->h_refcount == 1)
    426 			goto out2;
    427 
    428 		/* We need to CoW the block. */
    429 		header->h_refcount--;
    430 		err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino);
    431 		if (err)
    432 			goto out2;
    433 	} else {
    434 		/* No block, we must increment i_blocks */
    435 		err = ext2fs_iblk_add_blocks(fs, (struct ext2_inode *)inode,
    436 					     1);
    437 		if (err)
    438 			goto out;
    439 	}
    440 
    441 	/* Allocate a block */
    442 	goal = ext2fs_find_inode_goal(fs, ino, (struct ext2_inode *)inode, 0);
    443 	err = ext2fs_alloc_block2(fs, goal, NULL, &blk);
    444 	if (err)
    445 		goto out2;
    446 	ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, blk);
    447 out2:
    448 	if (block_buf)
    449 		ext2fs_free_mem(&block_buf);
    450 out:
    451 	return err;
    452 }
    453 
    454 
    455 static errcode_t write_xattrs_to_buffer(struct ext2_xattr_handle *handle,
    456 					struct ext2_xattr **pos,
    457 					void *entries_start,
    458 					unsigned int storage_size,
    459 					unsigned int value_offset_correction,
    460 					int write_hash)
    461 {
    462 	struct ext2_xattr *x = *pos;
    463 	struct ext2_ext_attr_entry *e = entries_start;
    464 	char *end = (char *) entries_start + storage_size;
    465 	char *shortname;
    466 	unsigned int entry_size, value_size;
    467 	int idx, ret;
    468 
    469 	memset(entries_start, 0, storage_size);
    470 	/* For all remaining x...  */
    471 	for (; x < handle->attrs + handle->length; x++) {
    472 		if (!x->name)
    473 			continue;
    474 
    475 		/* Calculate index and shortname position */
    476 		shortname = x->name;
    477 		ret = find_ea_index(x->name, &shortname, &idx);
    478 
    479 		/* Calculate entry and value size */
    480 		entry_size = (sizeof(*e) + strlen(shortname) +
    481 			      EXT2_EXT_ATTR_PAD - 1) &
    482 			     ~(EXT2_EXT_ATTR_PAD - 1);
    483 		value_size = ((x->value_len + EXT2_EXT_ATTR_PAD - 1) /
    484 			      EXT2_EXT_ATTR_PAD) * EXT2_EXT_ATTR_PAD;
    485 
    486 		/*
    487 		 * Would entry collide with value?
    488 		 * Note that we must leave sufficient room for a (u32)0 to
    489 		 * mark the end of the entries.
    490 		 */
    491 		if ((char *)e + entry_size + sizeof(__u32) > end - value_size)
    492 			break;
    493 
    494 		/* Fill out e appropriately */
    495 		e->e_name_len = strlen(shortname);
    496 		e->e_name_index = (ret ? idx : 0);
    497 		e->e_value_offs = end - value_size - (char *)entries_start +
    498 				value_offset_correction;
    499 		e->e_value_block = 0;
    500 		e->e_value_size = x->value_len;
    501 
    502 		/* Store name and value */
    503 		end -= value_size;
    504 		memcpy((char *)e + sizeof(*e), shortname, e->e_name_len);
    505 		memcpy(end, x->value, e->e_value_size);
    506 
    507 		if (write_hash)
    508 			e->e_hash = ext2fs_ext_attr_hash_entry(e, end);
    509 		else
    510 			e->e_hash = 0;
    511 
    512 		e = EXT2_EXT_ATTR_NEXT(e);
    513 		*(__u32 *)e = 0;
    514 	}
    515 	*pos = x;
    516 
    517 	return 0;
    518 }
    519 
    520 errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle)
    521 {
    522 	struct ext2_xattr *x;
    523 	struct ext2_inode_large *inode;
    524 	char *start, *block_buf = NULL;
    525 	struct ext2_ext_attr_header *header;
    526 	__u32 ea_inode_magic;
    527 	blk64_t blk;
    528 	unsigned int storage_size;
    529 	unsigned int i;
    530 	errcode_t err;
    531 
    532 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
    533 	i = EXT2_INODE_SIZE(handle->fs->super);
    534 	if (i < sizeof(*inode))
    535 		i = sizeof(*inode);
    536 	err = ext2fs_get_memzero(i, &inode);
    537 	if (err)
    538 		return err;
    539 
    540 	err = ext2fs_read_inode_full(handle->fs, handle->ino,
    541 				     (struct ext2_inode *)inode,
    542 				     EXT2_INODE_SIZE(handle->fs->super));
    543 	if (err)
    544 		goto out;
    545 
    546 	/* If extra_isize isn't set, we need to set it now */
    547 	if (inode->i_extra_isize == 0 &&
    548 	    EXT2_INODE_SIZE(handle->fs->super) > EXT2_GOOD_OLD_INODE_SIZE) {
    549 		char *p = (char *)inode;
    550 		size_t extra = handle->fs->super->s_want_extra_isize;
    551 
    552 		if (extra == 0)
    553 			extra = sizeof(__u32);
    554 		memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra);
    555 		inode->i_extra_isize = extra;
    556 	}
    557 	if (inode->i_extra_isize & 3) {
    558 		err = EXT2_ET_INODE_CORRUPTED;
    559 		goto out;
    560 	}
    561 
    562 	/*
    563 	 * Force the inlinedata attr to the front and the empty entries
    564 	 * to the end.
    565 	 */
    566 	x = handle->attrs;
    567 	qsort(x, handle->length, sizeof(struct ext2_xattr), attr_compare);
    568 
    569 	/* Does the inode have space for EA? */
    570 	if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
    571 	    EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
    572 						  inode->i_extra_isize +
    573 						  sizeof(__u32))
    574 		goto write_ea_block;
    575 
    576 	/* Write the inode EA */
    577 	ea_inode_magic = EXT2_EXT_ATTR_MAGIC;
    578 	memcpy(((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    579 	       inode->i_extra_isize, &ea_inode_magic, sizeof(__u32));
    580 	storage_size = EXT2_INODE_SIZE(handle->fs->super) -
    581 		EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize -
    582 		sizeof(__u32);
    583 	start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    584 		inode->i_extra_isize + sizeof(__u32);
    585 
    586 	err = write_xattrs_to_buffer(handle, &x, start, storage_size, 0, 0);
    587 	if (err)
    588 		goto out;
    589 
    590 write_ea_block:
    591 	/* Are we done? */
    592 	if (x >= handle->attrs + handle->count)
    593 		goto skip_ea_block;
    594 
    595 	/* Write the EA block */
    596 	err = ext2fs_get_memzero(handle->fs->blocksize, &block_buf);
    597 	if (err)
    598 		goto out;
    599 
    600 	storage_size = handle->fs->blocksize -
    601 		sizeof(struct ext2_ext_attr_header);
    602 	start = block_buf + sizeof(struct ext2_ext_attr_header);
    603 
    604 	err = write_xattrs_to_buffer(handle, &x, start, storage_size,
    605 				     start - block_buf, 1);
    606 	if (err)
    607 		goto out2;
    608 
    609 	if (x < handle->attrs + handle->length) {
    610 		err = EXT2_ET_EA_NO_SPACE;
    611 		goto out2;
    612 	}
    613 
    614 	/* Write a header on the EA block */
    615 	header = (struct ext2_ext_attr_header *) block_buf;
    616 	header->h_magic = EXT2_EXT_ATTR_MAGIC;
    617 	header->h_refcount = 1;
    618 	header->h_blocks = 1;
    619 
    620 	/* Get a new block for writing */
    621 	err = prep_ea_block_for_write(handle->fs, handle->ino, inode);
    622 	if (err)
    623 		goto out2;
    624 
    625 	/* Finally, write the new EA block */
    626 	blk = ext2fs_file_acl_block(handle->fs,
    627 				    (struct ext2_inode *)inode);
    628 	err = ext2fs_write_ext_attr3(handle->fs, blk, block_buf,
    629 				     handle->ino);
    630 	if (err)
    631 		goto out2;
    632 
    633 skip_ea_block:
    634 	blk = ext2fs_file_acl_block(handle->fs, (struct ext2_inode *)inode);
    635 	if (!block_buf && blk) {
    636 		/* xattrs shrunk, free the block */
    637 		err = ext2fs_free_ext_attr(handle->fs, handle->ino, inode);
    638 		if (err)
    639 			goto out;
    640 	}
    641 
    642 	/* Write the inode */
    643 	err = ext2fs_write_inode_full(handle->fs, handle->ino,
    644 				      (struct ext2_inode *)inode,
    645 				      EXT2_INODE_SIZE(handle->fs->super));
    646 	if (err)
    647 		goto out2;
    648 
    649 out2:
    650 	ext2fs_free_mem(&block_buf);
    651 out:
    652 	ext2fs_free_mem(&inode);
    653 	handle->dirty = 0;
    654 	return err;
    655 }
    656 
    657 static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle,
    658 					 struct ext2_ext_attr_entry *entries,
    659 					 unsigned int storage_size,
    660 					 char *value_start,
    661 					 size_t *nr_read)
    662 {
    663 	struct ext2_xattr *x;
    664 	struct ext2_ext_attr_entry *entry, *end;
    665 	const char *prefix;
    666 	unsigned int remain, prefix_len;
    667 	errcode_t err;
    668 	unsigned int values_size = storage_size +
    669 			((char *)entries - value_start);
    670 
    671 	x = handle->attrs;
    672 	while (x->name)
    673 		x++;
    674 
    675 	/* find the end */
    676 	end = entries;
    677 	remain = storage_size;
    678 	while (remain >= sizeof(struct ext2_ext_attr_entry) &&
    679 	       !EXT2_EXT_IS_LAST_ENTRY(end)) {
    680 
    681 		/* header eats this space */
    682 		remain -= sizeof(struct ext2_ext_attr_entry);
    683 
    684 		/* is attribute name valid? */
    685 		if (EXT2_EXT_ATTR_SIZE(end->e_name_len) > remain)
    686 			return EXT2_ET_EA_BAD_NAME_LEN;
    687 
    688 		/* attribute len eats this space */
    689 		remain -= EXT2_EXT_ATTR_SIZE(end->e_name_len);
    690 		end = EXT2_EXT_ATTR_NEXT(end);
    691 	}
    692 
    693 	entry = entries;
    694 	remain = storage_size;
    695 	while (remain >= sizeof(struct ext2_ext_attr_entry) &&
    696 	       !EXT2_EXT_IS_LAST_ENTRY(entry)) {
    697 		__u32 hash;
    698 
    699 		/* header eats this space */
    700 		remain -= sizeof(struct ext2_ext_attr_entry);
    701 
    702 		/* attribute len eats this space */
    703 		remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
    704 
    705 		/* check value size */
    706 		if (entry->e_value_size > remain)
    707 			return EXT2_ET_EA_BAD_VALUE_SIZE;
    708 
    709 		if (entry->e_value_offs + entry->e_value_size > values_size)
    710 			return EXT2_ET_EA_BAD_VALUE_OFFSET;
    711 
    712 		if (entry->e_value_size > 0 &&
    713 		    value_start + entry->e_value_offs <
    714 		    (char *)end + sizeof(__u32))
    715 			return EXT2_ET_EA_BAD_VALUE_OFFSET;
    716 
    717 		/* e_value_block must be 0 in inode's ea */
    718 		if (entry->e_value_block != 0)
    719 			return EXT2_ET_BAD_EA_BLOCK_NUM;
    720 
    721 		hash = ext2fs_ext_attr_hash_entry(entry, value_start +
    722 							 entry->e_value_offs);
    723 
    724 		/* e_hash may be 0 in older inode's ea */
    725 		if (entry->e_hash != 0 && entry->e_hash != hash)
    726 			return EXT2_ET_BAD_EA_HASH;
    727 
    728 		remain -= entry->e_value_size;
    729 
    730 		/* Allocate space for more attrs? */
    731 		if (x == handle->attrs + handle->length) {
    732 			err = ext2fs_xattrs_expand(handle, 4);
    733 			if (err)
    734 				return err;
    735 			x = handle->attrs + handle->length - 4;
    736 		}
    737 
    738 		/* Extract name/value */
    739 		prefix = find_ea_prefix(entry->e_name_index);
    740 		prefix_len = (prefix ? strlen(prefix) : 0);
    741 		err = ext2fs_get_memzero(entry->e_name_len + prefix_len + 1,
    742 					 &x->name);
    743 		if (err)
    744 			return err;
    745 		if (prefix)
    746 			memcpy(x->name, prefix, prefix_len);
    747 		if (entry->e_name_len)
    748 			memcpy(x->name + prefix_len,
    749 			       (char *)entry + sizeof(*entry),
    750 			       entry->e_name_len);
    751 
    752 		err = ext2fs_get_mem(entry->e_value_size, &x->value);
    753 		if (err)
    754 			return err;
    755 		x->value_len = entry->e_value_size;
    756 		memcpy(x->value, value_start + entry->e_value_offs,
    757 		       entry->e_value_size);
    758 		x++;
    759 		(*nr_read)++;
    760 		entry = EXT2_EXT_ATTR_NEXT(entry);
    761 	}
    762 
    763 	return 0;
    764 }
    765 
    766 static void xattrs_free_keys(struct ext2_xattr_handle *h)
    767 {
    768 	struct ext2_xattr *a = h->attrs;
    769 	size_t i;
    770 
    771 	for (i = 0; i < h->length; i++) {
    772 		if (a[i].name)
    773 			ext2fs_free_mem(&a[i].name);
    774 		if (a[i].value)
    775 			ext2fs_free_mem(&a[i].value);
    776 	}
    777 	h->count = 0;
    778 }
    779 
    780 errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle)
    781 {
    782 	struct ext2_inode_large *inode;
    783 	struct ext2_ext_attr_header *header;
    784 	__u32 ea_inode_magic;
    785 	unsigned int storage_size;
    786 	char *start, *block_buf = NULL;
    787 	blk64_t blk;
    788 	size_t i;
    789 	errcode_t err;
    790 
    791 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
    792 	i = EXT2_INODE_SIZE(handle->fs->super);
    793 	if (i < sizeof(*inode))
    794 		i = sizeof(*inode);
    795 	err = ext2fs_get_memzero(i, &inode);
    796 	if (err)
    797 		return err;
    798 
    799 	err = ext2fs_read_inode_full(handle->fs, handle->ino,
    800 				     (struct ext2_inode *)inode,
    801 				     EXT2_INODE_SIZE(handle->fs->super));
    802 	if (err)
    803 		goto out;
    804 
    805 	xattrs_free_keys(handle);
    806 
    807 	/* Does the inode have space for EA? */
    808 	if (inode->i_extra_isize < sizeof(inode->i_extra_isize) ||
    809 	    EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
    810 						  inode->i_extra_isize +
    811 						  sizeof(__u32))
    812 		goto read_ea_block;
    813 	if (inode->i_extra_isize & 3) {
    814 		err = EXT2_ET_INODE_CORRUPTED;
    815 		goto out;
    816 	}
    817 
    818 	/* Look for EA in the inode */
    819 	memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    820 	       inode->i_extra_isize, sizeof(__u32));
    821 	if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) {
    822 		storage_size = EXT2_INODE_SIZE(handle->fs->super) -
    823 			EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize -
    824 			sizeof(__u32);
    825 		start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    826 			inode->i_extra_isize + sizeof(__u32);
    827 
    828 		err = read_xattrs_from_buffer(handle,
    829 			(struct ext2_ext_attr_entry *) start, storage_size,
    830 					      start, &handle->count);
    831 		if (err)
    832 			goto out;
    833 	}
    834 
    835 read_ea_block:
    836 	/* Look for EA in a separate EA block */
    837 	blk = ext2fs_file_acl_block(handle->fs, (struct ext2_inode *)inode);
    838 	if (blk != 0) {
    839 		if ((blk < handle->fs->super->s_first_data_block) ||
    840 		    (blk >= ext2fs_blocks_count(handle->fs->super))) {
    841 			err = EXT2_ET_BAD_EA_BLOCK_NUM;
    842 			goto out;
    843 		}
    844 
    845 		err = ext2fs_get_mem(handle->fs->blocksize, &block_buf);
    846 		if (err)
    847 			goto out;
    848 
    849 		err = ext2fs_read_ext_attr3(handle->fs, blk, block_buf,
    850 					    handle->ino);
    851 		if (err)
    852 			goto out3;
    853 
    854 		/* We only know how to deal with v2 EA blocks */
    855 		header = (struct ext2_ext_attr_header *) block_buf;
    856 		if (header->h_magic != EXT2_EXT_ATTR_MAGIC) {
    857 			err = EXT2_ET_BAD_EA_HEADER;
    858 			goto out3;
    859 		}
    860 
    861 		/* Read EAs */
    862 		storage_size = handle->fs->blocksize -
    863 			sizeof(struct ext2_ext_attr_header);
    864 		start = block_buf + sizeof(struct ext2_ext_attr_header);
    865 		err = read_xattrs_from_buffer(handle,
    866 			(struct ext2_ext_attr_entry *) start, storage_size,
    867 					      block_buf, &handle->count);
    868 		if (err)
    869 			goto out3;
    870 
    871 		ext2fs_free_mem(&block_buf);
    872 	}
    873 
    874 	ext2fs_free_mem(&block_buf);
    875 	ext2fs_free_mem(&inode);
    876 	return 0;
    877 
    878 out3:
    879 	ext2fs_free_mem(&block_buf);
    880 out:
    881 	ext2fs_free_mem(&inode);
    882 	return err;
    883 }
    884 
    885 errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h,
    886 				int (*func)(char *name, char *value,
    887 					    size_t value_len, void *data),
    888 				void *data)
    889 {
    890 	struct ext2_xattr *x;
    891 	int ret;
    892 
    893 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
    894 	for (x = h->attrs; x < h->attrs + h->length; x++) {
    895 		if (!x->name)
    896 			continue;
    897 
    898 		ret = func(x->name, x->value, x->value_len, data);
    899 		if (ret & XATTR_CHANGED)
    900 			h->dirty = 1;
    901 		if (ret & XATTR_ABORT)
    902 			return 0;
    903 	}
    904 
    905 	return 0;
    906 }
    907 
    908 errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key,
    909 			   void **value, size_t *value_len)
    910 {
    911 	struct ext2_xattr *x;
    912 	char *val;
    913 	errcode_t err;
    914 
    915 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
    916 	for (x = h->attrs; x < h->attrs + h->length; x++) {
    917 		if (!x->name)
    918 			continue;
    919 
    920 		if (strcmp(x->name, key) == 0) {
    921 			err = ext2fs_get_mem(x->value_len, &val);
    922 			if (err)
    923 				return err;
    924 			memcpy(val, x->value, x->value_len);
    925 			*value = val;
    926 			*value_len = x->value_len;
    927 			return 0;
    928 		}
    929 	}
    930 
    931 	return EXT2_ET_EA_KEY_NOT_FOUND;
    932 }
    933 
    934 errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino,
    935 				      size_t *size)
    936 {
    937 	struct ext2_ext_attr_entry *entry;
    938 	struct ext2_inode_large *inode;
    939 	__u32 ea_inode_magic;
    940 	unsigned int minoff;
    941 	char *start;
    942 	size_t i;
    943 	errcode_t err;
    944 
    945 	i = EXT2_INODE_SIZE(fs->super);
    946 	if (i < sizeof(*inode))
    947 		i = sizeof(*inode);
    948 	err = ext2fs_get_memzero(i, &inode);
    949 	if (err)
    950 		return err;
    951 
    952 	err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)inode,
    953 				     EXT2_INODE_SIZE(fs->super));
    954 	if (err)
    955 		goto out;
    956 
    957 	/* Does the inode have size for EA? */
    958 	if (EXT2_INODE_SIZE(fs->super) <= EXT2_GOOD_OLD_INODE_SIZE +
    959 						  inode->i_extra_isize +
    960 						  sizeof(__u32)) {
    961 		err = EXT2_ET_INLINE_DATA_NO_SPACE;
    962 		goto out;
    963 	}
    964 
    965 	minoff = EXT2_INODE_SIZE(fs->super) - sizeof(*inode) - sizeof(__u32);
    966 	memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    967 	       inode->i_extra_isize, sizeof(__u32));
    968 	if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) {
    969 		/* has xattrs.  calculate the size */
    970 		start= ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
    971 			inode->i_extra_isize + sizeof(__u32);
    972 		entry = (struct ext2_ext_attr_entry *) start;
    973 		while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
    974 			if (!entry->e_value_block && entry->e_value_size) {
    975 				unsigned int offs = entry->e_value_offs;
    976 				if (offs < minoff)
    977 					minoff = offs;
    978 			}
    979 			entry = EXT2_EXT_ATTR_NEXT(entry);
    980 		}
    981 		*size = minoff - ((char *)entry - (char *)start) - sizeof(__u32);
    982 	} else {
    983 		/* no xattr.  return a maximum size */
    984 		*size = EXT2_EXT_ATTR_SIZE(minoff -
    985 					   EXT2_EXT_ATTR_LEN(strlen("data")) -
    986 					   EXT2_EXT_ATTR_ROUND - sizeof(__u32));
    987 	}
    988 
    989 out:
    990 	ext2fs_free_mem(&inode);
    991 	return err;
    992 }
    993 
    994 errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *handle,
    995 			   const char *key,
    996 			   const void *value,
    997 			   size_t value_len)
    998 {
    999 	struct ext2_xattr *x, *last_empty;
   1000 	char *new_value;
   1001 	errcode_t err;
   1002 
   1003 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
   1004 	last_empty = NULL;
   1005 	for (x = handle->attrs; x < handle->attrs + handle->length; x++) {
   1006 		if (!x->name) {
   1007 			last_empty = x;
   1008 			continue;
   1009 		}
   1010 
   1011 		/* Replace xattr */
   1012 		if (strcmp(x->name, key) == 0) {
   1013 			err = ext2fs_get_mem(value_len, &new_value);
   1014 			if (err)
   1015 				return err;
   1016 			memcpy(new_value, value, value_len);
   1017 			ext2fs_free_mem(&x->value);
   1018 			x->value = new_value;
   1019 			x->value_len = value_len;
   1020 			handle->dirty = 1;
   1021 			return 0;
   1022 		}
   1023 	}
   1024 
   1025 	/* Add attr to empty slot */
   1026 	if (last_empty) {
   1027 		err = ext2fs_get_mem(strlen(key) + 1, &last_empty->name);
   1028 		if (err)
   1029 			return err;
   1030 		strcpy(last_empty->name, key);
   1031 
   1032 		err = ext2fs_get_mem(value_len, &last_empty->value);
   1033 		if (err)
   1034 			return err;
   1035 		memcpy(last_empty->value, value, value_len);
   1036 		last_empty->value_len = value_len;
   1037 		handle->dirty = 1;
   1038 		handle->count++;
   1039 		return 0;
   1040 	}
   1041 
   1042 	/* Expand array, append slot */
   1043 	err = ext2fs_xattrs_expand(handle, 4);
   1044 	if (err)
   1045 		return err;
   1046 
   1047 	x = handle->attrs + handle->length - 4;
   1048 	err = ext2fs_get_mem(strlen(key) + 1, &x->name);
   1049 	if (err)
   1050 		return err;
   1051 	strcpy(x->name, key);
   1052 
   1053 	err = ext2fs_get_mem(value_len, &x->value);
   1054 	if (err)
   1055 		return err;
   1056 	memcpy(x->value, value, value_len);
   1057 	x->value_len = value_len;
   1058 	handle->dirty = 1;
   1059 	handle->count++;
   1060 	return 0;
   1061 }
   1062 
   1063 errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle,
   1064 			      const char *key)
   1065 {
   1066 	struct ext2_xattr *x;
   1067 
   1068 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
   1069 	for (x = handle->attrs; x < handle->attrs + handle->length; x++) {
   1070 		if (!x->name)
   1071 			continue;
   1072 
   1073 		if (strcmp(x->name, key) == 0) {
   1074 			ext2fs_free_mem(&x->name);
   1075 			ext2fs_free_mem(&x->value);
   1076 			x->value_len = 0;
   1077 			handle->dirty = 1;
   1078 			handle->count--;
   1079 			return 0;
   1080 		}
   1081 	}
   1082 
   1083 	/* no key found, success! */
   1084 	return 0;
   1085 }
   1086 
   1087 errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino,
   1088 			     struct ext2_xattr_handle **handle)
   1089 {
   1090 	struct ext2_xattr_handle *h;
   1091 	errcode_t err;
   1092 
   1093 	if (!ext2fs_has_feature_xattr(fs->super) &&
   1094 	    !ext2fs_has_feature_inline_data(fs->super))
   1095 		return EXT2_ET_MISSING_EA_FEATURE;
   1096 
   1097 	err = ext2fs_get_memzero(sizeof(*h), &h);
   1098 	if (err)
   1099 		return err;
   1100 
   1101 	h->magic = EXT2_ET_MAGIC_EA_HANDLE;
   1102 	h->length = 4;
   1103 	err = ext2fs_get_arrayzero(h->length, sizeof(struct ext2_xattr),
   1104 				   &h->attrs);
   1105 	if (err) {
   1106 		ext2fs_free_mem(&h);
   1107 		return err;
   1108 	}
   1109 	h->count = 0;
   1110 	h->ino = ino;
   1111 	h->fs = fs;
   1112 	*handle = h;
   1113 	return 0;
   1114 }
   1115 
   1116 errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle)
   1117 {
   1118 	struct ext2_xattr_handle *h = *handle;
   1119 	errcode_t err;
   1120 
   1121 	EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE);
   1122 	if (h->dirty) {
   1123 		err = ext2fs_xattrs_write(h);
   1124 		if (err)
   1125 			return err;
   1126 	}
   1127 
   1128 	xattrs_free_keys(h);
   1129 	ext2fs_free_mem(&h->attrs);
   1130 	ext2fs_free_mem(handle);
   1131 	return 0;
   1132 }
   1133 
   1134 errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count)
   1135 {
   1136 	EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE);
   1137 	*count = handle->count;
   1138 	return 0;
   1139 }
   1140