Exemplo n.º 1
0
unsigned char *squashfs_readdir(int fd, int root_entries, unsigned int directory_start_block, int offset, int size,
		unsigned int *last_directory_block, squashfs_super_block *sBlk, void (push_directory_entry)(char *, squashfs_inode, int, int))
{
	squashfs_dir_header dirh;
	char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
	squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
	unsigned char *directory_table = NULL;
	int byte, bytes = 0, dir_count;
	long long start = sBlk->directory_table_start + directory_start_block, last_start_block = -1;

	size += offset;
	if((directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) & ~(SQUASHFS_METADATA_SIZE - 1))) == NULL)
		return NULL;
	while(bytes < size) {
		TRACE("squashfs_readdir: reading block 0x%llx, bytes read so far %d\n", start, bytes);
		last_start_block = start;
		if((byte = read_block(fd, start, &start, directory_table + bytes, sBlk)) == 0) {
			free(directory_table);
			return NULL;
		}
		bytes += byte;
	}

	if(!root_entries)
		goto all_done;

	bytes = offset;
 	while(bytes < size) {			
		if(swap) {
			squashfs_dir_header sdirh;
			memcpy(&sdirh, directory_table + bytes, sizeof(sdirh));
			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
		} else
			memcpy(&dirh, directory_table + bytes, sizeof(dirh));

		dir_count = dirh.count + 1;
		TRACE("squashfs_readdir: Read directory header @ byte position 0x%x, 0x%x directory entries\n", bytes, dir_count);
		bytes += sizeof(dirh);

		while(dir_count--) {
			if(swap) {
				squashfs_dir_entry sdire;
				memcpy(&sdire, directory_table + bytes, sizeof(sdire));
				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
			} else
				memcpy(dire, directory_table + bytes, sizeof(*dire));
			bytes += sizeof(*dire);

			memcpy(dire->name, directory_table + bytes, dire->size + 1);
			dire->name[dire->size + 1] = '\0';
			TRACE("squashfs_readdir: pushing directory entry %s, inode %x:%x, type 0x%x\n", dire->name, dirh.start_block, dire->offset, dire->type);
			push_directory_entry(dire->name, SQUASHFS_MKINODE(dirh.start_block, dire->offset), dirh.inode_number + dire->inode_number, dire->type);
			bytes += dire->size + 1;
		}
	}

all_done:
	*last_directory_block = (unsigned int) last_start_block - sBlk->directory_table_start;
	return directory_table;
}
Exemplo n.º 2
0
unsigned char *squashfs_readdir(int fd, int root_entries,
	unsigned int directory_start_block, int offset, int size,
	unsigned int *last_directory_block, struct squashfs_super_block *sBlk,
	void (push_directory_entry)(char *, squashfs_inode, int, int))
{
	struct squashfs_dir_header dirh;
	char buffer[sizeof(struct squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1]
		__attribute__ ((aligned));
	struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
	unsigned char *directory_table = NULL;
	int byte, bytes = 0, dir_count;
	long long start = sBlk->directory_table_start + directory_start_block,
		last_start_block = start; 

	size += offset;
	directory_table = malloc((size + SQUASHFS_METADATA_SIZE * 2 - 1) &
		~(SQUASHFS_METADATA_SIZE - 1));
	if(directory_table == NULL)
		MEM_ERROR();

	while(bytes < size) {
		int expected = (size - bytes) >= SQUASHFS_METADATA_SIZE ?
			SQUASHFS_METADATA_SIZE : 0;

		TRACE("squashfs_readdir: reading block 0x%llx, bytes read so "
			"far %d\n", start, bytes);

		last_start_block = start;
		byte = read_block(fd, start, &start, expected, directory_table + bytes);
		if(byte == 0) {
			ERROR("Failed to read directory\n");
			ERROR("Filesystem corrupted?\n");
			free(directory_table);
			return NULL;
		}
		bytes += byte;
	}

	if(!root_entries)
		goto all_done;

	bytes = offset;
 	while(bytes < size) {			
		SQUASHFS_SWAP_DIR_HEADER(directory_table + bytes, &dirh);

		dir_count = dirh.count + 1;
		TRACE("squashfs_readdir: Read directory header @ byte position "
			"0x%x, 0x%x directory entries\n", bytes, dir_count);
		bytes += sizeof(dirh);

		while(dir_count--) {
			SQUASHFS_SWAP_DIR_ENTRY(directory_table + bytes, dire);
			bytes += sizeof(*dire);

			memcpy(dire->name, directory_table + bytes,
				dire->size + 1);
			dire->name[dire->size + 1] = '\0';
			TRACE("squashfs_readdir: pushing directory entry %s, "
				"inode %x:%x, type 0x%x\n", dire->name,
				dirh.start_block, dire->offset, dire->type);
			push_directory_entry(dire->name,
				SQUASHFS_MKINODE(dirh.start_block,
				dire->offset), dirh.inode_number +
				dire->inode_number, dire->type);
			bytes += dire->size + 1;
		}
	}

all_done:
	*last_directory_block = (unsigned int) last_start_block -
		sBlk->directory_table_start;
	return directory_table;
}