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
= ext2fs_get_ea_inode_hash(&inode
);
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 #undef NAME_HASH_SHIFT
104 #undef VALUE_HASH_SHIFT
106 #define BLOCK_HASH_SHIFT 16
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
)
112 struct ext2_ext_attr_entry
*here
;
115 here
= (struct ext2_ext_attr_entry
*)(header
+1);
116 while (here
< end
&& !EXT2_EXT_IS_LAST_ENTRY(here
)) {
118 /* Block is not shared if an entry's hash value == 0 */
122 hash
= (hash
<< BLOCK_HASH_SHIFT
) ^
123 (hash
>> (8*sizeof(hash
) - BLOCK_HASH_SHIFT
)) ^
125 here
= EXT2_EXT_ATTR_NEXT(here
);
127 header
->h_hash
= hash
;
130 #undef BLOCK_HASH_SHIFT
132 __u32
ext2fs_get_ea_inode_hash(struct ext2_inode
*inode
)
134 return inode
->i_atime
;
137 void ext2fs_set_ea_inode_hash(struct ext2_inode
*inode
, __u32 hash
)
139 inode
->i_atime
= hash
;
142 __u64
ext2fs_get_ea_inode_ref(struct ext2_inode
*inode
)
144 return ((__u64
)inode
->i_ctime
<< 32) | inode
->osd1
.linux1
.l_i_version
;
147 void ext2fs_set_ea_inode_ref(struct ext2_inode
*inode
, __u64 ref_count
)
149 inode
->i_ctime
= (__u32
)(ref_count
>> 32);
150 inode
->osd1
.linux1
.l_i_version
= (__u32
)ref_count
;
153 static errcode_t
check_ext_attr_header(struct ext2_ext_attr_header
*header
)
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
;
163 errcode_t
ext2fs_read_ext_attr3(ext2_filsys fs
, blk64_t block
, void *buf
,
169 retval
= io_channel_read_blk64(fs
->io
, block
, 1, buf
);
173 if (!(fs
->flags
& EXT2_FLAG_IGNORE_CSUM_ERRORS
) &&
174 !ext2fs_ext_attr_block_csum_verify(fs
, inum
, block
, buf
))
177 #ifdef WORDS_BIGENDIAN
178 ext2fs_swap_ext_attr(buf
, buf
, fs
->blocksize
, 1);
181 retval
= check_ext_attr_header(buf
);
182 if (retval
== 0 && csum_failed
)
183 retval
= EXT2_ET_EXT_ATTR_CSUM_INVALID
;
188 errcode_t
ext2fs_read_ext_attr2(ext2_filsys fs
, blk64_t block
, void *buf
)
190 return ext2fs_read_ext_attr3(fs
, block
, buf
, 0);
193 errcode_t
ext2fs_read_ext_attr(ext2_filsys fs
, blk_t block
, void *buf
)
195 return ext2fs_read_ext_attr2(fs
, block
, buf
);
198 errcode_t
ext2fs_write_ext_attr3(ext2_filsys fs
, blk64_t block
, void *inbuf
,
204 #ifdef WORDS_BIGENDIAN
205 retval
= ext2fs_get_mem(fs
->blocksize
, &write_buf
);
208 ext2fs_swap_ext_attr(write_buf
, inbuf
, fs
->blocksize
, 1);
210 write_buf
= (char *) inbuf
;
213 retval
= ext2fs_ext_attr_block_csum_set(fs
, inum
, block
,
214 (struct ext2_ext_attr_header
*)write_buf
);
218 retval
= io_channel_write_blk64(fs
->io
, block
, 1, write_buf
);
219 #ifdef WORDS_BIGENDIAN
220 ext2fs_free_mem(&write_buf
);
223 ext2fs_mark_changed(fs
);
227 errcode_t
ext2fs_write_ext_attr2(ext2_filsys fs
, blk64_t block
, void *inbuf
)
229 return ext2fs_write_ext_attr3(fs
, block
, inbuf
, 0);
232 errcode_t
ext2fs_write_ext_attr(ext2_filsys fs
, blk_t block
, void *inbuf
)
234 return ext2fs_write_ext_attr2(fs
, block
, inbuf
);
238 * This function adjusts the reference count of the EA block.
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
)
245 struct ext2_ext_attr_header
*header
;
248 if ((blk
>= ext2fs_blocks_count(fs
->super
)) ||
249 (blk
< fs
->super
->s_first_data_block
))
250 return EXT2_ET_BAD_EA_BLOCK_NUM
;
253 retval
= ext2fs_get_mem(fs
->blocksize
, &buf
);
259 retval
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, inum
);
263 header
= (struct ext2_ext_attr_header
*) block_buf
;
264 header
->h_refcount
+= adjust
;
266 *newcount
= header
->h_refcount
;
268 retval
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, inum
);
274 ext2fs_free_mem(&buf
);
278 errcode_t
ext2fs_adjust_ea_refcount2(ext2_filsys fs
, blk64_t blk
,
279 char *block_buf
, int adjust
,
282 return ext2fs_adjust_ea_refcount3(fs
, blk
, block_buf
, adjust
,
286 errcode_t
ext2fs_adjust_ea_refcount(ext2_filsys fs
, blk_t blk
,
287 char *block_buf
, int adjust
,
290 return ext2fs_adjust_ea_refcount2(fs
, blk
, block_buf
, adjust
,
294 /* Manipulate the contents of extended attribute regions */
298 unsigned int value_len
;
302 struct ext2_xattr_handle
{
305 struct ext2_xattr
*attrs
;
313 static errcode_t
ext2fs_xattrs_expand(struct ext2_xattr_handle
*h
,
314 unsigned int expandby
)
316 struct ext2_xattr
*new_attrs
;
319 err
= ext2fs_get_arrayzero(h
->capacity
+ expandby
,
320 sizeof(struct ext2_xattr
), &new_attrs
);
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
;
332 struct ea_name_index
{
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"},
349 static const char *find_ea_prefix(int index
)
351 struct ea_name_index
*e
;
353 for (e
= ea_names
; e
->name
; e
++)
354 if (e
->index
== index
)
360 static int find_ea_index(const char *fullname
, const char **name
, int *index
)
362 struct ea_name_index
*e
;
364 for (e
= ea_names
; e
->name
; e
++) {
365 if (strncmp(fullname
, e
->name
, strlen(e
->name
)) == 0) {
366 *name
= fullname
+ strlen(e
->name
);
374 errcode_t
ext2fs_free_ext_attr(ext2_filsys fs
, ext2_ino_t ino
,
375 struct ext2_inode_large
*inode
)
377 struct ext2_ext_attr_header
*header
;
378 void *block_buf
= NULL
;
381 struct ext2_inode_large i
;
385 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&i
,
386 sizeof(struct ext2_inode_large
));
392 /* Do we already have an EA block? */
393 blk
= ext2fs_file_acl_block(fs
, (struct ext2_inode
*)inode
);
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
;
404 err
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
408 err
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, ino
);
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
;
419 header
->h_refcount
--;
420 err
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, ino
);
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);
434 err
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&i
,
435 sizeof(struct ext2_inode_large
));
441 ext2fs_free_mem(&block_buf
);
446 static errcode_t
prep_ea_block_for_write(ext2_filsys fs
, ext2_ino_t ino
,
447 struct ext2_inode_large
*inode
)
449 struct ext2_ext_attr_header
*header
;
450 void *block_buf
= NULL
;
454 /* Do we already have an EA block? */
455 blk
= ext2fs_file_acl_block(fs
, (struct ext2_inode
*)inode
);
457 if ((blk
< fs
->super
->s_first_data_block
) ||
458 (blk
>= ext2fs_blocks_count(fs
->super
))) {
459 err
= EXT2_ET_BAD_EA_BLOCK_NUM
;
463 err
= ext2fs_get_mem(fs
->blocksize
, &block_buf
);
467 err
= ext2fs_read_ext_attr3(fs
, blk
, block_buf
, ino
);
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
;
478 /* Single-user block. We're done here. */
479 if (header
->h_refcount
== 1)
482 /* We need to CoW the block. */
483 header
->h_refcount
--;
484 err
= ext2fs_write_ext_attr3(fs
, blk
, block_buf
, ino
);
488 /* No block, we must increment i_blocks */
489 err
= ext2fs_iblk_add_blocks(fs
, (struct ext2_inode
*)inode
,
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
);
500 ext2fs_file_acl_block_set(fs
, (struct ext2_inode
*)inode
, blk
);
503 ext2fs_free_mem(&block_buf
);
510 posix_acl_xattr_count(size_t size
)
512 if (size
< sizeof(posix_acl_xattr_header
))
514 size
-= sizeof(posix_acl_xattr_header
);
515 if (size
% sizeof(posix_acl_xattr_entry
))
517 return size
/ sizeof(posix_acl_xattr_entry
);
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.
525 static errcode_t
convert_posix_acl_to_disk_buffer(const void *value
, size_t size
,
526 void *out_buf
, size_t *size_out
)
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
;
540 if (size
< sizeof(posix_acl_xattr_header
))
542 if (header
->a_version
!= ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION
))
545 count
= posix_acl_xattr_count(size
);
547 ext_acl
->a_version
= ext2fs_cpu_to_le32(EXT4_ACL_VERSION
);
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
);
559 switch(entry
->e_tag
) {
564 e
+= sizeof(ext4_acl_entry_short
);
565 s
+= sizeof(ext4_acl_entry_short
);
569 disk_entry
->e_id
= ext2fs_cpu_to_le32(entry
->e_id
);
570 e
+= sizeof(ext4_acl_entry
);
571 s
+= sizeof(ext4_acl_entry
);
579 static errcode_t
convert_disk_buffer_to_posix_acl(const void *value
, size_t size
,
580 void **out_buf
, size_t *size_out
)
582 posix_acl_xattr_header
*header
;
583 posix_acl_xattr_entry
*entry
;
584 const ext4_acl_header
*ext_acl
= (const ext4_acl_header
*) value
;
590 (size
< sizeof(ext4_acl_header
)) ||
591 (ext_acl
->a_version
!= ext2fs_cpu_to_le32(EXT4_ACL_VERSION
)))
594 err
= ext2fs_get_mem(size
* 2, &out
);
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
));
602 cp
= (const char *) value
+ sizeof(ext4_acl_header
);
603 size
-= sizeof(ext4_acl_header
);
606 const ext4_acl_entry
*disk_entry
= (const ext4_acl_entry
*) cp
;
608 entry
->e_tag
= ext2fs_le16_to_cpu(disk_entry
->e_tag
);
609 entry
->e_perm
= ext2fs_le16_to_cpu(disk_entry
->e_perm
);
611 switch(entry
->e_tag
) {
617 cp
+= sizeof(ext4_acl_entry_short
);
618 size
-= sizeof(ext4_acl_entry_short
);
622 entry
->e_id
= ext2fs_le32_to_cpu(disk_entry
->e_id
);
623 cp
+= sizeof(ext4_acl_entry
);
624 size
-= sizeof(ext4_acl_entry
);
627 ext2fs_free_mem(&out
);
634 *size_out
= ((char *) entry
- out
);
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
)
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
;
651 memset(entries_start
, 0, storage_size
);
652 for (x
= attrs
; x
< attrs
+ count
; x
++) {
653 /* Calculate index and shortname position */
655 ret
= find_ea_index(x
->name
, &shortname
, &idx
);
657 value_size
= ((x
->value_len
+ EXT2_EXT_ATTR_PAD
- 1) /
658 EXT2_EXT_ATTR_PAD
) * EXT2_EXT_ATTR_PAD
;
660 /* Fill out e appropriately */
661 e
->e_name_len
= strlen(shortname
);
662 e
->e_name_index
= (ret
? idx
: 0);
664 e
->e_value_size
= x
->value_len
;
665 e
->e_value_inum
= x
->ea_ino
;
668 memcpy((char *)e
+ sizeof(*e
), shortname
, e
->e_name_len
);
673 e
->e_value_offs
= end
- (char *) entries_start
+
674 value_offset_correction
;
675 memcpy(end
, x
->value
, e
->e_value_size
);
678 if (write_hash
|| x
->ea_ino
) {
679 err
= ext2fs_ext_attr_hash_entry2(fs
, e
,
687 e
= EXT2_EXT_ATTR_NEXT(e
);
693 errcode_t
ext2fs_xattrs_write(struct ext2_xattr_handle
*handle
)
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
;
702 unsigned int storage_size
;
706 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
708 if (i
< sizeof(*inode
))
710 err
= ext2fs_get_memzero(i
, &inode
);
714 err
= ext2fs_read_inode_full(fs
, handle
->ino
, EXT2_INODE(inode
),
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
;
726 extra
= sizeof(__u32
);
727 memset(p
+ EXT2_GOOD_OLD_INODE_SIZE
, 0, extra
);
728 inode
->i_extra_isize
= extra
;
730 if (inode
->i_extra_isize
& 3) {
731 err
= EXT2_ET_INODE_CORRUPTED
;
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
+
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
);
750 err
= write_xattrs_to_buffer(fs
, handle
->attrs
, handle
->ibody_count
,
751 start
, storage_size
, 0, 0);
756 if (handle
->ibody_count
== handle
->count
&&
757 !ext2fs_file_acl_block(fs
, EXT2_INODE(inode
)))
760 /* Write the EA block */
761 err
= ext2fs_get_memzero(fs
->blocksize
, &block_buf
);
765 storage_size
= fs
->blocksize
- sizeof(struct ext2_ext_attr_header
);
766 start
= block_buf
+ sizeof(struct ext2_ext_attr_header
);
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);
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;
780 /* Get a new block for writing */
781 err
= prep_ea_block_for_write(fs
, handle
->ino
, inode
);
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
);
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
);
800 /* Write the inode */
801 err
= ext2fs_write_inode_full(fs
, handle
->ino
, EXT2_INODE(inode
),
807 ext2fs_free_mem(&block_buf
);
809 ext2fs_free_mem(&inode
);
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
,
819 struct ext2_xattr
*x
;
820 struct ext2_ext_attr_entry
*entry
, *end
;
822 unsigned int remain
, prefix_len
;
824 unsigned int values_size
= storage_size
+
825 ((char *)entries
- value_start
);
829 remain
= storage_size
;
830 while (remain
>= sizeof(struct ext2_ext_attr_entry
) &&
831 !EXT2_EXT_IS_LAST_ENTRY(end
)) {
833 /* header eats this space */
834 remain
-= sizeof(struct ext2_ext_attr_entry
);
836 /* is attribute name valid? */
837 if (EXT2_EXT_ATTR_SIZE(end
->e_name_len
) > remain
)
838 return EXT2_ET_EA_BAD_NAME_LEN
;
840 /* attribute len eats this space */
841 remain
-= EXT2_EXT_ATTR_SIZE(end
->e_name_len
);
842 end
= EXT2_EXT_ATTR_NEXT(end
);
846 remain
= storage_size
;
847 while (remain
>= sizeof(struct ext2_ext_attr_entry
) &&
848 !EXT2_EXT_IS_LAST_ENTRY(entry
)) {
850 /* Allocate space for more attrs? */
851 if (handle
->count
== handle
->capacity
) {
852 err
= ext2fs_xattrs_expand(handle
, 4);
857 x
= handle
->attrs
+ handle
->count
;
859 /* header eats this space */
860 remain
-= sizeof(struct ext2_ext_attr_entry
);
862 /* attribute len eats this space */
863 remain
-= EXT2_EXT_ATTR_SIZE(entry
->e_name_len
);
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,
873 memcpy(x
->name
, prefix
, prefix_len
);
874 if (entry
->e_name_len
)
875 memcpy(x
->name
+ prefix_len
,
876 (char *)entry
+ sizeof(*entry
),
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
;
884 if (entry
->e_value_inum
== 0) {
885 if (entry
->e_value_size
> remain
)
886 return EXT2_ET_EA_BAD_VALUE_SIZE
;
888 if (entry
->e_value_offs
+ entry
->e_value_size
> values_size
)
889 return EXT2_ET_EA_BAD_VALUE_OFFSET
;
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
;
896 remain
-= entry
->e_value_size
;
898 err
= ext2fs_get_mem(entry
->e_value_size
, &x
->value
);
901 memcpy(x
->value
, value_start
+ entry
->e_value_offs
,
902 entry
->e_value_size
);
904 struct ext2_inode
*ea_inode
;
907 if (entry
->e_value_offs
!= 0)
908 return EXT2_ET_EA_BAD_VALUE_OFFSET
;
910 if (entry
->e_value_size
> (64 * 1024))
911 return EXT2_ET_EA_BAD_VALUE_SIZE
;
913 err
= ext2fs_get_mem(entry
->e_value_size
, &x
->value
);
917 err
= ext2fs_file_open(handle
->fs
, entry
->e_value_inum
,
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
) !=
929 err
= EXT2_ET_EA_BAD_VALUE_SIZE
;
931 err
= ext2fs_file_read(ea_file
, x
->value
,
932 entry
->e_value_size
, 0);
933 ext2fs_file_close(ea_file
);
938 x
->ea_ino
= entry
->e_value_inum
;
939 x
->value_len
= entry
->e_value_size
;
941 /* e_hash may be 0 in older inode's ea */
942 if (entry
->e_hash
!= 0) {
944 void *data
= (entry
->e_value_inum
!= 0) ?
945 0 : value_start
+ entry
->e_value_offs
;
947 err
= ext2fs_ext_attr_hash_entry2(handle
->fs
, entry
,
951 if (entry
->e_hash
!= hash
) {
952 struct ext2_inode child
;
954 /* Check whether this is an old Lustre-style
955 * ea_inode reference.
957 err
= ext2fs_read_inode(handle
->fs
,
962 if (child
.i_mtime
!= handle
->ino
||
963 child
.i_generation
!= inode
->i_generation
)
964 return EXT2_ET_BAD_EA_HASH
;
969 entry
= EXT2_EXT_ATTR_NEXT(entry
);
975 static void xattrs_free_keys(struct ext2_xattr_handle
*h
)
977 struct ext2_xattr
*a
= h
->attrs
;
980 for (i
= 0; i
< h
->capacity
; i
++) {
982 ext2fs_free_mem(&a
[i
].name
);
984 ext2fs_free_mem(&a
[i
].value
);
990 errcode_t
ext2fs_xattrs_read(struct ext2_xattr_handle
*handle
)
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
;
1001 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1002 i
= EXT2_INODE_SIZE(handle
->fs
->super
);
1003 if (i
< sizeof(*inode
))
1005 err
= ext2fs_get_memzero(i
, &inode
);
1009 err
= ext2fs_read_inode_full(handle
->fs
, handle
->ino
,
1010 (struct ext2_inode
*)inode
,
1011 EXT2_INODE_SIZE(handle
->fs
->super
));
1015 xattrs_free_keys(handle
);
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
+
1023 if (inode
->i_extra_isize
& 3) {
1024 err
= EXT2_ET_INODE_CORRUPTED
;
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
-
1035 start
= ((char *) inode
) + EXT2_GOOD_OLD_INODE_SIZE
+
1036 inode
->i_extra_isize
+ sizeof(__u32
);
1038 err
= read_xattrs_from_buffer(handle
, inode
,
1039 (struct ext2_ext_attr_entry
*) start
,
1040 storage_size
, start
);
1044 handle
->ibody_count
= handle
->count
;
1048 /* Look for EA in a separate EA block */
1049 blk
= ext2fs_file_acl_block(handle
->fs
, (struct ext2_inode
*)inode
);
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
;
1057 err
= ext2fs_get_mem(handle
->fs
->blocksize
, &block_buf
);
1061 err
= ext2fs_read_ext_attr3(handle
->fs
, blk
, block_buf
,
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
;
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
);
1083 ext2fs_free_mem(&block_buf
);
1086 ext2fs_free_mem(&block_buf
);
1087 ext2fs_free_mem(&inode
);
1091 ext2fs_free_mem(&block_buf
);
1093 ext2fs_free_mem(&inode
);
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
),
1102 struct ext2_xattr
*x
;
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
)
1111 if (ret
& XATTR_ABORT
)
1116 return ext2fs_xattrs_write(h
);
1120 errcode_t
ext2fs_xattr_get(struct ext2_xattr_handle
*h
, const char *key
,
1121 void **value
, size_t *value_len
)
1123 struct ext2_xattr
*x
;
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
))
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
,
1139 err
= ext2fs_get_mem(x
->value_len
, &val
);
1142 memcpy(val
, x
->value
, x
->value_len
);
1144 *value_len
= x
->value_len
;
1149 return EXT2_ET_EA_KEY_NOT_FOUND
;
1152 errcode_t
ext2fs_xattr_inode_max_size(ext2_filsys fs
, ext2_ino_t ino
,
1155 struct ext2_ext_attr_entry
*entry
;
1156 struct ext2_inode_large
*inode
;
1157 __u32 ea_inode_magic
;
1158 unsigned int minoff
;
1163 i
= EXT2_INODE_SIZE(fs
->super
);
1164 if (i
< sizeof(*inode
))
1166 err
= ext2fs_get_memzero(i
, &inode
);
1170 err
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)inode
,
1171 EXT2_INODE_SIZE(fs
->super
));
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
+
1179 err
= EXT2_ET_INLINE_DATA_NO_SPACE
;
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
;
1197 entry
= EXT2_EXT_ATTR_NEXT(entry
);
1199 *size
= minoff
- ((char *)entry
- (char *)start
) - sizeof(__u32
);
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
));
1208 ext2fs_free_mem(&inode
);
1212 static errcode_t
xattr_create_ea_inode(ext2_filsys fs
, const void *value
,
1213 size_t value_len
, ext2_ino_t
*ea_ino
)
1215 struct ext2_inode inode
;
1221 ret
= ext2fs_new_inode(fs
, 0, 0, 0, &ino
);
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
;
1230 inode
.i_mode
= LINUX_S_IFREG
| 0600;
1231 inode
.i_links_count
= 1;
1232 ret
= ext2fs_write_new_inode(fs
, ino
, &inode
);
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
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
);
1245 ret
= ext2fs_write_inode(fs
, ino
, &inode
);
1249 ret
= ext2fs_file_open(fs
, ino
, EXT2_FILE_WRITE
, &file
);
1252 ret
= ext2fs_file_write(file
, value
, value_len
, NULL
);
1253 ext2fs_file_close(file
);
1257 ext2fs_inode_alloc_stats2(fs
, ino
, 1 /* inuse */, 0 /* isdir */);
1263 static errcode_t
xattr_inode_dec_ref(ext2_filsys fs
, ext2_ino_t ino
)
1265 struct ext2_inode_large inode
;
1269 ret
= ext2fs_read_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
1274 ref_count
= ext2fs_get_ea_inode_ref(EXT2_INODE(&inode
));
1276 ext2fs_set_ea_inode_ref(EXT2_INODE(&inode
), ref_count
);
1281 inode
.i_links_count
= 0;
1282 inode
.i_dtime
= fs
->now
? fs
->now
: time(0);
1284 ret
= ext2fs_free_ext_attr(fs
, ino
, &inode
);
1288 if (ext2fs_inode_has_valid_blocks2(fs
, (struct ext2_inode
*)&inode
)) {
1289 ret
= ext2fs_punch(fs
, ino
, (struct ext2_inode
*)&inode
, NULL
,
1295 ext2fs_inode_alloc_stats2(fs
, ino
, -1 /* inuse */, 0 /* is_dir */);
1298 ret
= ext2fs_write_inode_full(fs
, ino
, (struct ext2_inode
*)&inode
,
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
)
1308 ext2_ino_t ea_ino
= 0;
1309 void *new_value
= NULL
;
1310 char *new_name
= NULL
;
1315 name_len
= strlen(name
);
1316 ret
= ext2fs_get_mem(name_len
+ 1, &new_name
);
1319 memcpy(new_name
, name
, name_len
+ 1);
1322 ret
= ext2fs_get_mem(value_len
, &new_value
);
1325 memcpy(new_value
, value
, value_len
);
1328 ret
= xattr_create_ea_inode(fs
, value
, value_len
, &ea_ino
);
1334 ret
= xattr_inode_dec_ref(fs
, x
->ea_ino
);
1343 ext2fs_free_mem(&x
->value
);
1344 x
->value
= new_value
;
1345 x
->value_len
= value_len
;
1350 ext2fs_free_mem(&new_name
);
1352 ext2fs_free_mem(&new_value
);
1354 xattr_inode_dec_ref(fs
, ea_ino
);
1358 static int xattr_find_position(struct ext2_xattr
*attrs
, int count
,
1361 struct ext2_xattr
*x
;
1363 const char *shortname
, *x_shortname
;
1364 int name_idx
, x_name_idx
;
1365 int shortname_len
, x_shortname_len
;
1367 find_ea_index(name
, &shortname
, &name_idx
);
1368 shortname_len
= strlen(shortname
);
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
)
1374 if (name_idx
> x_name_idx
)
1377 x_shortname_len
= strlen(x_shortname
);
1378 if (shortname_len
< x_shortname_len
)
1380 if (shortname_len
> x_shortname_len
)
1383 if (memcmp(shortname
, x_shortname
, shortname_len
) <= 0)
1389 static errcode_t
xattr_array_update(struct ext2_xattr_handle
*h
,
1391 const void *value
, size_t value_len
,
1392 int ibody_free
, int block_free
,
1393 int old_idx
, int in_inode
)
1395 struct ext2_xattr tmp
;
1398 int name_len
, name_idx
;
1399 const char *shortname
;
1403 find_ea_index(name
, &shortname
, &name_idx
);
1404 name_len
= strlen(shortname
);
1406 needed
= EXT2_EXT_ATTR_LEN(name_len
);
1408 needed
+= EXT2_EXT_ATTR_SIZE(value_len
);
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
);
1417 if (needed
<= ibody_free
) {
1419 new_idx
= h
->ibody_count
;
1424 /* Update the existing entry. */
1425 ret
= xattr_update_entry(h
->fs
, &h
->attrs
[old_idx
], name
,
1426 value
, value_len
, in_inode
);
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
;
1441 if (h
->ibody_count
<= old_idx
) {
1442 block_free
+= EXT2_EXT_ATTR_LEN(name_len
);
1443 if (!h
->attrs
[old_idx
].ea_ino
)
1445 EXT2_EXT_ATTR_SIZE(h
->attrs
[old_idx
].value_len
);
1448 if (needed
> block_free
)
1449 return EXT2_ET_EA_NO_SPACE
;
1452 /* Update the existing entry. */
1453 ret
= xattr_update_entry(h
->fs
, &h
->attrs
[old_idx
], name
,
1454 value
, value_len
, in_inode
);
1457 if (old_idx
< h
->ibody_count
) {
1459 * Move entry from ibody to the block. Note that
1460 * entries in the block are sorted.
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
;
1474 new_idx
= xattr_find_position(h
->attrs
+ h
->ibody_count
,
1475 h
->count
- h
->ibody_count
, name
);
1476 new_idx
+= h
->ibody_count
;
1480 if (h
->count
== h
->capacity
) {
1481 ret
= ext2fs_xattrs_expand(h
, 4);
1486 ret
= xattr_update_entry(h
->fs
, &h
->attrs
[h
->count
], name
, value
,
1487 value_len
, in_inode
);
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
;
1501 static int space_used(struct ext2_xattr
*attrs
, int count
)
1504 struct ext2_xattr
*x
;
1505 const char *shortname
;
1506 int i
, len
, name_idx
;
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
);
1513 total
+= EXT2_EXT_ATTR_SIZE(x
->value_len
);
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
1522 #define EXT4_XATTR_MIN_LARGE_EA_SIZE(b) \
1523 ((b) - EXT2_EXT_ATTR_LEN(3) - sizeof(struct ext2_ext_attr_header) - 4)
1525 errcode_t
ext2fs_xattr_set(struct ext2_xattr_handle
*h
,
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
;
1535 int ibody_free
, block_free
;
1541 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
1543 ret
= ext2fs_get_mem(value_len
, &new_value
);
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
);
1554 memcpy(new_value
, value
, value_len
);
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
)) {
1564 old_idx
= x
- h
->attrs
;
1569 ret
= ext2fs_get_memzero(inode_size
, &inode
);
1572 ret
= ext2fs_read_inode_full(fs
, h
->ino
,
1573 (struct ext2_inode
*)inode
,
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
);
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
);
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
;
1598 ret
= xattr_array_update(h
, name
, new_value
, value_len
,
1600 0 /* block_free */, old_idx
,
1607 block_free
= fs
->blocksize
;
1608 block_free
-= sizeof(struct ext2_ext_attr_header
);
1609 /* Final null entry. */
1610 block_free
-= sizeof(__u32
);
1611 block_free
-= space_used(h
->attrs
+ h
->ibody_count
,
1612 h
->count
- h
->ibody_count
);
1614 if (ext2fs_has_feature_ea_inode(fs
->super
) &&
1615 value_len
> EXT4_XATTR_MIN_LARGE_EA_SIZE(fs
->blocksize
))
1618 ret
= xattr_array_update(h
, name
, new_value
, value_len
, ibody_free
,
1619 block_free
, old_idx
, in_inode
);
1620 if (ret
== EXT2_ET_EA_NO_SPACE
&& !in_inode
&&
1621 ext2fs_has_feature_ea_inode(fs
->super
))
1622 ret
= xattr_array_update(h
, name
, new_value
, value_len
,
1623 ibody_free
, block_free
, old_idx
, 1 /* in_inode */);
1628 ret
= ext2fs_xattrs_write(h
);
1631 ext2fs_free_mem(&inode
);
1632 ext2fs_free_mem(&new_value
);
1636 errcode_t
ext2fs_xattr_remove(struct ext2_xattr_handle
*handle
,
1639 struct ext2_xattr
*x
;
1640 struct ext2_xattr
*end
= handle
->attrs
+ handle
->count
;
1642 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1643 for (x
= handle
->attrs
; x
< end
; x
++) {
1644 if (strcmp(x
->name
, key
) == 0) {
1645 ext2fs_free_mem(&x
->name
);
1646 ext2fs_free_mem(&x
->value
);
1648 xattr_inode_dec_ref(handle
->fs
, x
->ea_ino
);
1649 memmove(x
, x
+ 1, (end
- x
- 1)*sizeof(*x
));
1650 memset(end
- 1, 0, sizeof(*end
));
1651 if (x
< handle
->attrs
+ handle
->ibody_count
)
1652 handle
->ibody_count
--;
1654 return ext2fs_xattrs_write(handle
);
1658 /* no key found, success! */
1662 errcode_t
ext2fs_xattrs_open(ext2_filsys fs
, ext2_ino_t ino
,
1663 struct ext2_xattr_handle
**handle
)
1665 struct ext2_xattr_handle
*h
;
1668 if (!ext2fs_has_feature_xattr(fs
->super
) &&
1669 !ext2fs_has_feature_inline_data(fs
->super
))
1670 return EXT2_ET_MISSING_EA_FEATURE
;
1672 err
= ext2fs_get_memzero(sizeof(*h
), &h
);
1676 h
->magic
= EXT2_ET_MAGIC_EA_HANDLE
;
1678 err
= ext2fs_get_arrayzero(h
->capacity
, sizeof(struct ext2_xattr
),
1681 ext2fs_free_mem(&h
);
1691 errcode_t
ext2fs_xattrs_close(struct ext2_xattr_handle
**handle
)
1693 struct ext2_xattr_handle
*h
= *handle
;
1695 EXT2_CHECK_MAGIC(h
, EXT2_ET_MAGIC_EA_HANDLE
);
1696 xattrs_free_keys(h
);
1697 ext2fs_free_mem(&h
->attrs
);
1698 ext2fs_free_mem(handle
);
1702 errcode_t
ext2fs_xattrs_count(struct ext2_xattr_handle
*handle
, size_t *count
)
1704 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1705 *count
= handle
->count
;
1709 errcode_t
ext2fs_xattrs_flags(struct ext2_xattr_handle
*handle
,
1710 unsigned int *new_flags
, unsigned int *old_flags
)
1712 EXT2_CHECK_MAGIC(handle
, EXT2_ET_MAGIC_EA_HANDLE
);
1714 *old_flags
= handle
->flags
;
1716 handle
->flags
= *new_flags
;