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