Exemple #1
0
int read_block(int fd, long long start, long long *next, int expected,
								void *block)
{
	unsigned short c_byte;
	int res, compressed;
	int outlen = expected ? expected : SQUASHFS_METADATA_SIZE;
	
	/* Read block size */
	res = read_fs_bytes(fd, start, 2, &c_byte);
	if(res == 0)
		return 0;

	SQUASHFS_INSWAP_SHORTS(&c_byte, 1);
	compressed = SQUASHFS_COMPRESSED(c_byte);
	c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);

	/*
	 * The block size should not be larger than
	 * the uncompressed size (or max uncompressed size if
	 * expected is 0)
	 */
	if (c_byte > outlen)
		return 0;

	if(compressed) {
		char buffer[c_byte];
		int error;

		res = read_fs_bytes(fd, start + 2, c_byte, buffer);
		if(res == 0)
			return 0;

		res = compressor_uncompress(comp, block, buffer, c_byte,
			outlen, &error);
		if(res == -1) {
            // CJH: Decompression errors are displayed elsewhere
			//ERROR("%s uncompress failed with error code %d\n",
			//	comp->name, error);
			return 0;
		}
	} else {
		res = read_fs_bytes(fd, start + 2, c_byte, block);
		if(res == 0)
			return 0;
		res = c_byte;
	}

	if(next)
		*next = start + 2 + c_byte;

	/*
	 * if expected, then check the (uncompressed) return data
	 * is of the expected size
	 */
	if(expected && expected != res)
		return 0;
	else
		return res;
}
Exemple #2
0
static int read_metadata_block(const struct PkgData *pdata,
		const long long start, long long *next,
		void *buf, const size_t buf_size)
{
	long long offset = start;

	unsigned short c_byte;
	int ret = read_fs_bytes(pdata->fd, offset, &c_byte, 2);
	if (ret) {
		goto failed;
	}

	offset += 2;
	int csize = SQUASHFS_COMPRESSED_SIZE(c_byte);

	TRACE("read_metadata_block: block @0x%llx, %d %s bytes\n", start, csize,
			SQUASHFS_COMPRESSED(c_byte) ? "compressed" : "uncompressed");

	ret = SQUASHFS_COMPRESSED(c_byte)
		? read_compressed(pdata, offset, csize, buf, buf_size)
		: read_uncompressed(pdata, offset, csize, buf, buf_size);
	if (ret < 0) {
		goto failed;
	}

	offset += csize;
	if (next) *next = offset;
	return ret;

failed:
	ERROR("Failed to read metadata block @0x%llx\n", start);
	return ret;
}
Exemple #3
0
int read_uids_guids_4()
{
	int res, i, indexes = SQUASHFS_ID_BLOCKS(sBlk.s.no_ids);
	long long id_index_table[indexes];

	TRACE("read_uids_guids: no_ids %d\n", sBlk.s.no_ids);

	id_table = malloc(SQUASHFS_ID_BYTES(sBlk.s.no_ids));
	if(id_table == NULL) {
		ERROR("read_uids_guids: failed to allocate id table\n");
		return FALSE;
	}

	res = read_fs_bytes(fd, sBlk.s.id_table_start,
		SQUASHFS_ID_BLOCK_BYTES(sBlk.s.no_ids), id_index_table);
	if(res == FALSE) {
		ERROR("read_uids_guids: failed to read id index table\n");
		return FALSE;
	}
	SQUASHFS_INSWAP_ID_BLOCKS(id_index_table, indexes);

	for(i = 0; i < indexes; i++) {
		res = read_block(fd, id_index_table[i], NULL,
			((char *) id_table) + i * SQUASHFS_METADATA_SIZE);
		if(res == FALSE) {
			ERROR("read_uids_guids: failed to read id table block"
				"\n");
			return FALSE;
		}
	}

	SQUASHFS_INSWAP_INTS(id_table, sBlk.s.no_ids);

	return TRUE;
}
Exemple #4
0
int read_fragment_table(int fd, struct squashfs_super_block *sBlk,
	struct squashfs_fragment_entry **fragment_table)
{
	int res, i;
	int bytes = SQUASHFS_FRAGMENT_BYTES(sBlk->fragments);
	int indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments);
	long long fragment_table_index[indexes];

	TRACE("read_fragment_table: %d fragments, reading %d fragment indexes "
		"from 0x%llx\n", sBlk->fragments, indexes,
		sBlk->fragment_table_start);

	if(sBlk->fragments == 0)
		return 1;

	*fragment_table = malloc(bytes);
	if(*fragment_table == NULL)
		MEM_ERROR();

	res = read_fs_bytes(fd, sBlk->fragment_table_start,
		SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments),
		fragment_table_index);
	if(res == 0) {
		ERROR("Failed to read fragment table index\n");
		ERROR("Filesystem corrupted?\n");
		free(*fragment_table);
		return 0;
	}

	SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes);

	for(i = 0; i < indexes; i++) {
		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
					bytes & (SQUASHFS_METADATA_SIZE - 1);
		int length = read_block(fd, fragment_table_index[i], NULL,
			expected, ((unsigned char *) *fragment_table) +
			(i * SQUASHFS_METADATA_SIZE));
		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
			i, fragment_table_index[i], length);
		if(length == 0) {
			ERROR("Failed to read fragment table block %d, from "
				"0x%llx, length %d\n", i,
				fragment_table_index[i], length);
			ERROR("Filesystem corrupted?\n");
			free(*fragment_table);
			return 0;
		}
	}

	for(i = 0; i < sBlk->fragments; i++)
		SQUASHFS_INSWAP_FRAGMENT_ENTRY(&(*fragment_table)[i]);

	return 1;
}
Exemple #5
0
int read_uids_guids_1()
{
	int res;

	TRACE("read_uids_guids: no_uids %d, no_guids %d\n", sBlk.no_uids,
		sBlk.no_guids);

	uid_table = malloc((sBlk.no_uids + sBlk.no_guids) *
		sizeof(unsigned int));
	if(uid_table == NULL) {
		ERROR("read_uids_guids: failed to allocate uid/gid table\n");
		return FALSE;
	}

	guid_table = uid_table + sBlk.no_uids;

	if(swap) {
		unsigned int suid_table[sBlk.no_uids + sBlk.no_guids];

		res = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids +
			sBlk.no_guids) * sizeof(unsigned int), suid_table);
		if(res == FALSE) {
			ERROR("read_uids_guids: failed to read uid/gid table"
				"\n");
			return FALSE;
		}
		SQUASHFS_SWAP_INTS_3(uid_table, suid_table,
			sBlk.no_uids + sBlk.no_guids);
	} else {
		res = read_fs_bytes(fd, sBlk.uid_start, (sBlk.no_uids +
			sBlk.no_guids) * sizeof(unsigned int), uid_table);
		if(res == FALSE) {
			ERROR("read_uids_guids: failed to read uid/gid table"
				"\n");
			return FALSE;
		}
	}

	return TRUE;
}
Exemple #6
0
int read_fragment_table_4(long long *directory_table_end)
{
	int res, i;
	int bytes = SQUASHFS_FRAGMENT_BYTES(sBlk.s.fragments);
	int  indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.s.fragments);
	long long fragment_table_index[indexes];

	TRACE("read_fragment_table: %d fragments, reading %d fragment indexes "
		"from 0x%llx\n", sBlk.s.fragments, indexes,
		sBlk.s.fragment_table_start);

	if(sBlk.s.fragments == 0) {
		*directory_table_end = sBlk.s.fragment_table_start;
		return TRUE;
	}

	fragment_table = malloc(bytes);
	if(fragment_table == NULL)
		EXIT_UNSQUASH("read_fragment_table: failed to allocate "
			"fragment table\n");

	res = read_fs_bytes(fd, sBlk.s.fragment_table_start,
		SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.s.fragments),
		fragment_table_index);
	if(res == FALSE) {
		ERROR("read_fragment_table: failed to read fragment table "
			"index\n");
		return FALSE;
	}
	SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes);

	for(i = 0; i < indexes; i++) {
		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
					bytes & (SQUASHFS_METADATA_SIZE - 1);
		int length = read_block(fd, fragment_table_index[i], NULL,
			expected, ((char *) fragment_table) + (i *
			SQUASHFS_METADATA_SIZE));
		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
			i, fragment_table_index[i], length);
		if(length == FALSE) {
			ERROR("read_fragment_table: failed to read fragment "
				"table index\n");
			return FALSE;
		}
	}

	for(i = 0; i < sBlk.s.fragments; i++) 
		SQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]);

	*directory_table_end = fragment_table_index[0];
	return TRUE;
}
Exemple #7
0
unsigned int *read_id_table(int fd, struct squashfs_super_block *sBlk)
{
	int indexes = SQUASHFS_ID_BLOCKS(sBlk->no_ids);
	long long index[indexes];
	int bytes = SQUASHFS_ID_BYTES(sBlk->no_ids);
	unsigned int *id_table;
	int res, i;

	id_table = malloc(bytes);
	if(id_table == NULL)
		MEM_ERROR();

	res = read_fs_bytes(fd, sBlk->id_table_start,
		SQUASHFS_ID_BLOCK_BYTES(sBlk->no_ids), index);
	if(res == 0) {
		ERROR("Failed to read id table index\n");
		ERROR("Filesystem corrupted?\n");
		free(id_table);
		return NULL;
	}

	SQUASHFS_INSWAP_ID_BLOCKS(index, indexes);

	for(i = 0; i < indexes; i++) {
		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
					bytes & (SQUASHFS_METADATA_SIZE - 1);
		int length = read_block(fd, index[i], NULL, expected,
			((unsigned char *) id_table) +
			(i * SQUASHFS_METADATA_SIZE));
		TRACE("Read id table block %d, from 0x%llx, length %d\n", i,
			index[i], length);
		if(length == 0) {
			ERROR("Failed to read id table block %d, from 0x%llx, "
				"length %d\n", i, index[i], length);
			ERROR("Filesystem corrupted?\n");
			free(id_table);
			return NULL;
		}
	}

	SQUASHFS_INSWAP_INTS(id_table, sBlk->no_ids);

	for(i = 0; i < sBlk->no_ids; i++) {
		TRACE("Adding id %d to id tables\n", id_table[i]);
		create_id(id_table[i]);
	}

	return id_table;
}
Exemple #8
0
int read_inode_lookup_table(int fd, struct squashfs_super_block *sBlk,
	squashfs_inode **inode_lookup_table)
{
	int lookup_bytes = SQUASHFS_LOOKUP_BYTES(sBlk->inodes);
	int indexes = SQUASHFS_LOOKUP_BLOCKS(sBlk->inodes);
	long long index[indexes];
	int res, i;

	if(sBlk->lookup_table_start == SQUASHFS_INVALID_BLK)
		return 1;

	*inode_lookup_table = malloc(lookup_bytes);
	if(*inode_lookup_table == NULL)
		MEM_ERROR();

	res = read_fs_bytes(fd, sBlk->lookup_table_start,
		SQUASHFS_LOOKUP_BLOCK_BYTES(sBlk->inodes), index);
	if(res == 0) {
		ERROR("Failed to read inode lookup table index\n");
		ERROR("Filesystem corrupted?\n");
		free(*inode_lookup_table);
		return 0;
	}

	SQUASHFS_INSWAP_LONG_LONGS(index, indexes);

	for(i = 0; i <  indexes; i++) {
		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE :
				lookup_bytes & (SQUASHFS_METADATA_SIZE - 1);
		int length = read_block(fd, index[i], NULL, expected,
			((unsigned char *) *inode_lookup_table) +
			(i * SQUASHFS_METADATA_SIZE));
		TRACE("Read inode lookup table block %d, from 0x%llx, length "
			"%d\n", i, index[i], length);
		if(length == 0) {
			ERROR("Failed to read inode lookup table block %d, "
				"from 0x%llx, length %d\n", i, index[i],
				length);
			ERROR("Filesystem corrupted?\n");
			free(*inode_lookup_table);
			return 0;
		}
	}

	SQUASHFS_INSWAP_LONG_LONGS(*inode_lookup_table, sBlk->inodes);

	return 1;
}
Exemple #9
0
static int read_uncompressed(const struct PkgData *pdata,
		const long long offset, const size_t csize,
		void *buf, const size_t buf_size)
{
	if (csize > buf_size) {
		ERROR("Refusing to load oversized uncompressed block\n");
		return -EIO;
	}

	int err = read_fs_bytes(pdata->fd, offset, buf, csize);
	if (err < 0) {
		return err;
	}

	return (int) csize;
}
Exemple #10
0
static int read_compressed(const struct PkgData *pdata,
		const long long offset, const size_t csize,
		void *buf, const size_t buf_size)
{
	if (csize >= buf_size) {
		// In the case compression doesn't make a block smaller,
		// mksquashfs will store the block uncompressed.
		ERROR("Refusing to load too-large compressed block\n");
		return -EIO;
	}

	// Load compressed data into temporary buffer.
	char tmp[csize];
	int err = read_fs_bytes(pdata->fd, offset, tmp, csize);
	if (err < 0) {
		return err;
	}

#if USE_GZIP
	if (pdata->sBlk.compression == ZLIB_COMPRESSION) {
		unsigned long bytes_zlib = buf_size;
		int error = uncompress(buf, &bytes_zlib, (const Bytef *) tmp, csize);
		if (error == Z_OK) {
			return (int) bytes_zlib;
		}

		ERROR("GZIP uncompress failed with error code %d\n", error);
		return -EIO;
	}
#endif
#if USE_LZO
	if (pdata->sBlk.compression == LZO_COMPRESSION) {
		lzo_uint bytes_lzo = buf_size;
		int error = lzo1x_decompress_safe((const lzo_bytep) tmp, csize, buf, &bytes_lzo, NULL);
		if (error == LZO_E_OK) {
			return (int) bytes_lzo;
		}

		ERROR("LZO uncompress failed with error code %d\n", error);
		return -EIO;
	}
#endif

	ERROR("Unsupported compression algorithm (id: %hu)\n",
				pdata->sBlk.compression);
	return -EINVAL;
}
Exemple #11
0
int read_fragment_table_4()
{
	int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES(sBlk.s.fragments);
	long long fragment_table_index[indexes];

	TRACE("read_fragment_table: %d fragments, reading %d fragment indexes "
		"from 0x%llx\n", sBlk.s.fragments, indexes,
		sBlk.s.fragment_table_start);

	if(sBlk.s.fragments == 0)
		return TRUE;

	fragment_table = malloc(sBlk.s.fragments *
		sizeof(struct squashfs_fragment_entry));
	if(fragment_table == NULL)
		EXIT_UNSQUASH("read_fragment_table: failed to allocate "
			"fragment table\n");

	res = read_fs_bytes(fd, sBlk.s.fragment_table_start,
		SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk.s.fragments),
		fragment_table_index);
	if(res == FALSE) {
		ERROR("read_fragment_table: failed to read fragment table "
			"index\n");
		return FALSE;
	}
	SQUASHFS_INSWAP_FRAGMENT_INDEXES(fragment_table_index, indexes);

	for(i = 0; i < indexes; i++) {
		int length = read_block(fd, fragment_table_index[i], NULL,
			((char *) fragment_table) + (i *
			SQUASHFS_METADATA_SIZE));
		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
			i, fragment_table_index[i], length);
		if(length == FALSE) {
			ERROR("read_fragment_table: failed to read fragment "
				"table index\n");
			return FALSE;
		}
	}

	for(i = 0; i < sBlk.s.fragments; i++) 
		SQUASHFS_INSWAP_FRAGMENT_ENTRY(&fragment_table[i]);

	return TRUE;
}
Exemple #12
0
long long read_filesystem(char *root_name, int fd, struct squashfs_super_block *sBlk,
	char **cinode_table, char **data_cache, char **cdirectory_table,
	char **directory_data_cache, unsigned int *last_directory_block,
	unsigned int *inode_dir_offset, unsigned int *inode_dir_file_size,
	unsigned int *root_inode_size, unsigned int *inode_dir_start_block,
	int *file_count, int *sym_count, int *dev_count, int *dir_count,
	int *fifo_count, int *sock_count, long long *uncompressed_file,
	unsigned int *uncompressed_inode, unsigned int *uncompressed_directory,
	unsigned int *inode_dir_inode_number,
	unsigned int *inode_dir_parent_inode,
	void (push_directory_entry)(char *, squashfs_inode, int, int),
	struct squashfs_fragment_entry **fragment_table,
	squashfs_inode **inode_lookup_table)
{
	unsigned char *inode_table = NULL, *directory_table = NULL;
	long long start = sBlk->inode_table_start;
	long long end = sBlk->directory_table_start;
	long long root_inode_start = start +
		SQUASHFS_INODE_BLK(sBlk->root_inode);
	unsigned int root_inode_offset =
		SQUASHFS_INODE_OFFSET(sBlk->root_inode);
	unsigned int root_inode_block;
	union squashfs_inode_header inode;
	unsigned int *id_table = NULL;
	int res;

	printf("Scanning existing filesystem...\n");

	if(get_xattrs(fd, sBlk) == 0)
		goto error;

	if(read_fragment_table(fd, sBlk, fragment_table) == 0)
		goto error;

	if(read_inode_lookup_table(fd, sBlk, inode_lookup_table) == 0)
		goto error;

	id_table = read_id_table(fd, sBlk);
	if(id_table == NULL)
		goto error;

	res = scan_inode_table(fd, start, end, root_inode_start,
		root_inode_offset, sBlk, &inode, &inode_table,
		&root_inode_block, root_inode_size, uncompressed_file,
		uncompressed_directory, file_count, sym_count, dev_count,
		dir_count, fifo_count, sock_count, id_table);
	if(res == 0)
		goto error;

	*uncompressed_inode = root_inode_block;

	if(inode.base.inode_type == SQUASHFS_DIR_TYPE ||
			inode.base.inode_type == SQUASHFS_LDIR_TYPE) {
		if(inode.base.inode_type == SQUASHFS_DIR_TYPE) {
			*inode_dir_start_block = inode.dir.start_block;
			*inode_dir_offset = inode.dir.offset;
			*inode_dir_file_size = inode.dir.file_size - 3;
			*inode_dir_inode_number = inode.dir.inode_number;
			*inode_dir_parent_inode = inode.dir.parent_inode;
		} else {
			*inode_dir_start_block = inode.ldir.start_block;
			*inode_dir_offset = inode.ldir.offset;
			*inode_dir_file_size = inode.ldir.file_size - 3;
			*inode_dir_inode_number = inode.ldir.inode_number;
			*inode_dir_parent_inode = inode.ldir.parent_inode;
		}

		directory_table = squashfs_readdir(fd, !root_name,
			*inode_dir_start_block, *inode_dir_offset,
			*inode_dir_file_size, last_directory_block, sBlk,
			push_directory_entry);
		if(directory_table == NULL) 
			goto error;

		root_inode_start -= start;
		*cinode_table = malloc(root_inode_start);
		if(*cinode_table == NULL)
			MEM_ERROR();

	       	res = read_fs_bytes(fd, start, root_inode_start, *cinode_table);
		if(res == 0) {
			ERROR("Failed to read inode table\n");
			ERROR("Filesystem corrupted?\n");
			goto error;
		}

		*cdirectory_table = malloc(*last_directory_block);
		if(*cdirectory_table == NULL)
			MEM_ERROR();

		res = read_fs_bytes(fd, sBlk->directory_table_start,
			*last_directory_block, *cdirectory_table);
		if(res == 0) {
			ERROR("Failed to read directory table\n");
			ERROR("Filesystem corrupted?\n");
			goto error;
		}

		*data_cache = malloc(root_inode_offset + *root_inode_size);
		if(*data_cache == NULL)
			MEM_ERROR();

		memcpy(*data_cache, inode_table + root_inode_block,
			root_inode_offset + *root_inode_size);

		*directory_data_cache = malloc(*inode_dir_offset +
			*inode_dir_file_size);
		if(*directory_data_cache == NULL)
			MEM_ERROR();

		memcpy(*directory_data_cache, directory_table,
			*inode_dir_offset + *inode_dir_file_size);

		free(id_table);
		free(inode_table);
		free(directory_table);
		return sBlk->inode_table_start;
	}

error:
	free(id_table);
	free(inode_table);
	free(directory_table);
	return 0;
}
Exemple #13
0
struct compressor *read_super(int fd, struct squashfs_super_block *sBlk, char *source)
{
	int res, bytes = 0;
	char buffer[SQUASHFS_METADATA_SIZE] __attribute__ ((aligned));

