• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
69 static struct selabel_handle *sehnd = NULL;
70 #endif
71 /* ANDROID CHANGES END */
72 
73 /* compressed xattr table */
74 static char *xattr_table = NULL;
75 static unsigned int xattr_size = 0;
76 
77 /* cached uncompressed xattr data */
78 static char *data_cache = NULL;
79 static int cache_bytes = 0, cache_size = 0;
80 
81 /* cached uncompressed xattr id table */
82 static struct squashfs_xattr_id *xattr_id_table = NULL;
83 static int xattr_ids = 0;
84 
85 /* saved compressed xattr table */
86 unsigned int sxattr_bytes = 0, stotal_xattr_bytes = 0;
87 
88 /* saved cached uncompressed xattr data */
89 static char *sdata_cache = NULL;
90 static int scache_bytes = 0;
91 
92 /* saved cached uncompressed xattr id table */
93 static int sxattr_ids = 0;
94 
95 /* xattr hash table for value duplicate detection */
96 static struct xattr_list *dupl_value[65536];
97 
98 /* xattr hash table for id duplicate detection */
99 static struct dupl_id *dupl_id[65536];
100 
101 /* file system globals from mksquashfs.c */
102 extern int no_xattrs, noX;
103 extern long long bytes;
104 extern int fd;
105 extern unsigned int xattr_bytes, total_xattr_bytes;
106 /* ANDROID CHANGES START*/
107 extern char *context_file;
108 extern char *mount_point;
109 /* ANDROID CHANGES END */
110 
111 /* helper functions from mksquashfs.c */
112 extern unsigned short get_checksum(char *, int, unsigned short);
113 extern void write_destination(int, long long, int, void *);
114 extern long long generic_write_table(int, void *, int, void *, int);
115 extern int mangle(char *, char *, int, int, int, int);
116 extern char *pathname(struct dir_ent *);
117 /* ANDROID CHANGES START*/
118 #ifdef ANDROID
119 extern char *subpathname(struct dir_ent *);
120 #endif
121 /* ANDROID CHANGES END */
122 
123 /* helper functions and definitions from read_xattrs.c */
124 extern int read_xattrs_from_disk(int, struct squashfs_super_block *);
125 extern struct xattr_list *get_xattr(int, unsigned int *, int);
126 extern struct prefix prefix_table[];
127 
128 
get_prefix(struct xattr_list * xattr,char * name)129 static 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
next_xattr_list(int * xattr_count,struct xattr_list ** xattrs)152 static 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 
read_selinux_xattr_from_sehnd(char * filename,int mode,struct selabel_handle * sehnd,struct xattr_list * xattrs)160 static 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 
set_caps_xattr(uint64_t caps,struct xattr_list * xattrs)171 static 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 
read_xattrs_from_system(char * filename,struct xattr_list ** xattrs)186 static 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 
289 failed:
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 
get_xattr_size(struct xattr_list * xattr)300 static 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 
get_xattr_space(unsigned int req_size,long long * disk)314 static 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 
check_id_dupl(struct xattr_list * xattr_list,int xattrs)363 static 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 
check_value_dupl(struct xattr_list * xattr)414 static 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 
get_xattr_id(int xattrs,struct xattr_list * xattr_list,long long xattr_disk,struct dupl_id * xattr_dupl)456 static 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 
write_xattrs()488 long 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 
generate_xattrs(int xattrs,struct xattr_list * xattr_list)544 int 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 
read_xattrs(void * d)678 int 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  */
get_xattrs(int fd,struct squashfs_super_block * sBlk)737 int 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 
772 done:
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  */
save_xattrs()781 void 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  */
restore_xattrs()807 void 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