2 * ext_attr.c --- extended attribute blocks
4 * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
6 * Copyright (C) 2002 Theodore Ts'o.
9 * This file may be redistributed under the terms of the GNU Library
10 * General Public License, version 2.
23 #include "ext2_ext_attr.h"
27 #define NAME_HASH_SHIFT 5
28 #define VALUE_HASH_SHIFT 16
31 * ext2_xattr_hash_entry()
33 * Compute the hash of an extended attribute.
35 __u32
ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry
*entry
, void *data
)
38 char *name
= ((char *) entry
) + sizeof(struct ext2_ext_attr_entry
);
41 for (n
= 0; n
< entry
->e_name_len
; n
++) {
42 hash
= (hash
<< NAME_HASH_SHIFT
) ^
43 (hash
>> (8*sizeof(hash
) - NAME_HASH_SHIFT
)) ^
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
++);
61 static errcode_t
check_ext_attr_header(struct ext2_ext_attr_header
*header
)
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
;
71 #undef NAME_HASH_SHIFT
72 #undef VALUE_HASH_SHIFT
74 errcode_t
ext2fs_read_ext_attr3(ext2_filsys fs
, blk64_t block
, void *buf
,
80 retval
= io_channel_read_blk64(fs
->io
, block
, 1, buf
);
84 if (!(fs
->flags
& EXT2_FLAG_IGNORE_CSUM_ERRORS
) &&
85 !ext2fs_ext_attr_block_csum_verify(fs
, inum
, block
, buf
))
88 #ifdef WORDS_BIGENDIAN
89 ext2fs_swap_ext_attr(buf
, buf
, fs
->blocksize
, 1);
92 retval
= check_ext_attr_header(buf
);
93 if (retval
== 0 && csum_failed
)
94 retval
= EXT2_ET_EXT_ATTR_CSUM_INVALID
;
99 errcode_t
ext2fs_read_ext_attr2(ext2_filsys fs
, blk64_t block
, void *buf
)
101 return ext2fs_read_ext_attr3(fs
, block
, buf
, 0);
104 errcode_t
ext2fs_read_ext_attr(ext2_filsys fs
, blk_t block
, void *buf
)
106 return ext2fs_read_ext_attr2(fs
, block
, buf
);
109 errcode_t
ext2fs_write_ext_attr3(ext2_filsys fs
, blk64_t block
, void *inbuf
,
115 #ifdef WORDS_BIGENDIAN
116 retval
= ext2fs_get_mem(fs
->blocksize
, &write_buf
);
119 ext2fs_swap_ext_attr(write_buf
, inbuf
, fs
->blocksize
, 1);
121 write_buf
= (char *) inbuf
;
124 retval
= ext2fs_ext_attr_block_csum_set(fs
, inum
, block
,
125 (struct ext2_ext_attr_header
*)write_buf
);
129 retval
= io_channel_write_blk64(fs
->io
, block
, 1, write_buf
);
130 #ifdef WORDS_BIGENDIAN
131 ext2fs_free_mem(&write_buf
);
134 ext2fs_mark_changed(fs
);
138 errcode_t
ext2fs_write_ext_attr2(ext2_filsys fs
, blk64_t block
, void *inbuf
)
140 return ext2fs_write_ext_attr3(fs
, block
, inbuf
, 0);
143 errcode_t
ext2fs_write_ext_attr(ext2_filsys fs
, blk_t block
, void *inbuf
)
145 return ext2fs_write_ext_attr2(fs
, block
, inbuf
);
149 * This function adjusts the reference count of the EA block.
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
)
156 struct ext2_ext_attr_header
*header
;
159 if ((blk
>= ext2fs_blocks_count(fs
->super
)) ||
160 (blk
< fs
->super
->s_first_data_block
))
161 return EXT2_ET_BAD_EA_BLOCK_NUM
;
164 retval
= ext2fs_get_mem(fs
->blocksize
, &buf
);
170 retval
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, inum
);
174 header
= (struct ext2_ext_attr_header
*) block_buf
;
175 header
->h_refcount
+= adjust
;
177 *newcount
= header
->h_refcount
;
179 retval
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, inum
);
185 ext2fs_free_mem(&buf
);
189 errcode_t
ext2fs_adjust_ea_refcount2(ext2_filsys fs
, blk64_t blk
,
190 char *block_buf
, int adjust
,
193 return ext2fs_adjust_ea_refcount3(fs
, blk
, block_buf
, adjust
,
197 errcode_t
ext2fs_adjust_ea_refcount(ext2_filsys fs
, blk_t blk
,
198 char *block_buf
, int adjust
,
201 return ext2fs_adjust_ea_refcount2(fs
, blk
, block_buf
, adjust
,
205 /* Manipulate the contents of extended attribute regions */
212 struct ext2_xattr_handle
{
215 struct ext2_xattr
*attrs
;
216 size_t length
, count
;
221 static errcode_t
ext2fs_xattrs_expand(struct ext2_xattr_handle
*h
,
222 unsigned int expandby
)
224 struct ext2_xattr
*new_attrs
;
227 err
= ext2fs_get_arrayzero(h
->length
+ expandby
,
228 sizeof(struct ext2_xattr
), &new_attrs
);
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
;
240 struct ea_name_index
{
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"},
257 static int find_ea_index(char *fullname
, char **name
, int *index
);
259 /* Push empty attributes to the end and inlinedata to the front. */
260 static int attr_compare(const void *a
, const void *b
)
262 const struct ext2_xattr
*xa
= a
, *xb
= b
;
263 char *xa_suffix
, *xb_suffix
;
267 if (xa
->name
== NULL
)
269 else if (xb
->name
== NULL
)
271 else if (!strcmp(xa
->name
, "system.data"))
273 else if (!strcmp(xb
->name
, "system.data"))
277 * Duplicate the kernel's sorting algorithm because xattr blocks
278 * require sorted keys.
280 xa_suffix
= xa
->name
;
281 xb_suffix
= xb
->name
;
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
;
288 cmp
= strlen(xa_suffix
) - strlen(xb_suffix
);
291 cmp
= strcmp(xa_suffix
, xb_suffix
);
295 static const char *find_ea_prefix(int index
)
297 struct ea_name_index
*e
;
299 for (e
= ea_names
; e
->name
; e
++)
300 if (e
->index
== index
)
306 static int find_ea_index(char *fullname
, char **name
, int *index
)
308 struct ea_name_index
*e
;
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
);
320 errcode_t
ext2fs_free_ext_attr(ext2_filsys fs
, ext2_ino_t ino
,
321 struct ext2_inode_large
*inode
)
323 struct ext2_ext_attr_header
*header
;
324 void *block_buf
= NULL
;
327 struct ext2_inode_large i
;
331 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&i
,
332 sizeof(struct ext2_inode_large
));
338 /* Do we already have an EA block? */
339 blk
= ext2fs_file_acl_block(fs
, (struct ext2_inode
*)inode
);
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
;
350 err
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
354 err
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, ino
);
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
;
365 header
->h_refcount
--;
366 err
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, ino
);
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);
380 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&i
,
381 sizeof(struct ext2_inode_large
));
387 ext2fs_free_mem(&block_buf
);
392 static errcode_t
prep_ea_block_for_write(ext2_filsys fs
, ext2_ino_t ino
,
393 struct ext2_inode_large
*inode
)
395 struct ext2_ext_attr_header
*header
;
396 void *block_buf
= NULL
;
400 /* Do we already have an EA block? */
401 blk
= ext2fs_file_acl_block(fs
, (struct ext2_inode
*)inode
);
403 if ((blk
< fs
->super
->s_first_data_block
) ||
404 (blk
>= ext2fs_blocks_count(fs
->super
))) {
405 err
= EXT2_ET_BAD_EA_BLOCK_NUM
;
409 err
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
413 err
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, ino
);
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
;
424 /* Single-user block. We're done here. */
425 if (header
->h_refcount
== 1)
428 /* We need to CoW the block. */
429 header
->h_refcount
--;
430 err
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, ino
);
434 /* No block, we must increment i_blocks */
435 err
= ext2fs_iblk_add_blocks(fs
, (struct ext2_inode
*)inode
,
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
);
446 ext2fs_file_acl_block_set(fs
, (struct ext2_inode
*)inode
, blk
);
449 ext2fs_free_mem(&block_buf
);
455 static errcode_t
write_xattrs_to_buffer(struct ext2_xattr_handle
*handle
,
456 struct ext2_xattr
**pos
,
458 unsigned int storage_size
,
459 unsigned int value_offset_correction
,
462 struct ext2_xattr
*x
= *pos
;
463 struct ext2_ext_attr_entry
*e
= entries_start
;
464 char *end
= (char *) entries_start
+ storage_size
;
466 unsigned int entry_size
, value_size
;
469 memset(entries_start
, 0, storage_size
);
470 /* For all remaining x... */
471 for (; x
< handle
->attrs
+ handle
->length
; x
++) {
475 /* Calculate index and shortname position */
477 ret
= find_ea_index(x
->name
, &shortname
, &idx
);
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
;
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.
491 if ((char *)e
+ entry_size
+ sizeof(__u32
) > end
- value_size
)
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
;
502 /* Store name and value */
504 memcpy((char *)e
+ sizeof(*e
), shortname
, e
->e_name_len
);
505 memcpy(end
, x
->value
, e
->e_value_size
);
508 e
->e_hash
= ext2fs_ext_attr_hash_entry(e
, end
);
512 e
= EXT2_EXT_ATTR_NEXT(e
);
520 errcode_t
ext2fs_xattrs_write(struct ext2_xattr_handle
*handle
)
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
;
528 unsigned int storage_size
;
532 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
533 i
= EXT2_INODE_SIZE(handle
->fs
->super
);
534 if (i
< sizeof(*inode
))
536 err
= ext2fs_get_memzero(i
, &inode
);
540 err
= ext2fs_read_inode_full(handle
->fs
, handle
->ino
,
541 (struct ext2_inode
*)inode
,
542 EXT2_INODE_SIZE(handle
->fs
->super
));
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
;
553 extra
= sizeof(__u32
);
554 memset(p
+ EXT2_GOOD_OLD_INODE_SIZE
, 0, extra
);
555 inode
->i_extra_isize
= extra
;
559 * Force the inlinedata attr to the front and the empty entries
563 qsort(x
, handle
->length
, sizeof(struct ext2_xattr
), attr_compare
);
565 /* Does the inode have space for EA? */
566 if (inode
->i_extra_isize
< sizeof(inode
->i_extra_isize
) ||
567 EXT2_INODE_SIZE(handle
->fs
->super
) <= EXT2_GOOD_OLD_INODE_SIZE
+
568 inode
->i_extra_isize
+
572 /* Write the inode EA */
573 ea_inode_magic
= EXT2_EXT_ATTR_MAGIC
;
574 memcpy(((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
575 inode
->i_extra_isize
, &ea_inode_magic
, sizeof(__u32
));
576 storage_size
= EXT2_INODE_SIZE(handle
->fs
->super
) -
577 EXT2_GOOD_OLD_INODE_SIZE
- inode
->i_extra_isize
-
579 start
= ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
580 inode
->i_extra_isize
+ sizeof(__u32
);
582 err
= write_xattrs_to_buffer(handle
, &x
, start
, storage_size
, 0, 0);
588 if (x
>= handle
->attrs
+ handle
->count
)
591 /* Write the EA block */
592 err
= ext2fs_get_memzero(handle
->fs
->blocksize
, &block_buf
);
596 storage_size
= handle
->fs
->blocksize
-
597 sizeof(struct ext2_ext_attr_header
);
598 start
= block_buf
+ sizeof(struct ext2_ext_attr_header
);
600 err
= write_xattrs_to_buffer(handle
, &x
, start
, storage_size
,
601 start
- block_buf
, 1);
605 if (x
< handle
->attrs
+ handle
->length
) {
606 err
= EXT2_ET_EA_NO_SPACE
;
610 /* Write a header on the EA block */
611 header
= (struct ext2_ext_attr_header
*) block_buf
;
612 header
->h_magic
= EXT2_EXT_ATTR_MAGIC
;
613 header
->h_refcount
= 1;
614 header
->h_blocks
= 1;
616 /* Get a new block for writing */
617 err
= prep_ea_block_for_write(handle
->fs
, handle
->ino
, inode
);
621 /* Finally, write the new EA block */
622 blk
= ext2fs_file_acl_block(handle
->fs
,
623 (struct ext2_inode
*)inode
);
624 err
= ext2fs_write_ext_attr3(handle
->fs
, blk
, block_buf
,
630 blk
= ext2fs_file_acl_block(handle
->fs
, (struct ext2_inode
*)inode
);
631 if (!block_buf
&& blk
) {
632 /* xattrs shrunk, free the block */
633 err
= ext2fs_free_ext_attr(handle
->fs
, handle
->ino
, inode
);
638 /* Write the inode */
639 err
= ext2fs_write_inode_full(handle
->fs
, handle
->ino
,
640 (struct ext2_inode
*)inode
,
641 EXT2_INODE_SIZE(handle
->fs
->super
));
646 ext2fs_free_mem(&block_buf
);
648 ext2fs_free_mem(&inode
);
653 static errcode_t
read_xattrs_from_buffer(struct ext2_xattr_handle
*handle
,
654 struct ext2_ext_attr_entry
*entries
,
655 unsigned int storage_size
,
659 struct ext2_xattr
*x
;
660 struct ext2_ext_attr_entry
*entry
, *end
;
662 unsigned int remain
, prefix_len
;
664 unsigned int values_size
= storage_size
+
665 ((char *)entries
- value_start
);
673 remain
= storage_size
;
674 while (remain
>= sizeof(struct ext2_ext_attr_entry
) &&
675 !EXT2_EXT_IS_LAST_ENTRY(end
)) {
677 /* header eats this space */
678 remain
-= sizeof(struct ext2_ext_attr_entry
);
680 /* is attribute name valid? */
681 if (EXT2_EXT_ATTR_SIZE(end
->e_name_len
) > remain
)
682 return EXT2_ET_EA_BAD_NAME_LEN
;
684 /* attribute len eats this space */
685 remain
-= EXT2_EXT_ATTR_SIZE(end
->e_name_len
);
686 end
= EXT2_EXT_ATTR_NEXT(end
);
690 remain
= storage_size
;
691 while (remain
>= sizeof(struct ext2_ext_attr_entry
) &&
692 !EXT2_EXT_IS_LAST_ENTRY(entry
)) {
695 /* header eats this space */
696 remain
-= sizeof(struct ext2_ext_attr_entry
);
698 /* attribute len eats this space */
699 remain
-= EXT2_EXT_ATTR_SIZE(entry
->e_name_len
);
701 /* check value size */
702 if (entry
->e_value_size
> remain
)
703 return EXT2_ET_EA_BAD_VALUE_SIZE
;
705 if (entry
->e_value_offs
+ entry
->e_value_size
> values_size
)
706 return EXT2_ET_EA_BAD_VALUE_OFFSET
;
708 if (entry
->e_value_size
> 0 &&
709 value_start
+ entry
->e_value_offs
<
710 (char *)end
+ sizeof(__u32
))
711 return EXT2_ET_EA_BAD_VALUE_OFFSET
;
713 /* e_value_block must be 0 in inode's ea */
714 if (entry
->e_value_block
!= 0)
715 return EXT2_ET_BAD_EA_BLOCK_NUM
;
717 hash
= ext2fs_ext_attr_hash_entry(entry
, value_start
+
718 entry
->e_value_offs
);
720 /* e_hash may be 0 in older inode's ea */
721 if (entry
->e_hash
!= 0 && entry
->e_hash
!= hash
)
722 return EXT2_ET_BAD_EA_HASH
;
724 remain
-= entry
->e_value_size
;
726 /* Allocate space for more attrs? */
727 if (x
== handle
->attrs
+ handle
->length
) {
728 err
= ext2fs_xattrs_expand(handle
, 4);
731 x
= handle
->attrs
+ handle
->length
- 4;
734 /* Extract name/value */
735 prefix
= find_ea_prefix(entry
->e_name_index
);
736 prefix_len
= (prefix
? strlen(prefix
) : 0);
737 err
= ext2fs_get_memzero(entry
->e_name_len
+ prefix_len
+ 1,
742 memcpy(x
->name
, prefix
, prefix_len
);
743 if (entry
->e_name_len
)
744 memcpy(x
->name
+ prefix_len
,
745 (char *)entry
+ sizeof(*entry
),
748 err
= ext2fs_get_mem(entry
->e_value_size
, &x
->value
);
751 x
->value_len
= entry
->e_value_size
;
752 memcpy(x
->value
, value_start
+ entry
->e_value_offs
,
753 entry
->e_value_size
);
756 entry
= EXT2_EXT_ATTR_NEXT(entry
);
762 static void xattrs_free_keys(struct ext2_xattr_handle
*h
)
764 struct ext2_xattr
*a
= h
->attrs
;
767 for (i
= 0; i
< h
->length
; i
++) {
769 ext2fs_free_mem(&a
[i
].name
);
771 ext2fs_free_mem(&a
[i
].value
);
776 errcode_t
ext2fs_xattrs_read(struct ext2_xattr_handle
*handle
)
778 struct ext2_inode_large
*inode
;
779 struct ext2_ext_attr_header
*header
;
780 __u32 ea_inode_magic
;
781 unsigned int storage_size
;
782 char *start
, *block_buf
= NULL
;
787 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
788 i
= EXT2_INODE_SIZE(handle
->fs
->super
);
789 if (i
< sizeof(*inode
))
791 err
= ext2fs_get_memzero(i
, &inode
);
795 err
= ext2fs_read_inode_full(handle
->fs
, handle
->ino
,
796 (struct ext2_inode
*)inode
,
797 EXT2_INODE_SIZE(handle
->fs
->super
));
801 xattrs_free_keys(handle
);
803 /* Does the inode have space for EA? */
804 if (inode
->i_extra_isize
< sizeof(inode
->i_extra_isize
) ||
805 EXT2_INODE_SIZE(handle
->fs
->super
) <= EXT2_GOOD_OLD_INODE_SIZE
+
806 inode
->i_extra_isize
+
810 /* Look for EA in the inode */
811 memcpy(&ea_inode_magic
, ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
812 inode
->i_extra_isize
, sizeof(__u32
));
813 if (ea_inode_magic
== EXT2_EXT_ATTR_MAGIC
) {
814 storage_size
= EXT2_INODE_SIZE(handle
->fs
->super
) -
815 EXT2_GOOD_OLD_INODE_SIZE
- inode
->i_extra_isize
-
817 start
= ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
818 inode
->i_extra_isize
+ sizeof(__u32
);
820 err
= read_xattrs_from_buffer(handle
,
821 (struct ext2_ext_attr_entry
*) start
, storage_size
,
822 start
, &handle
->count
);
828 /* Look for EA in a separate EA block */
829 blk
= ext2fs_file_acl_block(handle
->fs
, (struct ext2_inode
*)inode
);
831 if ((blk
< handle
->fs
->super
->s_first_data_block
) ||
832 (blk
>= ext2fs_blocks_count(handle
->fs
->super
))) {
833 err
= EXT2_ET_BAD_EA_BLOCK_NUM
;
837 err
= ext2fs_get_mem(handle
->fs
->blocksize
, &block_buf
);
841 err
= ext2fs_read_ext_attr3(handle
->fs
, blk
, block_buf
,
846 /* We only know how to deal with v2 EA blocks */
847 header
= (struct ext2_ext_attr_header
*) block_buf
;
848 if (header
->h_magic
!= EXT2_EXT_ATTR_MAGIC
) {
849 err
= EXT2_ET_BAD_EA_HEADER
;
854 storage_size
= handle
->fs
->blocksize
-
855 sizeof(struct ext2_ext_attr_header
);
856 start
= block_buf
+ sizeof(struct ext2_ext_attr_header
);
857 err
= read_xattrs_from_buffer(handle
,
858 (struct ext2_ext_attr_entry
*) start
, storage_size
,
859 block_buf
, &handle
->count
);
863 ext2fs_free_mem(&block_buf
);
866 ext2fs_free_mem(&block_buf
);
867 ext2fs_free_mem(&inode
);
871 ext2fs_free_mem(&block_buf
);
873 ext2fs_free_mem(&inode
);
877 errcode_t
ext2fs_xattrs_iterate(struct ext2_xattr_handle
*h
,
878 int (*func
)(char *name
, char *value
,
879 size_t value_len
, void *data
),
882 struct ext2_xattr
*x
;
885 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
886 for (x
= h
->attrs
; x
< h
->attrs
+ h
->length
; x
++) {
890 ret
= func(x
->name
, x
->value
, x
->value_len
, data
);
891 if (ret
& XATTR_CHANGED
)
893 if (ret
& XATTR_ABORT
)
900 errcode_t
ext2fs_xattr_get(struct ext2_xattr_handle
*h
, const char *key
,
901 void **value
, size_t *value_len
)
903 struct ext2_xattr
*x
;
907 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
908 for (x
= h
->attrs
; x
< h
->attrs
+ h
->length
; x
++) {
912 if (strcmp(x
->name
, key
) == 0) {
913 err
= ext2fs_get_mem(x
->value_len
, &val
);
916 memcpy(val
, x
->value
, x
->value_len
);
918 *value_len
= x
->value_len
;
923 return EXT2_ET_EA_KEY_NOT_FOUND
;
926 errcode_t
ext2fs_xattr_inode_max_size(ext2_filsys fs
, ext2_ino_t ino
,
929 struct ext2_ext_attr_entry
*entry
;
930 struct ext2_inode_large
*inode
;
931 __u32 ea_inode_magic
;
937 i
= EXT2_INODE_SIZE(fs
->super
);
938 if (i
< sizeof(*inode
))
940 err
= ext2fs_get_memzero(i
, &inode
);
944 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)inode
,
945 EXT2_INODE_SIZE(fs
->super
));
949 /* Does the inode have size for EA? */
950 if (EXT2_INODE_SIZE(fs
->super
) <= EXT2_GOOD_OLD_INODE_SIZE
+
951 inode
->i_extra_isize
+
953 err
= EXT2_ET_INLINE_DATA_NO_SPACE
;
957 minoff
= EXT2_INODE_SIZE(fs
->super
) - sizeof(*inode
) - sizeof(__u32
);
958 memcpy(&ea_inode_magic
, ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
959 inode
->i_extra_isize
, sizeof(__u32
));
960 if (ea_inode_magic
== EXT2_EXT_ATTR_MAGIC
) {
961 /* has xattrs. calculate the size */
962 start
= ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
963 inode
->i_extra_isize
+ sizeof(__u32
);
964 entry
= (struct ext2_ext_attr_entry
*) start
;
965 while (!EXT2_EXT_IS_LAST_ENTRY(entry
)) {
966 if (!entry
->e_value_block
&& entry
->e_value_size
) {
967 unsigned int offs
= entry
->e_value_offs
;
971 entry
= EXT2_EXT_ATTR_NEXT(entry
);
973 *size
= minoff
- ((char *)entry
- (char *)start
) - sizeof(__u32
);
975 /* no xattr. return a maximum size */
976 *size
= EXT2_EXT_ATTR_SIZE(minoff
-
977 EXT2_EXT_ATTR_LEN(strlen("data")) -
978 EXT2_EXT_ATTR_ROUND
- sizeof(__u32
));
982 ext2fs_free_mem(&inode
);
986 errcode_t
ext2fs_xattr_set(struct ext2_xattr_handle
*handle
,
991 struct ext2_xattr
*x
, *last_empty
;
995 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
997 for (x
= handle
->attrs
; x
< handle
->attrs
+ handle
->length
; x
++) {
1004 if (strcmp(x
->name
, key
) == 0) {
1005 err
= ext2fs_get_mem(value_len
, &new_value
);
1008 memcpy(new_value
, value
, value_len
);
1009 ext2fs_free_mem(&x
->value
);
1010 x
->value
= new_value
;
1011 x
->value_len
= value_len
;
1017 /* Add attr to empty slot */
1019 err
= ext2fs_get_mem(strlen(key
) + 1, &last_empty
->name
);
1022 strcpy(last_empty
->name
, key
);
1024 err
= ext2fs_get_mem(value_len
, &last_empty
->value
);
1027 memcpy(last_empty
->value
, value
, value_len
);
1028 last_empty
->value_len
= value_len
;
1034 /* Expand array, append slot */
1035 err
= ext2fs_xattrs_expand(handle
, 4);
1039 x
= handle
->attrs
+ handle
->length
- 4;
1040 err
= ext2fs_get_mem(strlen(key
) + 1, &x
->name
);
1043 strcpy(x
->name
, key
);
1045 err
= ext2fs_get_mem(value_len
, &x
->value
);
1048 memcpy(x
->value
, value
, value_len
);
1049 x
->value_len
= value_len
;
1055 errcode_t
ext2fs_xattr_remove(struct ext2_xattr_handle
*handle
,
1058 struct ext2_xattr
*x
;
1060 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1061 for (x
= handle
->attrs
; x
< handle
->attrs
+ handle
->length
; x
++) {
1065 if (strcmp(x
->name
, key
) == 0) {
1066 ext2fs_free_mem(&x
->name
);
1067 ext2fs_free_mem(&x
->value
);
1075 /* no key found, success! */
1079 errcode_t
ext2fs_xattrs_open(ext2_filsys fs
, ext2_ino_t ino
,
1080 struct ext2_xattr_handle
**handle
)
1082 struct ext2_xattr_handle
*h
;
1085 if (!ext2fs_has_feature_xattr(fs
->super
) &&
1086 !ext2fs_has_feature_inline_data(fs
->super
))
1087 return EXT2_ET_MISSING_EA_FEATURE
;
1089 err
= ext2fs_get_memzero(sizeof(*h
), &h
);
1093 h
->magic
= EXT2_ET_MAGIC_EA_HANDLE
;
1095 err
= ext2fs_get_arrayzero(h
->length
, sizeof(struct ext2_xattr
),
1098 ext2fs_free_mem(&h
);
1108 errcode_t
ext2fs_xattrs_close(struct ext2_xattr_handle
**handle
)
1110 struct ext2_xattr_handle
*h
= *handle
;
1113 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
1115 err
= ext2fs_xattrs_write(h
);
1120 xattrs_free_keys(h
);
1121 ext2fs_free_mem(&h
->attrs
);
1122 ext2fs_free_mem(handle
);
1126 errcode_t
ext2fs_xattrs_count(struct ext2_xattr_handle
*handle
, size_t *count
)
1128 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1129 *count
= handle
->count
;