	res = read_fs_bytes(fd, SQUASHFS_START, sizeof(struct squashfs_super_block),
		sBlk);
	if(res == 0) {
		ERROR("Can't find a SQUASHFS superblock on %s\n",
				source);
		ERROR("Wrong filesystem or filesystem is corrupted!\n");
		goto failed_mount;
	}

	SQUASHFS_INSWAP_SUPER_BLOCK(sBlk);

	if(sBlk->s_magic != SQUASHFS_MAGIC) {
		if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP)
			ERROR("Pre 4.0 big-endian filesystem on %s, appending"
				" to this is unsupported\n", source);
		else {
			ERROR("Can't find a SQUASHFS superblock on %s\n",
				source);
			ERROR("Wrong filesystem or filesystem is corrupted!\n");
		}
		goto failed_mount;
	}

	/* Check the MAJOR & MINOR versions */
	if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
		if(sBlk->s_major < 4)
			ERROR("Filesystem on %s is a SQUASHFS %d.%d filesystem."
				"  Appending\nto SQUASHFS %d.%d filesystems is "
				"not supported.  Please convert it to a "
				"SQUASHFS 4 filesystem\n", source,
				sBlk->s_major,
				sBlk->s_minor, sBlk->s_major, sBlk->s_minor);
		else
			ERROR("Filesystem on %s is %d.%d, which is a later "
				"filesystem version than I support\n",
				source, sBlk->s_major, sBlk->s_minor);
		goto failed_mount;
	}

	/* Check the compression type */
	comp = lookup_compressor_id(sBlk->compression);
	if(!comp->supported) {
		ERROR("Filesystem on %s uses %s compression, this is "
			"unsupported by this version\n", source, comp->name);
		ERROR("Compressors available:\n");
		display_compressors("", "");
		goto failed_mount;
	}

	/*
	 * Read extended superblock information from disk.
	 *
	 * Read compressor specific options from disk if present, and pass
	 * to compressor to set compressor options.
	 *
	 * Note, if there's no compressor options present, the compressor
	 * is still called to set the default options (the defaults may have
	 * been changed by the user specifying options on the command
	 * line which need to be over-ridden).
	 *
	 * Compressor_extract_options is also used to ensure that 
	 * we know how decompress a filesystem compressed with these
	 * compression options.
	 */
	if(SQUASHFS_COMP_OPTS(sBlk->flags)) {
		bytes = read_block(fd, sizeof(*sBlk), NULL, 0, buffer);

		if(bytes == 0) {
			ERROR("Failed to read compressor options from append "
				"filesystem\n");
			ERROR("Filesystem corrupted?\n");
			goto failed_mount;
		}
	}

	res = compressor_extract_options(comp, sBlk->block_size, buffer, bytes);
	if(res == -1) {
		ERROR("Compressor failed to set compressor options\n");
		goto failed_mount;
	}

	printf("Found a valid %sSQUASHFS superblock on %s.\n",
		SQUASHFS_EXPORTABLE(sBlk->flags) ? "exportable " : "", source);
	printf("\tCompression used %s\n", comp->name);
	printf("\tInodes are %scompressed\n",
		SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
	printf("\tData is %scompressed\n",
		SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : "");
	printf("\tFragments are %scompressed\n",
		SQUASHFS_UNCOMPRESSED_FRAGMENTS(sBlk->flags) ? "un" : "");
	printf("\tXattrs are %scompressed\n",
		SQUASHFS_UNCOMPRESSED_XATTRS(sBlk->flags) ? "un" : "");
	printf("\tFragments are %spresent in the filesystem\n",
		SQUASHFS_NO_FRAGMENTS(sBlk->flags) ? "not " : "");
	printf("\tAlways-use-fragments option is %sspecified\n",
		SQUASHFS_ALWAYS_FRAGMENTS(sBlk->flags) ? "" : "not ");
	printf("\tDuplicates are %sremoved\n",
		SQUASHFS_DUPLICATES(sBlk->flags) ? "" : "not ");
	printf("\tXattrs are %sstored\n",
		SQUASHFS_NO_XATTRS(sBlk->flags) ? "not " : "");
	printf("\tFilesystem size %.2f Kbytes (%.2f Mbytes)\n",
		sBlk->bytes_used / 1024.0, sBlk->bytes_used
		/ (1024.0 * 1024.0));
	printf("\tBlock size %d\n", sBlk->block_size);
	printf("\tNumber of fragments %d\n", sBlk->fragments);
	printf("\tNumber of inodes %d\n", sBlk->inodes);
	printf("\tNumber of ids %d\n", sBlk->no_ids);
	TRACE("sBlk->inode_table_start %llx\n", sBlk->inode_table_start);
	TRACE("sBlk->directory_table_start %llx\n",
		sBlk->directory_table_start);
	TRACE("sBlk->id_table_start %llx\n", sBlk->id_table_start);
	TRACE("sBlk->fragment_table_start %llx\n", sBlk->fragment_table_start);
	TRACE("sBlk->lookup_table_start %llx\n", sBlk->lookup_table_start);
	TRACE("sBlk->xattr_id_table_start %llx\n", sBlk->xattr_id_table_start);
	printf("\n");

	return comp;

failed_mount:
	return NULL;
}
Exemple #14
0
/*
 * Read and decompress the xattr id table and the xattr metadata.
 * This is cached in memory for later use by get_xattr()
 */
