1/* 2 * Create a squashfs filesystem. This is a highly compressed read only 3 * filesystem. 4 * 5 * Copyright (c) 2008, 2009, 2010, 2012, 2014 6 * Phillip Lougher <phillip@squashfs.org.uk> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2, 11 * or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * 22 * xattr.c 23 */ 24 25#ifndef linux 26#define __BYTE_ORDER BYTE_ORDER 27#define __BIG_ENDIAN BIG_ENDIAN 28#define __LITTLE_ENDIAN LITTLE_ENDIAN 29#else 30#include <endian.h> 31#endif 32 33#define TRUE 1 34#define FALSE 0 35 36#include <unistd.h> 37#include <stdio.h> 38#include <sys/types.h> 39#include <sys/stat.h> 40#include <fcntl.h> 41#include <errno.h> 42#include <dirent.h> 43#include <string.h> 44#include <stdlib.h> 45#include <sys/xattr.h> 46 47#ifdef XATTR_NOFOLLOW /* Apple's xattrs */ 48 #define llistxattr(path_, buf_, sz_) \ 49 listxattr(path_, buf_, sz_, XATTR_NOFOLLOW) 50 #define lgetxattr(path_, name_, val_, sz_) \ 51 getxattr(path_, name_, val_, sz_, 0, XATTR_NOFOLLOW) 52#endif 53 54#include "squashfs_fs.h" 55#include "squashfs_swap.h" 56#include "mksquashfs.h" 57#include "xattr.h" 58#include "error.h" 59#include "progressbar.h" 60 61/* ANDROID CHANGES START*/ 62#ifdef ANDROID 63#include "android.h" 64#ifdef __ANDROID__ 65#include <linux/capability.h> 66#else 67#include <private/android_filesystem_capability.h> 68#endif 69static struct selabel_handle *sehnd = NULL; 70#endif 71/* ANDROID CHANGES END */ 72 73/* compressed xattr table */ 74static char *xattr_table = NULL; 75static unsigned int xattr_size = 0; 76 77/* cached uncompressed xattr data */ 78static char *data_cache = NULL; 79static int cache_bytes = 0, cache_size = 0; 80 81/* cached uncompressed xattr id table */ 82static struct squashfs_xattr_id *xattr_id_table = NULL; 83static int xattr_ids = 0; 84 85/* saved compressed xattr table */ 86unsigned int sxattr_bytes = 0, stotal_xattr_bytes = 0; 87 88/* saved cached uncompressed xattr data */ 89static char *sdata_cache = NULL; 90static int scache_bytes = 0; 91 92/* saved cached uncompressed xattr id table */ 93static int sxattr_ids = 0; 94 95/* xattr hash table for value duplicate detection */ 96static struct xattr_list *dupl_value[65536]; 97 98/* xattr hash table for id duplicate detection */ 99static struct dupl_id *dupl_id[65536]; 100 101/* file system globals from mksquashfs.c */ 102extern int no_xattrs, noX; 103extern long long bytes; 104extern int fd; 105extern unsigned int xattr_bytes, total_xattr_bytes; 106/* ANDROID CHANGES START*/ 107extern char *context_file; 108extern char *mount_point; 109/* ANDROID CHANGES END */ 110 111/* helper functions from mksquashfs.c */ 112extern unsigned short get_checksum(char *, int, unsigned short); 113extern void write_destination(int, long long, int, void *); 114extern long long generic_write_table(int, void *, int, void *, int); 115extern int mangle(char *, char *, int, int, int, int); 116extern char *pathname(struct dir_ent *); 117/* ANDROID CHANGES START*/ 118#ifdef ANDROID 119extern char *subpathname(struct dir_ent *); 120#endif 121/* ANDROID CHANGES END */ 122 123/* helper functions and definitions from read_xattrs.c */ 124extern int read_xattrs_from_disk(int, struct squashfs_super_block *); 125extern struct xattr_list *get_xattr(int, unsigned int *, int); 126extern struct prefix prefix_table[]; 127 128 129static int get_prefix(struct xattr_list *xattr, char *name) 130{ 131 int i; 132 133 xattr->full_name = strdup(name); 134 135 for(i = 0; prefix_table[i].type != -1; i++) { 136 struct prefix *p = &prefix_table[i]; 137 if(strncmp(xattr->full_name, p->prefix, strlen(p->prefix)) == 0) 138 break; 139 } 140 141 if(prefix_table[i].type != -1) { 142 xattr->name = xattr->full_name + strlen(prefix_table[i].prefix); 143 xattr->size = strlen(xattr->name); 144 } 145 146 return prefix_table[i].type; 147} 148 149 150/* ANDROID CHANGES START*/ 151#ifdef ANDROID 152static struct xattr_list *next_xattr_list(int *xattr_count, struct xattr_list **xattrs) { 153 struct xattr_list *x; 154 x = realloc(*xattrs, ++*xattr_count * sizeof(struct xattr_list)); 155 if (x == NULL) MEM_ERROR(); 156 *xattrs = x; 157 return &x[*xattr_count - 1]; 158} 159 160static void read_selinux_xattr_from_sehnd(char *filename, int mode, 161 struct selabel_handle *sehnd, struct xattr_list *xattrs) 162{ 163 char *attr_val; 164 165 xattrs->type = get_prefix(xattrs, "security.selinux"); 166 attr_val = set_selabel(filename, mode, sehnd); 167 xattrs->value = (void *)attr_val; 168 xattrs->vsize = strlen(attr_val); 169} 170 171static void set_caps_xattr(uint64_t caps, struct xattr_list *xattrs) 172{ 173 struct vfs_cap_data *attr_val; 174 attr_val = malloc(sizeof(*attr_val)); 175 if (attr_val == NULL) MEM_ERROR(); 176 177 xattrs->type = get_prefix(xattrs, "security.capability"); 178 *attr_val = set_caps(caps); 179 xattrs->value = attr_val; 180 xattrs->vsize = sizeof(*attr_val); 181} 182#endif 183/* ANDROID CHANGES END */ 184 185 186static int read_xattrs_from_system(char *filename, struct xattr_list **xattrs) 187{ 188 ssize_t size, vsize; 189 char *xattr_names, *p; 190 int i; 191 struct xattr_list *xattr_list = NULL; 192 193 while(1) { 194 size = llistxattr(filename, NULL, 0); 195 if(size <= 0) { 196 if(size < 0 && errno != ENOTSUP) { 197 ERROR_START("llistxattr for %s failed in " 198 "read_attrs, because %s", filename, 199 strerror(errno)); 200 ERROR_EXIT(". Ignoring"); 201 } 202 return 0; 203 } 204 205 xattr_names = malloc(size); 206 if(xattr_names == NULL) 207 MEM_ERROR(); 208 209 size = llistxattr(filename, xattr_names, size); 210 if(size < 0) { 211 free(xattr_names); 212 if(errno == ERANGE) 213 /* xattr list grew? Try again */ 214 continue; 215 else { 216 ERROR_START("llistxattr for %s failed in " 217 "read_attrs, because %s", filename, 218 strerror(errno)); 219 ERROR_EXIT(". Ignoring"); 220 return 0; 221 } 222 } 223 224 break; 225 } 226 227 for(i = 0, p = xattr_names; p < xattr_names + size; i++) { 228 struct xattr_list *x = realloc(xattr_list, (i + 1) * 229 sizeof(struct xattr_list)); 230 if(x == NULL) 231 MEM_ERROR(); 232 xattr_list = x; 233 234 xattr_list[i].type = get_prefix(&xattr_list[i], p); 235 p += strlen(p) + 1; 236 if(xattr_list[i].type == -1) { 237 ERROR("Unrecognised xattr prefix %s\n", 238 xattr_list[i].full_name); 239 free(xattr_list[i].full_name); 240 i--; 241 continue; 242 } 243 244 while(1) { 245 vsize = lgetxattr(filename, xattr_list[i].full_name, 246 NULL, 0); 247 if(vsize < 0) { 248 ERROR_START("lgetxattr failed for %s in " 249 "read_attrs, because %s", filename, 250 strerror(errno)); 251 ERROR_EXIT(". Ignoring"); 252 free(xattr_list[i].full_name); 253 goto failed; 254 } 255 256 xattr_list[i].value = malloc(vsize); 257 if(xattr_list[i].value == NULL) 258 MEM_ERROR(); 259 260 vsize = lgetxattr(filename, xattr_list[i].full_name, 261 xattr_list[i].value, vsize); 262 if(vsize < 0) { 263 free(xattr_list[i].value); 264 if(errno == ERANGE) 265 /* xattr grew? Try again */ 266 continue; 267 else { 268 ERROR_START("lgetxattr failed for %s " 269 "in read_attrs, because %s", 270 filename, strerror(errno)); 271 ERROR_EXIT(". Ignoring"); 272 free(xattr_list[i].full_name); 273 goto failed; 274 } 275 } 276 277 break; 278 } 279 xattr_list[i].vsize = vsize; 280 281 TRACE("read_xattrs_from_system: filename %s, xattr name %s," 282 " vsize %d\n", filename, xattr_list[i].full_name, 283 xattr_list[i].vsize); 284 } 285 free(xattr_names); 286 *xattrs = xattr_list; 287 return i; 288 289failed: 290 while(--i >= 0) { 291 free(xattr_list[i].full_name); 292 free(xattr_list[i].value); 293 } 294 free(xattr_list); 295 free(xattr_names); 296 return 0; 297} 298 299 300static int get_xattr_size(struct xattr_list *xattr) 301{ 302 int size = sizeof(struct squashfs_xattr_entry) + 303 sizeof(struct squashfs_xattr_val) + xattr->size; 304 305 if(xattr->type & XATTR_VALUE_OOL) 306 size += XATTR_VALUE_OOL_SIZE; 307 else 308 size += xattr->vsize; 309 310 return size; 311} 312 313 314static void *get_xattr_space(unsigned int req_size, long long *disk) 315{ 316 int data_space; 317 unsigned short c_byte; 318 319 /* 320 * Move and compress cached uncompressed data into xattr table. 321 */ 322 while(cache_bytes >= SQUASHFS_METADATA_SIZE) { 323 if((xattr_size - xattr_bytes) < 324 ((SQUASHFS_METADATA_SIZE << 1)) + 2) { 325 xattr_table = realloc(xattr_table, xattr_size + 326 (SQUASHFS_METADATA_SIZE << 1) + 2); 327 if(xattr_table == NULL) 328 MEM_ERROR(); 329 xattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2; 330 } 331 332 c_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, 333 data_cache, SQUASHFS_METADATA_SIZE, 334 SQUASHFS_METADATA_SIZE, noX, 0); 335 TRACE("Xattr block @ 0x%x, size %d\n", xattr_bytes, c_byte); 336 SQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1); 337 xattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; 338 memmove(data_cache, data_cache + SQUASHFS_METADATA_SIZE, 339 cache_bytes - SQUASHFS_METADATA_SIZE); 340 cache_bytes -= SQUASHFS_METADATA_SIZE; 341 } 342 343 /* 344 * Ensure there's enough space in the uncompressed data cache 345 */ 346 data_space = cache_size - cache_bytes; 347 if(data_space < req_size) { 348 int realloc_size = req_size - data_space; 349 data_cache = realloc(data_cache, cache_size + 350 realloc_size); 351 if(data_cache == NULL) 352 MEM_ERROR(); 353 cache_size += realloc_size; 354 } 355 356 if(disk) 357 *disk = ((long long) xattr_bytes << 16) | cache_bytes; 358 cache_bytes += req_size; 359 return data_cache + cache_bytes - req_size; 360} 361 362 363static struct dupl_id *check_id_dupl(struct xattr_list *xattr_list, int xattrs) 364{ 365 struct dupl_id *entry; 366 int i; 367 unsigned short checksum = 0; 368 369 /* compute checksum over all xattrs */ 370 for(i = 0; i < xattrs; i++) { 371 struct xattr_list *xattr = &xattr_list[i]; 372 373 checksum = get_checksum(xattr->full_name, 374 strlen(xattr->full_name), checksum); 375 checksum = get_checksum(xattr->value, 376 xattr->vsize, checksum); 377 } 378 379 for(entry = dupl_id[checksum]; entry; entry = entry->next) { 380 if (entry->xattrs != xattrs) 381 continue; 382 383 for(i = 0; i < xattrs; i++) { 384 struct xattr_list *xattr = &xattr_list[i]; 385 struct xattr_list *dup_xattr = &entry->xattr_list[i]; 386 387 if(strcmp(xattr->full_name, dup_xattr->full_name)) 388 break; 389 390 if(memcmp(xattr->value, dup_xattr->value, xattr->vsize)) 391 break; 392 } 393 394 if(i == xattrs) 395 break; 396 } 397 398 if(entry == NULL) { 399 /* no duplicate exists */ 400 entry = malloc(sizeof(*entry)); 401 if(entry == NULL) 402 MEM_ERROR(); 403 entry->xattrs = xattrs; 404 entry->xattr_list = xattr_list; 405 entry->xattr_id = SQUASHFS_INVALID_XATTR; 406 entry->next = dupl_id[checksum]; 407 dupl_id[checksum] = entry; 408 } 409 410 return entry; 411} 412 413 414static void check_value_dupl(struct xattr_list *xattr) 415{ 416 struct xattr_list *entry; 417 418 if(xattr->vsize < XATTR_VALUE_OOL_SIZE) 419 return; 420 421 /* Check if this is a duplicate of an existing value */ 422 xattr->vchecksum = get_checksum(xattr->value, xattr->vsize, 0); 423 for(entry = dupl_value[xattr->vchecksum]; entry; entry = entry->vnext) { 424 if(entry->vsize != xattr->vsize) 425 continue; 426 427 if(memcmp(entry->value, xattr->value, xattr->vsize) == 0) 428 break; 429 } 430 431 if(entry == NULL) { 432 /* 433 * No duplicate exists, add to hash table, and mark as 434 * requiring writing 435 */ 436 xattr->vnext = dupl_value[xattr->vchecksum]; 437 dupl_value[xattr->vchecksum] = xattr; 438 xattr->ool_value = SQUASHFS_INVALID_BLK; 439 } else { 440 /* 441 * Duplicate exists, make type XATTR_VALUE_OOL, and 442 * remember where the duplicate is 443 */ 444 xattr->type |= XATTR_VALUE_OOL; 445 xattr->ool_value = entry->ool_value; 446 /* on appending don't free duplicate values because the 447 * duplicate value already points to the non-duplicate value */ 448 if(xattr->value != entry->value) { 449 free(xattr->value); 450 xattr->value = entry->value; 451 } 452 } 453} 454 455 456static int get_xattr_id(int xattrs, struct xattr_list *xattr_list, 457 long long xattr_disk, struct dupl_id *xattr_dupl) 458{ 459 int i, size = 0; 460 struct squashfs_xattr_id *xattr_id; 461 462 xattr_id_table = realloc(xattr_id_table, (xattr_ids + 1) * 463 sizeof(struct squashfs_xattr_id)); 464 if(xattr_id_table == NULL) 465 MEM_ERROR(); 466 467 /* get total uncompressed size of xattr data, needed for stat */ 468 for(i = 0; i < xattrs; i++) 469 size += strlen(xattr_list[i].full_name) + 1 + 470 xattr_list[i].vsize; 471 472 xattr_id = &xattr_id_table[xattr_ids]; 473 xattr_id->xattr = xattr_disk; 474 xattr_id->count = xattrs; 475 xattr_id->size = size; 476 477 /* 478 * keep track of total uncompressed xattr data, needed for mksquashfs 479 * file system summary 480 */ 481 total_xattr_bytes += size; 482 483 xattr_dupl->xattr_id = xattr_ids ++; 484 return xattr_dupl->xattr_id; 485} 486 487 488long long write_xattrs() 489{ 490 unsigned short c_byte; 491 int i, avail_bytes; 492 char *datap = data_cache; 493 long long start_bytes = bytes; 494 struct squashfs_xattr_table header; 495 496 if(xattr_ids == 0) 497 return SQUASHFS_INVALID_BLK; 498 499 /* 500 * Move and compress cached uncompressed data into xattr table. 501 */ 502 while(cache_bytes) { 503 if((xattr_size - xattr_bytes) < 504 ((SQUASHFS_METADATA_SIZE << 1)) + 2) { 505 xattr_table = realloc(xattr_table, xattr_size + 506 (SQUASHFS_METADATA_SIZE << 1) + 2); 507 if(xattr_table == NULL) 508 MEM_ERROR(); 509 xattr_size += (SQUASHFS_METADATA_SIZE << 1) + 2; 510 } 511 512 avail_bytes = cache_bytes > SQUASHFS_METADATA_SIZE ? 513 SQUASHFS_METADATA_SIZE : cache_bytes; 514 c_byte = mangle(xattr_table + xattr_bytes + BLOCK_OFFSET, datap, 515 avail_bytes, SQUASHFS_METADATA_SIZE, noX, 0); 516 TRACE("Xattr block @ 0x%x, size %d\n", xattr_bytes, c_byte); 517 SQUASHFS_SWAP_SHORTS(&c_byte, xattr_table + xattr_bytes, 1); 518 xattr_bytes += SQUASHFS_COMPRESSED_SIZE(c_byte) + BLOCK_OFFSET; 519 datap += avail_bytes; 520 cache_bytes -= avail_bytes; 521 } 522 523 /* 524 * Write compressed xattr table to file system 525 */ 526 write_destination(fd, bytes, xattr_bytes, xattr_table); 527 bytes += xattr_bytes; 528 529 /* 530 * Swap if necessary the xattr id table 531 */ 532 for(i = 0; i < xattr_ids; i++) 533 SQUASHFS_INSWAP_XATTR_ID(&xattr_id_table[i]); 534 535 header.xattr_ids = xattr_ids; 536 header.xattr_table_start = start_bytes; 537 SQUASHFS_INSWAP_XATTR_TABLE(&header); 538 539 return generic_write_table(xattr_ids * sizeof(struct squashfs_xattr_id), 540 xattr_id_table, sizeof(header), &header, noX); 541} 542 543 544int generate_xattrs(int xattrs, struct xattr_list *xattr_list) 545{ 546 int total_size, i; 547 int xattr_value_max; 548 void *xp; 549 long long xattr_disk; 550 struct dupl_id *xattr_dupl; 551 552 /* 553 * check if the file xattrs are a complete duplicate of a pre-existing 554 * id 555 */ 556 xattr_dupl = check_id_dupl(xattr_list, xattrs); 557 if(xattr_dupl->xattr_id != SQUASHFS_INVALID_XATTR) 558 return xattr_dupl->xattr_id; 559 560 /* 561 * Scan the xattr_list deciding which type to assign to each 562 * xattr. The choice is fairly straightforward, and depends on the 563 * size of each xattr name/value and the overall size of the 564 * resultant xattr list stored in the xattr metadata table. 565 * 566 * Choices are whether to store data inline or out of line. 567 * 568 * The overall goal is to optimise xattr scanning and lookup, and 569 * to enable the file system layout to scale from a couple of 570 * small xattr name/values to a large number of large xattr 571 * names/values without affecting performance. While hopefully 572 * enabling the common case of a couple of small xattr name/values 573 * to be stored efficiently 574 * 575 * Code repeatedly scans, doing the following 576 * move xattr data out of line if it exceeds 577 * xattr_value_max. Where xattr_value_max is 578 * initially XATTR_INLINE_MAX. If the final uncompressed 579 * xattr list is larger than XATTR_TARGET_MAX then more 580 * aggressively move xattr data out of line by repeatedly 581 * setting inline threshold to 1/2, then 1/4, 1/8 of 582 * XATTR_INLINE_MAX until target achieved or there's 583 * nothing left to move out of line 584 */ 585 xattr_value_max = XATTR_INLINE_MAX; 586 while(1) { 587 for(total_size = 0, i = 0; i < xattrs; i++) { 588 struct xattr_list *xattr = &xattr_list[i]; 589 xattr->type &= XATTR_PREFIX_MASK; /* all inline */ 590 if (xattr->vsize > xattr_value_max) 591 xattr->type |= XATTR_VALUE_OOL; 592 593 total_size += get_xattr_size(xattr); 594 } 595 596 /* 597 * If the total size of the uncompressed xattr list is <= 598 * XATTR_TARGET_MAX we're done 599 */ 600 if(total_size <= XATTR_TARGET_MAX) 601 break; 602 603 if(xattr_value_max == XATTR_VALUE_OOL_SIZE) 604 break; 605 606 /* 607 * Inline target not yet at minimum and so reduce it, and 608 * try again 609 */ 610 xattr_value_max /= 2; 611 if(xattr_value_max < XATTR_VALUE_OOL_SIZE) 612 xattr_value_max = XATTR_VALUE_OOL_SIZE; 613 } 614 615 /* 616 * Check xattr values for duplicates 617 */ 618 for(i = 0; i < xattrs; i++) { 619 check_value_dupl(&xattr_list[i]); 620 } 621 622 /* 623 * Add each out of line value to the file system xattr table 624 * if it doesn't already exist as a duplicate 625 */ 626 for(i = 0; i < xattrs; i++) { 627 struct xattr_list *xattr = &xattr_list[i]; 628 629 if((xattr->type & XATTR_VALUE_OOL) && 630 (xattr->ool_value == SQUASHFS_INVALID_BLK)) { 631 struct squashfs_xattr_val val; 632 int size = sizeof(val) + xattr->vsize; 633 xp = get_xattr_space(size, &xattr->ool_value); 634 val.vsize = xattr->vsize; 635 SQUASHFS_SWAP_XATTR_VAL(&val, xp); 636 memcpy(xp + sizeof(val), xattr->value, xattr->vsize); 637 } 638 } 639 640 /* 641 * Create xattr list and add to file system xattr table 642 */ 643 get_xattr_space(0, &xattr_disk); 644 for(i = 0; i < xattrs; i++) { 645 struct xattr_list *xattr = &xattr_list[i]; 646 struct squashfs_xattr_entry entry; 647 struct squashfs_xattr_val val; 648 649 xp = get_xattr_space(sizeof(entry) + xattr->size, NULL); 650 entry.type = xattr->type; 651 entry.size = xattr->size; 652 SQUASHFS_SWAP_XATTR_ENTRY(&entry, xp); 653 memcpy(xp + sizeof(entry), xattr->name, xattr->size); 654 655 if(xattr->type & XATTR_VALUE_OOL) { 656 int size = sizeof(val) + XATTR_VALUE_OOL_SIZE; 657 xp = get_xattr_space(size, NULL); 658 val.vsize = XATTR_VALUE_OOL_SIZE; 659 SQUASHFS_SWAP_XATTR_VAL(&val, xp); 660 SQUASHFS_SWAP_LONG_LONGS(&xattr->ool_value, xp + 661 sizeof(val), 1); 662 } else { 663 int size = sizeof(val) + xattr->vsize; 664 xp = get_xattr_space(size, &xattr->ool_value); 665 val.vsize = xattr->vsize; 666 SQUASHFS_SWAP_XATTR_VAL(&val, xp); 667 memcpy(xp + sizeof(val), xattr->value, xattr->vsize); 668 } 669 } 670 671 /* 672 * Add to xattr id lookup table 673 */ 674 return get_xattr_id(xattrs, xattr_list, xattr_disk, xattr_dupl); 675} 676 677 678int read_xattrs(void *d) 679{ 680 struct dir_ent *dir_ent = d; 681 struct inode_info *inode = dir_ent->inode; 682 char *filename = pathname(dir_ent); 683/* ANDROID CHANGES START*/ 684#ifdef ANDROID 685 // NOTE: xattr_list has to point to an array of xattr_list elements 686 struct xattr_list *xattr_list = NULL, *next_xattr = NULL; 687 int xattrs = 0; 688#else 689 struct xattr_list *xattr_list; 690 int xattrs; 691#endif 692/* ANDROID CHANGES END */ 693 694 if(no_xattrs || IS_PSEUDO(inode) || inode->root_entry) 695 return SQUASHFS_INVALID_XATTR; 696 697/* ANDROID CHANGES START*/ 698#ifdef ANDROID 699 if (context_file) { 700 if (sehnd == NULL) 701 sehnd = get_sehnd(context_file); 702 if (mount_point) { 703 char *mounted_path; 704 alloc_mounted_path(mount_point, subpathname(dir_ent), &mounted_path); 705 next_xattr = next_xattr_list(&xattrs, &xattr_list); 706 read_selinux_xattr_from_sehnd(mounted_path, inode->buf.st_mode, 707 sehnd, next_xattr); 708 free(mounted_path); 709 } else { 710 next_xattr = next_xattr_list(&xattrs, &xattr_list); 711 read_selinux_xattr_from_sehnd(filename, inode->buf.st_mode, 712 sehnd, next_xattr); 713 } 714 } 715 if (dir_ent->capabilities != 0) { 716 next_xattr = next_xattr_list(&xattrs, &xattr_list); 717 set_caps_xattr(dir_ent->capabilities, next_xattr); 718 } 719#else 720 xattrs = read_xattrs_from_system(filename, &xattr_list); 721#endif 722/* ANDROID CHANGES END */ 723 724 if(xattrs == 0) 725 return SQUASHFS_INVALID_XATTR; 726 727 return generate_xattrs(xattrs, xattr_list); 728} 729 730 731/* 732 * Add the existing xattr ids and xattr metadata in the file system being 733 * appended to, to the in-memory xattr cache. This allows duplicate checking to 734 * take place against the xattrs already in the file system being appended to, 735 * and ensures the pre-existing xattrs are written out along with any new xattrs 736 */ 737int get_xattrs(int fd, struct squashfs_super_block *sBlk) 738{ 739 int ids, res, i, id; 740 unsigned int count; 741 742 TRACE("get_xattrs\n"); 743 744 res = read_xattrs_from_disk(fd, sBlk); 745 if(res == SQUASHFS_INVALID_BLK || res == 0) 746 goto done; 747 ids = res; 748 749 /* 750 * for each xattr id read and construct its list of xattr 751 * name:value pairs, and add them to the in-memory xattr cache 752 */ 753 for(i = 0; i < ids; i++) { 754 struct xattr_list *xattr_list = get_xattr(i, &count, 0); 755 if(xattr_list == NULL) { 756 res = 0; 757 goto done; 758 } 759 id = generate_xattrs(count, xattr_list); 760 761 /* 762 * Sanity check, the new xattr id should be the same as the 763 * xattr id in the original file system 764 */ 765 if(id != i) { 766 ERROR("BUG, different xattr_id in get_xattrs\n"); 767 res = 0; 768 goto done; 769 } 770 } 771 772done: 773 return res; 774} 775 776 777/* 778 * Save current state of xattrs, needed for restoring state in the event of an 779 * abort in appending 780 */ 781void save_xattrs() 782{ 783 /* save the current state of the compressed xattr data */ 784 sxattr_bytes = xattr_bytes; 785 stotal_xattr_bytes = total_xattr_bytes; 786 787 /* 788 * save the current state of the cached uncompressed xattr data. 789 * Note we have to save the contents of the data cache because future 790 * operations will delete the current contents 791 */ 792 sdata_cache = malloc(cache_bytes); 793 if(sdata_cache == NULL) 794 MEM_ERROR(); 795 796 memcpy(sdata_cache, data_cache, cache_bytes); 797 scache_bytes = cache_bytes; 798 799 /* save the current state of the xattr id table */ 800 sxattr_ids = xattr_ids; 801} 802 803 804/* 805 * Restore xattrs in the event of an abort in appending 806 */ 807void restore_xattrs() 808{ 809 /* restore the state of the compressed xattr data */ 810 xattr_bytes = sxattr_bytes; 811 total_xattr_bytes = stotal_xattr_bytes; 812 813 /* restore the state of the uncomoressed xattr data */ 814 memcpy(data_cache, sdata_cache, scache_bytes); 815 cache_bytes = scache_bytes; 816 817 /* restore the state of the xattr id table */ 818 xattr_ids = sxattr_ids; 819} 820