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