int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk) {
	int res, bytes, i, indexes, index_bytes, ids;
	long long *index, start, end;
	struct squashfs_xattr_table id_table;

	TRACE("read_xattrs_from_disk\n");

	if (sBlk->xattr_id_table_start == SQUASHFS_INVALID_BLK)
		return SQUASHFS_INVALID_BLK;

	/*
	 * Read xattr id table, containing start of xattr metadata and the
	 * number of xattrs in the file system
	 */
	res = read_fs_bytes(fd, sBlk->xattr_id_table_start, sizeof(id_table), &id_table);
	if (res == 0)
		return 0;

	SQUASHFS_INSWAP_XATTR_TABLE(&id_table);

	/*
	 * Allocate and read the index to the xattr id table metadata
	 * blocks
	 */
	ids = id_table.xattr_ids;
	xattr_table_start = id_table.xattr_table_start;
	index_bytes = SQUASHFS_XATTR_BLOCK_BYTES(ids);
	indexes = SQUASHFS_XATTR_BLOCKS(ids);
	index = malloc(index_bytes);
	if (index == NULL)
		MEM_ERROR();

	res = read_fs_bytes(fd, sBlk->xattr_id_table_start + sizeof(id_table), index_bytes, index);
	if (res == 0)
		goto failed1;

	SQUASHFS_INSWAP_LONG_LONGS(index, indexes);

	/*
	 * Allocate enough space for the uncompressed xattr id table, and
	 * read and decompress it
	 */
	bytes = SQUASHFS_XATTR_BYTES(ids);
	xattr_ids = malloc(bytes);
	if (xattr_ids == NULL)
		MEM_ERROR();

	for (i = 0; i < indexes; i++) {
		int expected = (i + 1) != indexes ? SQUASHFS_METADATA_SIZE : bytes & (SQUASHFS_METADATA_SIZE - 1);
		int length = read_block(fd, index[i], NULL, expected,
								((unsigned char *)xattr_ids) + (i * SQUASHFS_METADATA_SIZE));
		TRACE("Read xattr id table block %d, from 0x%llx, length " "%d\n", i, index[i], length);
		if (length == 0) {
			ERROR("Failed to read xattr id table block %d, " "from 0x%llx, length %d\n", i, index[i], length);
			goto failed2;
		}
	}

	/*
	 * Read and decompress the xattr metadata
	 *
	 * Note the first xattr id table metadata block is immediately after
	 * the last xattr metadata block, so we can use index[0] to work out
	 * the end of the xattr metadata
	 */
	start = xattr_table_start;
	end = index[0];
	for (i = 0; start < end; i++) {
		int length;
		xattrs = realloc(xattrs, (i + 1) * SQUASHFS_METADATA_SIZE);
		if (xattrs == NULL)
			MEM_ERROR();

		/* store mapping from location of compressed block in fs ->
		 * location of uncompressed block in memory */
		save_xattr_block(start, i * SQUASHFS_METADATA_SIZE);

		length = read_block(fd, start, &start, 0, ((unsigned char *)xattrs) + (i * SQUASHFS_METADATA_SIZE));
		TRACE("Read xattr block %d, length %d\n", i, length);
		if (length == 0) {
			ERROR("Failed to read xattr block %d\n", i);
			goto failed3;
		}

		/*
		 * If this is not the last metadata block in the xattr metadata
		 * then it should be SQUASHFS_METADATA_SIZE in size.
		 * Note, we can't use expected in read_block() above for this
		 * because we don't know if this is the last block until
		 * after reading.
		 */
		if (start != end && length != SQUASHFS_METADATA_SIZE) {
			ERROR("Xattr block %d should be %d bytes in length, " "it is %d bytes\n", i, SQUASHFS_METADATA_SIZE, length);
			goto failed3;
		}
	}

	/* swap if necessary the xattr id entries */
	for (i = 0; i < ids; i++)
		SQUASHFS_INSWAP_XATTR_ID(&xattr_ids[i]);

	free(index);

	return ids;

 failed3:
	free(xattrs);
 failed2:
	free(xattr_ids);
 failed1:
	free(index);

	return 0;
}
Exemple #15
0
int read_fragment_table_3()
{
	int res, i, indexes = SQUASHFS_FRAGMENT_INDEXES_3(sBlk.s.fragments);
	squashfs_fragment_index fragment_table_index[indexes];

	TRACE("read_fragment_table: %d fragments, reading %d fragment indexes "
		"from 0x%llx\n", sBlk.s.fragments, indexes,
		sBlk.s.fragment_table_start);

	if(sBlk.s.fragments == 0)
		return TRUE;

	if((fragment_table = malloc(sBlk.s.fragments *
			sizeof(squashfs_fragment_entry_3))) == NULL)
		EXIT_UNSQUASH("read_fragment_table: failed to allocate "
			"fragment table\n");

	if(swap) {
		squashfs_fragment_index sfragment_table_index[indexes];

		res = read_fs_bytes(fd, sBlk.s.fragment_table_start,
			SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments),
			sfragment_table_index);
		if(res == FALSE) {
			ERROR("read_fragment_table: failed to read fragment "
				"table index\n");       
			return FALSE;
		}
		SQUASHFS_SWAP_FRAGMENT_INDEXES_3(fragment_table_index,
			sfragment_table_index, indexes);
	} else {
		res = read_fs_bytes(fd, sBlk.s.fragment_table_start,
			SQUASHFS_FRAGMENT_INDEX_BYTES_3(sBlk.s.fragments),
			fragment_table_index);
		if(res == FALSE) {
			ERROR("read_fragment_table: failed to read fragment "
				"table index\n");       
			return FALSE;
		}
	}

	for(i = 0; i < indexes; i++) {
		int length = read_block(fd, fragment_table_index[i], NULL,
			((char *) fragment_table) + (i *
			SQUASHFS_METADATA_SIZE));
		TRACE("Read fragment table block %d, from 0x%llx, length %d\n",
			i, fragment_table_index[i], length);
		if(length == FALSE) {
			ERROR("read_fragment_table: failed to read fragment "
				"table block\n");       
			return FALSE;
		}
	}

	if(swap) {
		squashfs_fragment_entry_3 sfragment;
		for(i = 0; i < sBlk.s.fragments; i++) {
			SQUASHFS_SWAP_FRAGMENT_ENTRY_3((&sfragment),
				(&fragment_table[i]));
			memcpy((char *) &fragment_table[i], (char *) &sfragment,
				sizeof(squashfs_fragment_entry_3));
		}
	}

	return TRUE;
}
Exemple #16
0
/*
 * Read and decompress the xattr id table and the xattr metadata.
 * This is cached in memory for later use by get_xattr()
 */
