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"
28 static errcode_t
read_ea_inode_hash(ext2_filsys fs
, ext2_ino_t ino
, __u32
*hash
)
30 struct ext2_inode inode
;
33 retval
= ext2fs_read_inode(fs
, ino
, &inode
);
36 *hash
= inode
.i_atime
;
40 #define NAME_HASH_SHIFT 5
41 #define VALUE_HASH_SHIFT 16
44 * ext2_xattr_hash_entry()
46 * Compute the hash of an extended attribute.
48 __u32
ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry
*entry
, void *data
)
51 char *name
= ((char *) entry
) + sizeof(struct ext2_ext_attr_entry
);
54 for (n
= 0; n
< entry
->e_name_len
; n
++) {
55 hash
= (hash
<< NAME_HASH_SHIFT
) ^
56 (hash
>> (8*sizeof(hash
) - NAME_HASH_SHIFT
)) ^
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
++);
75 * ext2fs_ext_attr_hash_entry2()
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).
81 errcode_t
ext2fs_ext_attr_hash_entry2(ext2_filsys fs
,
82 struct ext2_ext_attr_entry
*entry
,
83 void *data
, __u32
*hash
)
85 *hash
= ext2fs_ext_attr_hash_entry(entry
, data
);
87 if (entry
->e_value_inum
) {
91 retval
= read_ea_inode_hash(fs
, entry
->e_value_inum
,
96 *hash
= (*hash
<< VALUE_HASH_SHIFT
) ^
97 (*hash
>> (8*sizeof(*hash
) - VALUE_HASH_SHIFT
)) ^
103 static errcode_t
check_ext_attr_header(struct ext2_ext_attr_header
*header
)
105 if ((header
->h_magic
!= EXT2_EXT_ATTR_MAGIC_v1
&&
106 header
->h_magic
!= EXT2_EXT_ATTR_MAGIC
) ||
107 header
->h_blocks
!= 1)
108 return EXT2_ET_BAD_EA_HEADER
;
113 #undef NAME_HASH_SHIFT
114 #undef VALUE_HASH_SHIFT
116 errcode_t
ext2fs_read_ext_attr3(ext2_filsys fs
, blk64_t block
, void *buf
,
122 retval
= io_channel_read_blk64(fs
->io
, block
, 1, buf
);
126 if (!(fs
->flags
& EXT2_FLAG_IGNORE_CSUM_ERRORS
) &&
127 !ext2fs_ext_attr_block_csum_verify(fs
, inum
, block
, buf
))
130 #ifdef WORDS_BIGENDIAN
131 ext2fs_swap_ext_attr(buf
, buf
, fs
->blocksize
, 1);
134 retval
= check_ext_attr_header(buf
);
135 if (retval
== 0 && csum_failed
)
136 retval
= EXT2_ET_EXT_ATTR_CSUM_INVALID
;
141 errcode_t
ext2fs_read_ext_attr2(ext2_filsys fs
, blk64_t block
, void *buf
)
143 return ext2fs_read_ext_attr3(fs
, block
, buf
, 0);
146 errcode_t
ext2fs_read_ext_attr(ext2_filsys fs
, blk_t block
, void *buf
)
148 return ext2fs_read_ext_attr2(fs
, block
, buf
);
151 errcode_t
ext2fs_write_ext_attr3(ext2_filsys fs
, blk64_t block
, void *inbuf
,
157 #ifdef WORDS_BIGENDIAN
158 retval
= ext2fs_get_mem(fs
->blocksize
, &write_buf
);
161 ext2fs_swap_ext_attr(write_buf
, inbuf
, fs
->blocksize
, 1);
163 write_buf
= (char *) inbuf
;
166 retval
= ext2fs_ext_attr_block_csum_set(fs
, inum
, block
,
167 (struct ext2_ext_attr_header
*)write_buf
);
171 retval
= io_channel_write_blk64(fs
->io
, block
, 1, write_buf
);
172 #ifdef WORDS_BIGENDIAN
173 ext2fs_free_mem(&write_buf
);
176 ext2fs_mark_changed(fs
);
180 errcode_t
ext2fs_write_ext_attr2(ext2_filsys fs
, blk64_t block
, void *inbuf
)
182 return ext2fs_write_ext_attr3(fs
, block
, inbuf
, 0);
185 errcode_t
ext2fs_write_ext_attr(ext2_filsys fs
, blk_t block
, void *inbuf
)
187 return ext2fs_write_ext_attr2(fs
, block
, inbuf
);
191 * This function adjusts the reference count of the EA block.
193 errcode_t
ext2fs_adjust_ea_refcount3(ext2_filsys fs
, blk64_t blk
,
194 char *block_buf
, int adjust
,
195 __u32
*newcount
, ext2_ino_t inum
)
198 struct ext2_ext_attr_header
*header
;
201 if ((blk
>= ext2fs_blocks_count(fs
->super
)) ||
202 (blk
< fs
->super
->s_first_data_block
))
203 return EXT2_ET_BAD_EA_BLOCK_NUM
;
206 retval
= ext2fs_get_mem(fs
->blocksize
, &buf
);
212 retval
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, inum
);
216 header
= (struct ext2_ext_attr_header
*) block_buf
;
217 header
->h_refcount
+= adjust
;
219 *newcount
= header
->h_refcount
;
221 retval
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, inum
);
227 ext2fs_free_mem(&buf
);
231 errcode_t
ext2fs_adjust_ea_refcount2(ext2_filsys fs
, blk64_t blk
,
232 char *block_buf
, int adjust
,
235 return ext2fs_adjust_ea_refcount3(fs
, blk
, block_buf
, adjust
,
239 errcode_t
ext2fs_adjust_ea_refcount(ext2_filsys fs
, blk_t blk
,
240 char *block_buf
, int adjust
,
243 return ext2fs_adjust_ea_refcount2(fs
, blk
, block_buf
, adjust
,
247 /* Manipulate the contents of extended attribute regions */
254 struct ext2_xattr_handle
{
257 struct ext2_xattr
*attrs
;
258 size_t length
, count
;
264 static errcode_t
ext2fs_xattrs_expand(struct ext2_xattr_handle
*h
,
265 unsigned int expandby
)
267 struct ext2_xattr
*new_attrs
;
270 err
= ext2fs_get_arrayzero(h
->length
+ expandby
,
271 sizeof(struct ext2_xattr
), &new_attrs
);
275 memcpy(new_attrs
, h
->attrs
, h
->length
* sizeof(struct ext2_xattr
));
276 ext2fs_free_mem(&h
->attrs
);
277 h
->length
+= expandby
;
278 h
->attrs
= new_attrs
;
283 struct ea_name_index
{
288 /* Keep these names sorted in order of decreasing specificity. */
289 static struct ea_name_index ea_names
[] = {
290 {3, "system.posix_acl_default"},
291 {2, "system.posix_acl_access"},
292 {8, "system.richacl"},
300 static int find_ea_index(char *fullname
, char **name
, int *index
);
302 /* Push empty attributes to the end and inlinedata to the front. */
303 static int attr_compare(const void *a
, const void *b
)
305 const struct ext2_xattr
*xa
= a
, *xb
= b
;
306 char *xa_suffix
, *xb_suffix
;
310 if (xa
->name
== NULL
)
312 else if (xb
->name
== NULL
)
314 else if (!strcmp(xa
->name
, "system.data"))
316 else if (!strcmp(xb
->name
, "system.data"))
320 * Duplicate the kernel's sorting algorithm because xattr blocks
321 * require sorted keys.
323 xa_suffix
= xa
->name
;
324 xb_suffix
= xb
->name
;
326 find_ea_index(xa
->name
, &xa_suffix
, &xa_idx
);
327 find_ea_index(xb
->name
, &xb_suffix
, &xb_idx
);
328 cmp
= xa_idx
- xb_idx
;
331 cmp
= strlen(xa_suffix
) - strlen(xb_suffix
);
334 cmp
= strcmp(xa_suffix
, xb_suffix
);
338 static const char *find_ea_prefix(int index
)
340 struct ea_name_index
*e
;
342 for (e
= ea_names
; e
->name
; e
++)
343 if (e
->index
== index
)
349 static int find_ea_index(char *fullname
, char **name
, int *index
)
351 struct ea_name_index
*e
;
353 for (e
= ea_names
; e
->name
; e
++) {
354 if (strncmp(fullname
, e
->name
, strlen(e
->name
)) == 0) {
355 *name
= (char *)fullname
+ strlen(e
->name
);
363 errcode_t
ext2fs_free_ext_attr(ext2_filsys fs
, ext2_ino_t ino
,
364 struct ext2_inode_large
*inode
)
366 struct ext2_ext_attr_header
*header
;
367 void *block_buf
= NULL
;
370 struct ext2_inode_large i
;
374 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&i
,
375 sizeof(struct ext2_inode_large
));
381 /* Do we already have an EA block? */
382 blk
= ext2fs_file_acl_block(fs
, (struct ext2_inode
*)inode
);
386 /* Find block, zero it, write back */
387 if ((blk
< fs
->super
->s_first_data_block
) ||
388 (blk
>= ext2fs_blocks_count(fs
->super
))) {
389 err
= EXT2_ET_BAD_EA_BLOCK_NUM
;
393 err
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
397 err
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, ino
);
401 /* We only know how to deal with v2 EA blocks */
402 header
= (struct ext2_ext_attr_header
*) block_buf
;
403 if (header
->h_magic
!= EXT2_EXT_ATTR_MAGIC
) {
404 err
= EXT2_ET_BAD_EA_HEADER
;
408 header
->h_refcount
--;
409 err
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, ino
);
413 /* Erase link to block */
414 ext2fs_file_acl_block_set(fs
, (struct ext2_inode
*)inode
, 0);
415 if (header
->h_refcount
== 0)
416 ext2fs_block_alloc_stats2(fs
, blk
, -1);
417 err
= ext2fs_iblk_sub_blocks(fs
, (struct ext2_inode
*)inode
, 1);
423 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&i
,
424 sizeof(struct ext2_inode_large
));
430 ext2fs_free_mem(&block_buf
);
435 static errcode_t
prep_ea_block_for_write(ext2_filsys fs
, ext2_ino_t ino
,
436 struct ext2_inode_large
*inode
)
438 struct ext2_ext_attr_header
*header
;
439 void *block_buf
= NULL
;
443 /* Do we already have an EA block? */
444 blk
= ext2fs_file_acl_block(fs
, (struct ext2_inode
*)inode
);
446 if ((blk
< fs
->super
->s_first_data_block
) ||
447 (blk
>= ext2fs_blocks_count(fs
->super
))) {
448 err
= EXT2_ET_BAD_EA_BLOCK_NUM
;
452 err
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
456 err
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, ino
);
460 /* We only know how to deal with v2 EA blocks */
461 header
= (struct ext2_ext_attr_header
*) block_buf
;
462 if (header
->h_magic
!= EXT2_EXT_ATTR_MAGIC
) {
463 err
= EXT2_ET_BAD_EA_HEADER
;
467 /* Single-user block. We're done here. */
468 if (header
->h_refcount
== 1)
471 /* We need to CoW the block. */
472 header
->h_refcount
--;
473 err
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, ino
);
477 /* No block, we must increment i_blocks */
478 err
= ext2fs_iblk_add_blocks(fs
, (struct ext2_inode
*)inode
,
484 /* Allocate a block */
485 goal
= ext2fs_find_inode_goal(fs
, ino
, (struct ext2_inode
*)inode
, 0);
486 err
= ext2fs_alloc_block2(fs
, goal
, NULL
, &blk
);
489 ext2fs_file_acl_block_set(fs
, (struct ext2_inode
*)inode
, blk
);
492 ext2fs_free_mem(&block_buf
);
499 posix_acl_xattr_count(size_t size
)
501 if (size
< sizeof(posix_acl_xattr_header
))
503 size
-= sizeof(posix_acl_xattr_header
);
504 if (size
% sizeof(posix_acl_xattr_entry
))
506 return size
/ sizeof(posix_acl_xattr_entry
);
510 * The lgetxattr function returns data formatted in the POSIX extended
511 * attribute format. The on-disk format uses a more compact encoding.
512 * See the ext4_acl_to_disk in fs/ext4/acl.c.
514 static errcode_t
convert_posix_acl_to_disk_buffer(const void *value
, size_t size
,
515 void *out_buf
, size_t *size_out
)
517 posix_acl_xattr_header
*header
= (posix_acl_xattr_header
*) value
;
518 posix_acl_xattr_entry
*entry
= (posix_acl_xattr_entry
*)(header
+1), *end
;
519 ext4_acl_header
*ext_acl
;
527 if (size
< sizeof(posix_acl_xattr_header
))
529 if (header
->a_version
!= ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION
))
532 count
= posix_acl_xattr_count(size
);
534 ext_acl
->a_version
= ext2fs_cpu_to_le32(EXT4_ACL_VERSION
);
539 e
= (char *) out_buf
+ sizeof(ext4_acl_header
);
540 s
= sizeof(ext4_acl_header
);
541 for (end
= entry
+ count
; entry
!= end
;entry
++) {
542 ext4_acl_entry
*disk_entry
= (ext4_acl_entry
*) e
;
543 disk_entry
->e_tag
= ext2fs_cpu_to_le16(entry
->e_tag
);
544 disk_entry
->e_perm
= ext2fs_cpu_to_le16(entry
->e_perm
);
546 switch(entry
->e_tag
) {
551 e
+= sizeof(ext4_acl_entry_short
);
552 s
+= sizeof(ext4_acl_entry_short
);
556 disk_entry
->e_id
= ext2fs_cpu_to_le32(entry
->e_id
);
557 e
+= sizeof(ext4_acl_entry
);
558 s
+= sizeof(ext4_acl_entry
);
566 static errcode_t
convert_disk_buffer_to_posix_acl(const void *value
, size_t size
,
567 void **out_buf
, size_t *size_out
)
569 posix_acl_xattr_header
*header
;
570 posix_acl_xattr_entry
*entry
;
571 ext4_acl_header
*ext_acl
= (ext4_acl_header
*) value
;
577 (size
< sizeof(ext4_acl_header
)) ||
578 (ext_acl
->a_version
!= ext2fs_cpu_to_le32(EXT4_ACL_VERSION
)))
581 err
= ext2fs_get_mem(size
* 2, &out
);
585 header
= (posix_acl_xattr_header
*) out
;
586 header
->a_version
= ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION
);
587 entry
= (posix_acl_xattr_entry
*) (out
+ sizeof(posix_acl_xattr_header
));
589 cp
= value
+ sizeof(ext4_acl_header
);
590 size
-= sizeof(ext4_acl_header
);
593 const ext4_acl_entry
*disk_entry
= (const ext4_acl_entry
*) cp
;
595 entry
->e_tag
= ext2fs_le16_to_cpu(disk_entry
->e_tag
);
596 entry
->e_perm
= ext2fs_le16_to_cpu(disk_entry
->e_perm
);
598 switch(entry
->e_tag
) {
604 cp
+= sizeof(ext4_acl_entry_short
);
605 size
-= sizeof(ext4_acl_entry_short
);
609 entry
->e_id
= ext2fs_le32_to_cpu(disk_entry
->e_id
);
610 cp
+= sizeof(ext4_acl_entry
);
611 size
-= sizeof(ext4_acl_entry
);
614 ext2fs_free_mem(&out
);
621 *size_out
= ((char *) entry
- out
);
626 static errcode_t
write_xattrs_to_buffer(struct ext2_xattr_handle
*handle
,
627 struct ext2_xattr
**pos
,
629 unsigned int storage_size
,
630 unsigned int value_offset_correction
,
633 struct ext2_xattr
*x
= *pos
;
634 struct ext2_ext_attr_entry
*e
= entries_start
;
635 char *end
= (char *) entries_start
+ storage_size
;
637 unsigned int entry_size
, value_size
;
640 memset(entries_start
, 0, storage_size
);
641 /* For all remaining x... */
642 for (; x
< handle
->attrs
+ handle
->length
; x
++) {
646 /* Calculate index and shortname position */
648 ret
= find_ea_index(x
->name
, &shortname
, &idx
);
650 /* Calculate entry and value size */
651 entry_size
= (sizeof(*e
) + strlen(shortname
) +
652 EXT2_EXT_ATTR_PAD
- 1) &
653 ~(EXT2_EXT_ATTR_PAD
- 1);
654 value_size
= ((x
->value_len
+ EXT2_EXT_ATTR_PAD
- 1) /
655 EXT2_EXT_ATTR_PAD
) * EXT2_EXT_ATTR_PAD
;
658 * Would entry collide with value?
659 * Note that we must leave sufficient room for a (u32)0 to
660 * mark the end of the entries.
662 if ((char *)e
+ entry_size
+ sizeof(__u32
) > end
- value_size
)
665 /* Fill out e appropriately */
666 e
->e_name_len
= strlen(shortname
);
667 e
->e_name_index
= (ret
? idx
: 0);
668 e
->e_value_offs
= end
- value_size
- (char *)entries_start
+
669 value_offset_correction
;
671 e
->e_value_size
= x
->value_len
;
673 /* Store name and value */
675 memcpy((char *)e
+ sizeof(*e
), shortname
, e
->e_name_len
);
676 memcpy(end
, x
->value
, e
->e_value_size
);
679 e
->e_hash
= ext2fs_ext_attr_hash_entry(e
, end
);
683 e
= EXT2_EXT_ATTR_NEXT(e
);
691 errcode_t
ext2fs_xattrs_write(struct ext2_xattr_handle
*handle
)
693 struct ext2_xattr
*x
;
694 struct ext2_inode_large
*inode
;
695 char *start
, *block_buf
= NULL
;
696 struct ext2_ext_attr_header
*header
;
697 __u32 ea_inode_magic
;
699 unsigned int storage_size
;
703 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
704 i
= EXT2_INODE_SIZE(handle
->fs
->super
);
705 if (i
< sizeof(*inode
))
707 err
= ext2fs_get_memzero(i
, &inode
);
711 err
= ext2fs_read_inode_full(handle
->fs
, handle
->ino
,
712 (struct ext2_inode
*)inode
,
713 EXT2_INODE_SIZE(handle
->fs
->super
));
717 /* If extra_isize isn't set, we need to set it now */
718 if (inode
->i_extra_isize
== 0 &&
719 EXT2_INODE_SIZE(handle
->fs
->super
) > EXT2_GOOD_OLD_INODE_SIZE
) {
720 char *p
= (char *)inode
;
721 size_t extra
= handle
->fs
->super
->s_want_extra_isize
;
724 extra
= sizeof(__u32
);
725 memset(p
+ EXT2_GOOD_OLD_INODE_SIZE
, 0, extra
);
726 inode
->i_extra_isize
= extra
;
728 if (inode
->i_extra_isize
& 3) {
729 err
= EXT2_ET_INODE_CORRUPTED
;
734 * Force the inlinedata attr to the front and the empty entries
738 qsort(x
, handle
->length
, sizeof(struct ext2_xattr
), attr_compare
);
740 /* Does the inode have space for EA? */
741 if (inode
->i_extra_isize
< sizeof(inode
->i_extra_isize
) ||
742 EXT2_INODE_SIZE(handle
->fs
->super
) <= EXT2_GOOD_OLD_INODE_SIZE
+
743 inode
->i_extra_isize
+
747 /* Write the inode EA */
748 ea_inode_magic
= EXT2_EXT_ATTR_MAGIC
;
749 memcpy(((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
750 inode
->i_extra_isize
, &ea_inode_magic
, sizeof(__u32
));
751 storage_size
= EXT2_INODE_SIZE(handle
->fs
->super
) -
752 EXT2_GOOD_OLD_INODE_SIZE
- inode
->i_extra_isize
-
754 start
= ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
755 inode
->i_extra_isize
+ sizeof(__u32
);
757 err
= write_xattrs_to_buffer(handle
, &x
, start
, storage_size
, 0, 0);
763 if (x
>= handle
->attrs
+ handle
->count
)
766 /* Write the EA block */
767 err
= ext2fs_get_memzero(handle
->fs
->blocksize
, &block_buf
);
771 storage_size
= handle
->fs
->blocksize
-
772 sizeof(struct ext2_ext_attr_header
);
773 start
= block_buf
+ sizeof(struct ext2_ext_attr_header
);
775 err
= write_xattrs_to_buffer(handle
, &x
, start
, storage_size
,
776 start
- block_buf
, 1);
780 if (x
< handle
->attrs
+ handle
->length
) {
781 err
= EXT2_ET_EA_NO_SPACE
;
785 /* Write a header on the EA block */
786 header
= (struct ext2_ext_attr_header
*) block_buf
;
787 header
->h_magic
= EXT2_EXT_ATTR_MAGIC
;
788 header
->h_refcount
= 1;
789 header
->h_blocks
= 1;
791 /* Get a new block for writing */
792 err
= prep_ea_block_for_write(handle
->fs
, handle
->ino
, inode
);
796 /* Finally, write the new EA block */
797 blk
= ext2fs_file_acl_block(handle
->fs
,
798 (struct ext2_inode
*)inode
);
799 err
= ext2fs_write_ext_attr3(handle
->fs
, blk
, block_buf
,
805 blk
= ext2fs_file_acl_block(handle
->fs
, (struct ext2_inode
*)inode
);
806 if (!block_buf
&& blk
) {
807 /* xattrs shrunk, free the block */
808 err
= ext2fs_free_ext_attr(handle
->fs
, handle
->ino
, inode
);
813 /* Write the inode */
814 err
= ext2fs_write_inode_full(handle
->fs
, handle
->ino
,
815 (struct ext2_inode
*)inode
,
816 EXT2_INODE_SIZE(handle
->fs
->super
));
821 ext2fs_free_mem(&block_buf
);
823 ext2fs_free_mem(&inode
);
828 static errcode_t
read_xattrs_from_buffer(struct ext2_xattr_handle
*handle
,
829 struct ext2_inode_large
*inode
,
830 struct ext2_ext_attr_entry
*entries
,
831 unsigned int storage_size
,
835 struct ext2_xattr
*x
;
836 struct ext2_ext_attr_entry
*entry
, *end
;
838 unsigned int remain
, prefix_len
;
840 unsigned int values_size
= storage_size
+
841 ((char *)entries
- value_start
);
849 remain
= storage_size
;
850 while (remain
>= sizeof(struct ext2_ext_attr_entry
) &&
851 !EXT2_EXT_IS_LAST_ENTRY(end
)) {
853 /* header eats this space */
854 remain
-= sizeof(struct ext2_ext_attr_entry
);
856 /* is attribute name valid? */
857 if (EXT2_EXT_ATTR_SIZE(end
->e_name_len
) > remain
)
858 return EXT2_ET_EA_BAD_NAME_LEN
;
860 /* attribute len eats this space */
861 remain
-= EXT2_EXT_ATTR_SIZE(end
->e_name_len
);
862 end
= EXT2_EXT_ATTR_NEXT(end
);
866 remain
= storage_size
;
867 while (remain
>= sizeof(struct ext2_ext_attr_entry
) &&
868 !EXT2_EXT_IS_LAST_ENTRY(entry
)) {
870 /* Allocate space for more attrs? */
871 if (x
== handle
->attrs
+ handle
->length
) {
872 err
= ext2fs_xattrs_expand(handle
, 4);
875 x
= handle
->attrs
+ handle
->length
- 4;
878 /* header eats this space */
879 remain
-= sizeof(struct ext2_ext_attr_entry
);
881 /* attribute len eats this space */
882 remain
-= EXT2_EXT_ATTR_SIZE(entry
->e_name_len
);
885 prefix
= find_ea_prefix(entry
->e_name_index
);
886 prefix_len
= (prefix
? strlen(prefix
) : 0);
887 err
= ext2fs_get_memzero(entry
->e_name_len
+ prefix_len
+ 1,
892 memcpy(x
->name
, prefix
, prefix_len
);
893 if (entry
->e_name_len
)
894 memcpy(x
->name
+ prefix_len
,
895 (char *)entry
+ sizeof(*entry
),
898 /* Check & copy value */
899 if (!ext2fs_has_feature_ea_inode(handle
->fs
->super
) &&
900 entry
->e_value_inum
!= 0)
901 return EXT2_ET_BAD_EA_BLOCK_NUM
;
903 if (entry
->e_value_inum
== 0) {
904 if (entry
->e_value_size
> remain
)
905 return EXT2_ET_EA_BAD_VALUE_SIZE
;
907 if (entry
->e_value_offs
+ entry
->e_value_size
> values_size
)
908 return EXT2_ET_EA_BAD_VALUE_OFFSET
;
910 if (entry
->e_value_size
> 0 &&
911 value_start
+ entry
->e_value_offs
<
912 (char *)end
+ sizeof(__u32
))
913 return EXT2_ET_EA_BAD_VALUE_OFFSET
;
915 remain
-= entry
->e_value_size
;
917 err
= ext2fs_get_mem(entry
->e_value_size
, &x
->value
);
920 memcpy(x
->value
, value_start
+ entry
->e_value_offs
,
921 entry
->e_value_size
);
925 if (entry
->e_value_offs
!= 0)
926 return EXT2_ET_EA_BAD_VALUE_OFFSET
;
928 if (entry
->e_value_size
> (64 * 1024))
929 return EXT2_ET_EA_BAD_VALUE_SIZE
;
931 err
= ext2fs_get_mem(entry
->e_value_size
, &x
->value
);
935 err
= ext2fs_file_open(handle
->fs
, entry
->e_value_inum
,
940 if (ext2fs_file_get_size(ea_file
) !=
942 err
= EXT2_ET_EA_BAD_VALUE_SIZE
;
944 err
= ext2fs_file_read(ea_file
, x
->value
,
945 entry
->e_value_size
, 0);
946 ext2fs_file_close(ea_file
);
951 x
->value_len
= entry
->e_value_size
;
953 /* e_hash may be 0 in older inode's ea */
954 if (entry
->e_hash
!= 0) {
956 void *data
= (entry
->e_value_inum
!= 0) ?
957 0 : value_start
+ entry
->e_value_offs
;
959 err
= ext2fs_ext_attr_hash_entry2(handle
->fs
, entry
,
963 if (entry
->e_hash
!= hash
) {
964 struct ext2_inode child
;
966 /* Check whether this is an old Lustre-style
967 * ea_inode reference.
969 err
= ext2fs_read_inode(handle
->fs
,
974 if (child
.i_mtime
!= handle
->ino
||
975 child
.i_generation
!= inode
->i_generation
)
976 return EXT2_ET_BAD_EA_HASH
;
982 entry
= EXT2_EXT_ATTR_NEXT(entry
);
988 static void xattrs_free_keys(struct ext2_xattr_handle
*h
)
990 struct ext2_xattr
*a
= h
->attrs
;
993 for (i
= 0; i
< h
->length
; i
++) {
995 ext2fs_free_mem(&a
[i
].name
);
997 ext2fs_free_mem(&a
[i
].value
);
1002 errcode_t
ext2fs_xattrs_read(struct ext2_xattr_handle
*handle
)
1004 struct ext2_inode_large
*inode
;
1005 struct ext2_ext_attr_header
*header
;
1006 __u32 ea_inode_magic
;
1007 unsigned int storage_size
;
1008 char *start
, *block_buf
= NULL
;
1013 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1014 i
= EXT2_INODE_SIZE(handle
->fs
->super
);
1015 if (i
< sizeof(*inode
))
1017 err
= ext2fs_get_memzero(i
, &inode
);
1021 err
= ext2fs_read_inode_full(handle
->fs
, handle
->ino
,
1022 (struct ext2_inode
*)inode
,
1023 EXT2_INODE_SIZE(handle
->fs
->super
));
1027 xattrs_free_keys(handle
);
1029 /* Does the inode have space for EA? */
1030 if (inode
->i_extra_isize
< sizeof(inode
->i_extra_isize
) ||
1031 EXT2_INODE_SIZE(handle
->fs
->super
) <= EXT2_GOOD_OLD_INODE_SIZE
+
1032 inode
->i_extra_isize
+
1035 if (inode
->i_extra_isize
& 3) {
1036 err
= EXT2_ET_INODE_CORRUPTED
;
1040 /* Look for EA in the inode */
1041 memcpy(&ea_inode_magic
, ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
1042 inode
->i_extra_isize
, sizeof(__u32
));
1043 if (ea_inode_magic
== EXT2_EXT_ATTR_MAGIC
) {
1044 storage_size
= EXT2_INODE_SIZE(handle
->fs
->super
) -
1045 EXT2_GOOD_OLD_INODE_SIZE
- inode
->i_extra_isize
-
1047 start
= ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
1048 inode
->i_extra_isize
+ sizeof(__u32
);
1050 err
= read_xattrs_from_buffer(handle
, inode
,
1051 (struct ext2_ext_attr_entry
*) start
, storage_size
,
1052 start
, &handle
->count
);
1058 /* Look for EA in a separate EA block */
1059 blk
= ext2fs_file_acl_block(handle
->fs
, (struct ext2_inode
*)inode
);
1061 if ((blk
< handle
->fs
->super
->s_first_data_block
) ||
1062 (blk
>= ext2fs_blocks_count(handle
->fs
->super
))) {
1063 err
= EXT2_ET_BAD_EA_BLOCK_NUM
;
1067 err
= ext2fs_get_mem(handle
->fs
->blocksize
, &block_buf
);
1071 err
= ext2fs_read_ext_attr3(handle
->fs
, blk
, block_buf
,
1076 /* We only know how to deal with v2 EA blocks */
1077 header
= (struct ext2_ext_attr_header
*) block_buf
;
1078 if (header
->h_magic
!= EXT2_EXT_ATTR_MAGIC
) {
1079 err
= EXT2_ET_BAD_EA_HEADER
;
1084 storage_size
= handle
->fs
->blocksize
-
1085 sizeof(struct ext2_ext_attr_header
);
1086 start
= block_buf
+ sizeof(struct ext2_ext_attr_header
);
1087 err
= read_xattrs_from_buffer(handle
, inode
,
1088 (struct ext2_ext_attr_entry
*) start
, storage_size
,
1089 block_buf
, &handle
->count
);
1093 ext2fs_free_mem(&block_buf
);
1096 ext2fs_free_mem(&block_buf
);
1097 ext2fs_free_mem(&inode
);
1101 ext2fs_free_mem(&block_buf
);
1103 ext2fs_free_mem(&inode
);
1107 errcode_t
ext2fs_xattrs_iterate(struct ext2_xattr_handle
*h
,
1108 int (*func
)(char *name
, char *value
,
1109 size_t value_len
, void *data
),
1112 struct ext2_xattr
*x
;
1115 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
1116 for (x
= h
->attrs
; x
< h
->attrs
+ h
->length
; x
++) {
1120 ret
= func(x
->name
, x
->value
, x
->value_len
, data
);
1121 if (ret
& XATTR_CHANGED
)
1123 if (ret
& XATTR_ABORT
)
1130 errcode_t
ext2fs_xattr_get(struct ext2_xattr_handle
*h
, const char *key
,
1131 void **value
, size_t *value_len
)
1133 struct ext2_xattr
*x
;
1137 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
1138 for (x
= h
->attrs
; x
< h
->attrs
+ h
->length
; x
++) {
1139 if (!x
->name
|| strcmp(x
->name
, key
))
1142 if (!(h
->flags
& XATTR_HANDLE_FLAG_RAW
) &&
1143 ((strcmp(key
, "system.posix_acl_default") == 0) ||
1144 (strcmp(key
, "system.posix_acl_access") == 0))) {
1145 err
= convert_disk_buffer_to_posix_acl(x
->value
, x
->value_len
,
1149 err
= ext2fs_get_mem(x
->value_len
, &val
);
1152 memcpy(val
, x
->value
, x
->value_len
);
1154 *value_len
= x
->value_len
;
1159 return EXT2_ET_EA_KEY_NOT_FOUND
;
1162 errcode_t
ext2fs_xattr_inode_max_size(ext2_filsys fs
, ext2_ino_t ino
,
1165 struct ext2_ext_attr_entry
*entry
;
1166 struct ext2_inode_large
*inode
;
1167 __u32 ea_inode_magic
;
1168 unsigned int minoff
;
1173 i
= EXT2_INODE_SIZE(fs
->super
);
1174 if (i
< sizeof(*inode
))
1176 err
= ext2fs_get_memzero(i
, &inode
);
1180 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)inode
,
1181 EXT2_INODE_SIZE(fs
->super
));
1185 /* Does the inode have size for EA? */
1186 if (EXT2_INODE_SIZE(fs
->super
) <= EXT2_GOOD_OLD_INODE_SIZE
+
1187 inode
->i_extra_isize
+
1189 err
= EXT2_ET_INLINE_DATA_NO_SPACE
;
1193 minoff
= EXT2_INODE_SIZE(fs
->super
) - sizeof(*inode
) - sizeof(__u32
);
1194 memcpy(&ea_inode_magic
, ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
1195 inode
->i_extra_isize
, sizeof(__u32
));
1196 if (ea_inode_magic
== EXT2_EXT_ATTR_MAGIC
) {
1197 /* has xattrs. calculate the size */
1198 start
= ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
1199 inode
->i_extra_isize
+ sizeof(__u32
);
1200 entry
= (struct ext2_ext_attr_entry
*) start
;
1201 while (!EXT2_EXT_IS_LAST_ENTRY(entry
)) {
1202 if (!entry
->e_value_inum
&& entry
->e_value_size
) {
1203 unsigned int offs
= entry
->e_value_offs
;
1207 entry
= EXT2_EXT_ATTR_NEXT(entry
);
1209 *size
= minoff
- ((char *)entry
- (char *)start
) - sizeof(__u32
);
1211 /* no xattr. return a maximum size */
1212 *size
= EXT2_EXT_ATTR_SIZE(minoff
-
1213 EXT2_EXT_ATTR_LEN(strlen("data")) -
1214 EXT2_EXT_ATTR_ROUND
- sizeof(__u32
));
1218 ext2fs_free_mem(&inode
);
1222 errcode_t
ext2fs_xattr_set(struct ext2_xattr_handle
*handle
,
1227 struct ext2_xattr
*x
, *last_empty
;
1231 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1234 err
= ext2fs_get_mem(value_len
, &new_value
);
1237 if (!(handle
->flags
& XATTR_HANDLE_FLAG_RAW
) &&
1238 ((strcmp(key
, "system.posix_acl_default") == 0) ||
1239 (strcmp(key
, "system.posix_acl_access") == 0))) {
1240 err
= convert_posix_acl_to_disk_buffer(value
, value_len
,
1241 new_value
, &value_len
);
1245 memcpy(new_value
, value
, value_len
);
1247 for (x
= handle
->attrs
; x
< handle
->attrs
+ handle
->length
; x
++) {
1254 if (strcmp(x
->name
, key
) == 0) {
1255 ext2fs_free_mem(&x
->value
);
1256 x
->value
= new_value
;
1257 x
->value_len
= value_len
;
1263 /* Add attr to empty slot */
1265 err
= ext2fs_get_mem(strlen(key
) + 1, &last_empty
->name
);
1268 strcpy(last_empty
->name
, key
);
1269 last_empty
->value
= new_value
;
1270 last_empty
->value_len
= value_len
;
1276 /* Expand array, append slot */
1277 err
= ext2fs_xattrs_expand(handle
, 4);
1281 x
= handle
->attrs
+ handle
->length
- 4;
1282 err
= ext2fs_get_mem(strlen(key
) + 1, &x
->name
);
1285 strcpy(x
->name
, key
);
1287 err
= ext2fs_get_mem(value_len
, &x
->value
);
1290 memcpy(x
->value
, value
, value_len
);
1291 x
->value_len
= value_len
;
1296 ext2fs_free_mem(&new_value
);
1300 errcode_t
ext2fs_xattr_remove(struct ext2_xattr_handle
*handle
,
1303 struct ext2_xattr
*x
;
1305 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1306 for (x
= handle
->attrs
; x
< handle
->attrs
+ handle
->length
; x
++) {
1310 if (strcmp(x
->name
, key
) == 0) {
1311 ext2fs_free_mem(&x
->name
);
1312 ext2fs_free_mem(&x
->value
);
1320 /* no key found, success! */
1324 errcode_t
ext2fs_xattrs_open(ext2_filsys fs
, ext2_ino_t ino
,
1325 struct ext2_xattr_handle
**handle
)
1327 struct ext2_xattr_handle
*h
;
1330 if (!ext2fs_has_feature_xattr(fs
->super
) &&
1331 !ext2fs_has_feature_inline_data(fs
->super
))
1332 return EXT2_ET_MISSING_EA_FEATURE
;
1334 err
= ext2fs_get_memzero(sizeof(*h
), &h
);
1338 h
->magic
= EXT2_ET_MAGIC_EA_HANDLE
;
1340 err
= ext2fs_get_arrayzero(h
->length
, sizeof(struct ext2_xattr
),
1343 ext2fs_free_mem(&h
);
1353 errcode_t
ext2fs_xattrs_close(struct ext2_xattr_handle
**handle
)
1355 struct ext2_xattr_handle
*h
= *handle
;
1358 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
1360 err
= ext2fs_xattrs_write(h
);
1365 xattrs_free_keys(h
);
1366 ext2fs_free_mem(&h
->attrs
);
1367 ext2fs_free_mem(handle
);
1371 errcode_t
ext2fs_xattrs_count(struct ext2_xattr_handle
*handle
, size_t *count
)
1373 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1374 *count
= handle
->count
;
1378 errcode_t
ext2fs_xattrs_flags(struct ext2_xattr_handle
*handle
,
1379 unsigned int *new_flags
, unsigned int *old_flags
)
1381 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1383 *old_flags
= handle
->flags
;
1385 handle
->flags
= *new_flags
;