Exemple #1
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 #2
0
long long read_filesystem(char *root_name, int fd, 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, squashfs_uid *uids,
		unsigned short *uid_count, squashfs_uid *guids, unsigned short *guid_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), squashfs_fragment_entry **fragment_table,
		squashfs_inode **inode_lookup_table)
{
	unsigned char *inode_table = NULL, *directory_table;
	long long start = sBlk->inode_table_start, end = sBlk->directory_table_start, root_inode_start = start +
		SQUASHFS_INODE_BLK(sBlk->root_inode);
	unsigned int root_inode_offset = SQUASHFS_INODE_OFFSET(sBlk->root_inode), root_inode_block, files;
	squashfs_inode_header inode;

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

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

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

	if((files = 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)) == 0) {
		ERROR("read_filesystem: inode table read failed\n");
		goto error;
	}

	*uncompressed_inode = root_inode_block;

	printf("Read existing filesystem, %d inodes scanned\n", files);

	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;
		}

		if((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)) == NULL) {
			ERROR("read_filesystem: Could not read root directory\n");
			goto error;
		}

		root_inode_start -= start;
		if((*cinode_table = (char *) malloc(root_inode_start)) == NULL) {
			ERROR("read_filesystem: failed to alloc space for existing filesystem inode table\n");
			goto error;
		}
	       	read_bytes(fd, start, root_inode_start, *cinode_table);

		if((*cdirectory_table = (char *) malloc(*last_directory_block)) == NULL) {
			ERROR("read_filesystem: failed to alloc space for existing filesystem directory table\n");
			goto error;
		}
		read_bytes(fd, sBlk->directory_table_start, *last_directory_block, *cdirectory_table);

		if((*data_cache = (char *) malloc(root_inode_offset + *root_inode_size)) == NULL) {
			ERROR("read_filesystem: failed to alloc inode cache\n");
			goto error;
		}
		memcpy(*data_cache, inode_table + root_inode_block, root_inode_offset + *root_inode_size);

		if((*directory_data_cache = (char *) malloc(*inode_dir_offset + *inode_dir_file_size)) == NULL) {
			ERROR("read_filesystem: failed to alloc directory cache\n");
			goto error;
		}
		memcpy(*directory_data_cache, directory_table, *inode_dir_offset + *inode_dir_file_size);

		if(!swap)
			read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids);
		else {
			squashfs_uid uids_copy[sBlk->no_uids];

			read_bytes(fd, sBlk->uid_start, sBlk->no_uids * sizeof(squashfs_uid), (char *) uids_copy);
			SQUASHFS_SWAP_DATA(uids, uids_copy, sBlk->no_uids, sizeof(squashfs_uid) * 8);
		}

		if(!swap)
			read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids);
		else {
			squashfs_uid guids_copy[sBlk->no_guids];

			read_bytes(fd, sBlk->guid_start, sBlk->no_guids * sizeof(squashfs_uid), (char *) guids_copy);
			SQUASHFS_SWAP_DATA(guids, guids_copy, sBlk->no_guids, sizeof(squashfs_uid) * 8);
		}
		*uid_count = sBlk->no_uids;
		*guid_count = sBlk->no_guids;

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

error:
	return 0;
}