int read_xattrs_from_disk(int fd, struct squashfs_super_block *sBlk)
{
	int res, bytes, i, indexes, index_bytes, ids;
	long long *index, start, end;
	struct squashfs_xattr_table id_table;

	TRACE("read_xattrs_from_disk\n");

	if(sBlk->xattr_id_table_start == SQUASHFS_INVALID_BLK)
		return SQUASHFS_INVALID_BLK;

	/*
	 * Read xattr id table, containing start of xattr metadata and the
	 * number of xattrs in the file system
	 */
	res = read_fs_bytes(fd, sBlk->xattr_id_table_start, sizeof(id_table),
		&id_table);
	if(res == 0)
		return 0;

	SQUASHFS_INSWAP_XATTR_TABLE(&id_table);

	/*
	 * Allocate and read the index to the xattr id table metadata
	 * blocks
	 */
	ids = id_table.xattr_ids;
	xattr_table_start = id_table.xattr_table_start;
	index_bytes = SQUASHFS_XATTR_BLOCK_BYTES(ids);
	indexes = SQUASHFS_XATTR_BLOCKS(ids);
	index = malloc(index_bytes);
	if(index == NULL) {
		ERROR("Failed to allocate index array\n");
		return 0;
	}

	res = read_fs_bytes(fd, sBlk->xattr_id_table_start + sizeof(id_table),
		index_bytes, index);
	if(res ==0)
		goto failed1;

	SQUASHFS_INSWAP_LONG_LONGS(index, indexes);

	/*
	 * Allocate enough space for the uncompressed xattr id table, and
	 * read and decompress it
	 */
	bytes = SQUASHFS_XATTR_BYTES(ids);
	xattr_ids = malloc(bytes);
	if(xattr_ids == NULL) {
		ERROR("Failed to allocate xattr id table\n");
		goto failed1;
	}

	for(i = 0; i < indexes; i++) {
		int length = read_block(fd, index[i], NULL,
			((unsigned char *) xattr_ids) +
			(i * SQUASHFS_METADATA_SIZE));
		TRACE("Read xattr id table block %d, from 0x%llx, length "
			"%d\n", i, index[i], length);
		if(length == 0) {
			ERROR("Failed to read xattr id table block %d, "
				"from 0x%llx, length %d\n", i, index[i],
				length);
			goto failed2;
		}
	}

	/*
	 * Read and decompress the xattr metadata
	 *
	 * Note the first xattr id table metadata block is immediately after
	 * the last xattr metadata block, so we can use index[0] to work out
	 * the end of the xattr metadata
	 */
	start = xattr_table_start;
	end = index[0];
	for(i = 0; start < end; i++) {
		int length;
		void *x = realloc(xattrs, (i + 1) * SQUASHFS_METADATA_SIZE);
		if(x == NULL) {
			ERROR("Failed to realloc xattr data\n");
			goto failed3;
		}
		xattrs = x;

		/* store mapping from location of compressed block in fs ->
		 * location of uncompressed block in memory */
		res = save_xattr_block(start, i * SQUASHFS_METADATA_SIZE);
		if(res == -1)
			goto failed3;

		length = read_block(fd, start, &start,
			((unsigned char *) xattrs) +
			(i * SQUASHFS_METADATA_SIZE));
		TRACE("Read xattr block %d, length %d\n", i, length);
		if(length == 0) {
			ERROR("Failed to read xattr block %d\n", i);
			goto failed3;
		}
	}

	/* swap if necessary the xattr id entries */
	for(i = 0; i < ids; i++)
		SQUASHFS_INSWAP_XATTR_ID(&xattr_ids[i]);

	free(index);

	return ids;

failed3:
	free(xattrs);
failed2:
	free(xattr_ids);
failed1:
	free(index);

	return 0;
}