1/*
2 * Squashfs - a compressed read only filesystem for Linux
3 *
4 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
5 * Phillip Lougher <phillip@lougher.org.uk>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * squashfs2_0.c
22 */
23
24#include <linux/squashfs_fs.h>
25#include <linux/module.h>
26#include <linux/zlib.h>
27#include <linux/fs.h>
28#include <linux/squashfs_fs_sb.h>
29#include <linux/squashfs_fs_i.h>
30
31#include "squashfs.h"
32static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
33static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
34				struct nameidata *);
35
36static struct file_operations squashfs_dir_ops_2 = {
37	.read = generic_read_dir,
38	.readdir = squashfs_readdir_2
39};
40
41static struct inode_operations squashfs_dir_inode_ops_2 = {
42	.lookup = squashfs_lookup_2
43};
44
45static unsigned char squashfs_filetype_table[] = {
46	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
47};
48
49static int read_fragment_index_table_2(struct super_block *s)
50{
51	struct squashfs_sb_info *msblk = s->s_fs_info;
52	struct squashfs_super_block *sblk = &msblk->sblk;
53
54	if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
55					(sblk->fragments), GFP_KERNEL))) {
56		ERROR("Failed to allocate uid/gid table\n");
57		return 0;
58	}
59
60	if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
61					!squashfs_read_data(s, (char *)
62					msblk->fragment_index_2,
63					sblk->fragment_table_start,
64					SQUASHFS_FRAGMENT_INDEX_BYTES_2
65					(sblk->fragments) |
66					SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
67		ERROR("unable to read fragment index table\n");
68		return 0;
69	}
70
71	if (msblk->swap) {
72		int i;
73		unsigned int fragment;
74
75		for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
76									i++) {
77			SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
78						&msblk->fragment_index_2[i], 1);
79			msblk->fragment_index_2[i] = fragment;
80		}
81	}
82
83	return 1;
84}
85
86
87static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
88				long long *fragment_start_block,
89				unsigned int *fragment_size)
90{
91	struct squashfs_sb_info *msblk = s->s_fs_info;
92	long long start_block =
93		msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
94	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
95	struct squashfs_fragment_entry_2 fragment_entry;
96
97	if (msblk->swap) {
98		struct squashfs_fragment_entry_2 sfragment_entry;
99
100		if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
101					start_block, offset,
102					sizeof(sfragment_entry), &start_block,
103					&offset))
104			goto out;
105		SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
106	} else
107		if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
108					start_block, offset,
109					sizeof(fragment_entry), &start_block,
110					&offset))
111			goto out;
112
113	*fragment_start_block = fragment_entry.start_block;
114	*fragment_size = fragment_entry.size;
115
116	return 1;
117
118out:
119	return 0;
120}
121
122
123static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
124		struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
125{
126	struct squashfs_super_block *sblk = &msblk->sblk;
127
128	i->i_ino = ino;
129	i->i_mtime.tv_sec = sblk->mkfs_time;
130	i->i_atime.tv_sec = sblk->mkfs_time;
131	i->i_ctime.tv_sec = sblk->mkfs_time;
132	i->i_uid = msblk->uid[inodeb->uid];
133	i->i_mode = inodeb->mode;
134	i->i_nlink = 1;
135	i->i_size = 0;
136	if (inodeb->guid == SQUASHFS_GUIDS)
137		i->i_gid = i->i_uid;
138	else
139		i->i_gid = msblk->guid[inodeb->guid];
140}
141
142
143static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
144{
145	struct super_block *s = i->i_sb;
146	struct squashfs_sb_info *msblk = s->s_fs_info;
147	struct squashfs_super_block *sblk = &msblk->sblk;
148	unsigned int block = SQUASHFS_INODE_BLK(inode) +
149		sblk->inode_table_start;
150	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
151	unsigned int ino = i->i_ino;
152	long long next_block;
153	unsigned int next_offset;
154	union squashfs_inode_header_2 id, sid;
155	struct squashfs_base_inode_header_2 *inodeb = &id.base,
156					  *sinodeb = &sid.base;
157
158	TRACE("Entered squashfs_iget\n");
159
160	if (msblk->swap) {
161		if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
162					offset, sizeof(*sinodeb), &next_block,
163					&next_offset))
164			goto failed_read;
165		SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
166					sizeof(*sinodeb));
167	} else
168		if (!squashfs_get_cached_block(s, (char *) inodeb, block,
169					offset, sizeof(*inodeb), &next_block,
170					&next_offset))
171			goto failed_read;
172
173	squashfs_new_inode(msblk, i, inodeb, ino);
174
175	switch(inodeb->inode_type) {
176		case SQUASHFS_FILE_TYPE: {
177			struct squashfs_reg_inode_header_2 *inodep = &id.reg;
178			struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
179			long long frag_blk;
180			unsigned int frag_size = 0;
181
182			if (msblk->swap) {
183				if (!squashfs_get_cached_block(s, (char *)
184						sinodep, block, offset,
185						sizeof(*sinodep), &next_block,
186						&next_offset))
187					goto failed_read;
188				SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
189			} else
190				if (!squashfs_get_cached_block(s, (char *)
191						inodep, block, offset,
192						sizeof(*inodep), &next_block,
193						&next_offset))
194					goto failed_read;
195
196			frag_blk = SQUASHFS_INVALID_BLK;
197			if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
198					!get_fragment_location_2(s,
199					inodep->fragment, &frag_blk, &frag_size))
200				goto failed_read;
201
202			i->i_size = inodep->file_size;
203			i->i_fop = &generic_ro_fops;
204			i->i_mode |= S_IFREG;
205			i->i_mtime.tv_sec = inodep->mtime;
206			i->i_atime.tv_sec = inodep->mtime;
207			i->i_ctime.tv_sec = inodep->mtime;
208			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
209			SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
210			SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
211			SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
212			SQUASHFS_I(i)->start_block = inodep->start_block;
213			SQUASHFS_I(i)->u.s1.block_list_start = next_block;
214			SQUASHFS_I(i)->offset = next_offset;
215			if (sblk->block_size > 4096)
216				i->i_data.a_ops = &squashfs_aops;
217			else
218				i->i_data.a_ops = &squashfs_aops_4K;
219
220			TRACE("File inode %x:%x, start_block %x, "
221					"block_list_start %llx, offset %x\n",
222					SQUASHFS_INODE_BLK(inode), offset,
223					inodep->start_block, next_block,
224					next_offset);
225			break;
226		}
227		case SQUASHFS_DIR_TYPE: {
228			struct squashfs_dir_inode_header_2 *inodep = &id.dir;
229			struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
230
231			if (msblk->swap) {
232				if (!squashfs_get_cached_block(s, (char *)
233						sinodep, block, offset,
234						sizeof(*sinodep), &next_block,
235						&next_offset))
236					goto failed_read;
237				SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
238			} else
239				if (!squashfs_get_cached_block(s, (char *)
240						inodep, block, offset,
241						sizeof(*inodep), &next_block,
242						&next_offset))
243					goto failed_read;
244
245			i->i_size = inodep->file_size;
246			i->i_op = &squashfs_dir_inode_ops_2;
247			i->i_fop = &squashfs_dir_ops_2;
248			i->i_mode |= S_IFDIR;
249			i->i_mtime.tv_sec = inodep->mtime;
250			i->i_atime.tv_sec = inodep->mtime;
251			i->i_ctime.tv_sec = inodep->mtime;
252			SQUASHFS_I(i)->start_block = inodep->start_block;
253			SQUASHFS_I(i)->offset = inodep->offset;
254			SQUASHFS_I(i)->u.s2.directory_index_count = 0;
255			SQUASHFS_I(i)->u.s2.parent_inode = 0;
256
257			TRACE("Directory inode %x:%x, start_block %x, offset "
258					"%x\n", SQUASHFS_INODE_BLK(inode),
259					offset, inodep->start_block,
260					inodep->offset);
261			break;
262		}
263		case SQUASHFS_LDIR_TYPE: {
264			struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
265			struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
266
267			if (msblk->swap) {
268				if (!squashfs_get_cached_block(s, (char *)
269						sinodep, block, offset,
270						sizeof(*sinodep), &next_block,
271						&next_offset))
272					goto failed_read;
273				SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
274						sinodep);
275			} else
276				if (!squashfs_get_cached_block(s, (char *)
277						inodep, block, offset,
278						sizeof(*inodep), &next_block,
279						&next_offset))
280					goto failed_read;
281
282			i->i_size = inodep->file_size;
283			i->i_op = &squashfs_dir_inode_ops_2;
284			i->i_fop = &squashfs_dir_ops_2;
285			i->i_mode |= S_IFDIR;
286			i->i_mtime.tv_sec = inodep->mtime;
287			i->i_atime.tv_sec = inodep->mtime;
288			i->i_ctime.tv_sec = inodep->mtime;
289			SQUASHFS_I(i)->start_block = inodep->start_block;
290			SQUASHFS_I(i)->offset = inodep->offset;
291			SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
292			SQUASHFS_I(i)->u.s2.directory_index_offset =
293								next_offset;
294			SQUASHFS_I(i)->u.s2.directory_index_count =
295								inodep->i_count;
296			SQUASHFS_I(i)->u.s2.parent_inode = 0;
297
298			TRACE("Long directory inode %x:%x, start_block %x, "
299					"offset %x\n",
300					SQUASHFS_INODE_BLK(inode), offset,
301					inodep->start_block, inodep->offset);
302			break;
303		}
304		case SQUASHFS_SYMLINK_TYPE: {
305			struct squashfs_symlink_inode_header_2 *inodep =
306								&id.symlink;
307			struct squashfs_symlink_inode_header_2 *sinodep =
308								&sid.symlink;
309
310			if (msblk->swap) {
311				if (!squashfs_get_cached_block(s, (char *)
312						sinodep, block, offset,
313						sizeof(*sinodep), &next_block,
314						&next_offset))
315					goto failed_read;
316				SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
317								sinodep);
318			} else
319				if (!squashfs_get_cached_block(s, (char *)
320						inodep, block, offset,
321						sizeof(*inodep), &next_block,
322						&next_offset))
323					goto failed_read;
324
325			i->i_size = inodep->symlink_size;
326			i->i_op = &page_symlink_inode_operations;
327			i->i_data.a_ops = &squashfs_symlink_aops;
328			i->i_mode |= S_IFLNK;
329			SQUASHFS_I(i)->start_block = next_block;
330			SQUASHFS_I(i)->offset = next_offset;
331
332			TRACE("Symbolic link inode %x:%x, start_block %llx, "
333					"offset %x\n",
334					SQUASHFS_INODE_BLK(inode), offset,
335					next_block, next_offset);
336			break;
337		 }
338		 case SQUASHFS_BLKDEV_TYPE:
339		 case SQUASHFS_CHRDEV_TYPE: {
340			struct squashfs_dev_inode_header_2 *inodep = &id.dev;
341			struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
342
343			if (msblk->swap) {
344				if (!squashfs_get_cached_block(s, (char *)
345						sinodep, block, offset,
346						sizeof(*sinodep), &next_block,
347						&next_offset))
348					goto failed_read;
349				SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
350			} else
351				if (!squashfs_get_cached_block(s, (char *)
352						inodep, block, offset,
353						sizeof(*inodep), &next_block,
354						&next_offset))
355					goto failed_read;
356
357			i->i_mode |= (inodeb->inode_type ==
358					SQUASHFS_CHRDEV_TYPE) ?  S_IFCHR :
359					S_IFBLK;
360			init_special_inode(i, i->i_mode,
361					old_decode_dev(inodep->rdev));
362
363			TRACE("Device inode %x:%x, rdev %x\n",
364					SQUASHFS_INODE_BLK(inode), offset,
365					inodep->rdev);
366			break;
367		 }
368		 case SQUASHFS_FIFO_TYPE:
369		 case SQUASHFS_SOCKET_TYPE: {
370
371			i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
372							? S_IFIFO : S_IFSOCK;
373			init_special_inode(i, i->i_mode, 0);
374			break;
375		 }
376		 default:
377			ERROR("Unknown inode type %d in squashfs_iget!\n",
378					inodeb->inode_type);
379			goto failed_read1;
380	}
381
382	return 1;
383
384failed_read:
385	ERROR("Unable to read inode [%x:%x]\n", block, offset);
386
387failed_read1:
388	return 0;
389}
390
391
392static int get_dir_index_using_offset(struct super_block *s, long long
393				*next_block, unsigned int *next_offset,
394				long long index_start,
395				unsigned int index_offset, int i_count,
396				long long f_pos)
397{
398	struct squashfs_sb_info *msblk = s->s_fs_info;
399	struct squashfs_super_block *sblk = &msblk->sblk;
400	int i, length = 0;
401	struct squashfs_dir_index_2 index;
402
403	TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
404					i_count, (unsigned int) f_pos);
405
406	if (f_pos == 0)
407		goto finish;
408
409	for (i = 0; i < i_count; i++) {
410		if (msblk->swap) {
411			struct squashfs_dir_index_2 sindex;
412			squashfs_get_cached_block(s, (char *) &sindex,
413					index_start, index_offset,
414					sizeof(sindex), &index_start,
415					&index_offset);
416			SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
417		} else
418			squashfs_get_cached_block(s, (char *) &index,
419					index_start, index_offset,
420					sizeof(index), &index_start,
421					&index_offset);
422
423		if (index.index > f_pos)
424			break;
425
426		squashfs_get_cached_block(s, NULL, index_start, index_offset,
427					index.size + 1, &index_start,
428					&index_offset);
429
430		length = index.index;
431		*next_block = index.start_block + sblk->directory_table_start;
432	}
433
434	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
435
436finish:
437	return length;
438}
439
440
441static int get_dir_index_using_name(struct super_block *s, long long
442				*next_block, unsigned int *next_offset,
443				long long index_start,
444				unsigned int index_offset, int i_count,
445				const char *name, int size)
446{
447	struct squashfs_sb_info *msblk = s->s_fs_info;
448	struct squashfs_super_block *sblk = &msblk->sblk;
449	int i, length = 0;
450	struct squashfs_dir_index_2 *index;
451	char *str;
452
453	TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
454
455	if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
456		(SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
457		ERROR("Failed to allocate squashfs_dir_index\n");
458		goto failure;
459	}
460
461	index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
462	strncpy(str, name, size);
463	str[size] = '\0';
464
465	for (i = 0; i < i_count; i++) {
466		if (msblk->swap) {
467			struct squashfs_dir_index_2 sindex;
468			squashfs_get_cached_block(s, (char *) &sindex,
469					index_start, index_offset,
470					sizeof(sindex), &index_start,
471					&index_offset);
472			SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
473		} else
474			squashfs_get_cached_block(s, (char *) index,
475					index_start, index_offset,
476					sizeof(struct squashfs_dir_index_2),
477					&index_start, &index_offset);
478
479		squashfs_get_cached_block(s, index->name, index_start,
480					index_offset, index->size + 1,
481					&index_start, &index_offset);
482
483		index->name[index->size + 1] = '\0';
484
485		if (strcmp(index->name, str) > 0)
486			break;
487
488		length = index->index;
489		*next_block = index->start_block + sblk->directory_table_start;
490	}
491
492	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
493	kfree(str);
494failure:
495	return length;
496}
497
498
499static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
500{
501	struct inode *i = file->f_dentry->d_inode;
502	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
503	struct squashfs_super_block *sblk = &msblk->sblk;
504	long long next_block = SQUASHFS_I(i)->start_block +
505		sblk->directory_table_start;
506	int next_offset = SQUASHFS_I(i)->offset, length = 0,
507		dir_count;
508	struct squashfs_dir_header_2 dirh;
509	struct squashfs_dir_entry_2 *dire;
510
511	TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
512
513	if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
514		SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
515		ERROR("Failed to allocate squashfs_dir_entry\n");
516		goto finish;
517	}
518
519	length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
520				SQUASHFS_I(i)->u.s2.directory_index_start,
521				SQUASHFS_I(i)->u.s2.directory_index_offset,
522				SQUASHFS_I(i)->u.s2.directory_index_count,
523				file->f_pos);
524
525	while (length < i_size_read(i)) {
526		/* read directory header */
527		if (msblk->swap) {
528			struct squashfs_dir_header_2 sdirh;
529
530			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
531					next_block, next_offset, sizeof(sdirh),
532					&next_block, &next_offset))
533				goto failed_read;
534
535			length += sizeof(sdirh);
536			SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
537		} else {
538			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
539					next_block, next_offset, sizeof(dirh),
540					&next_block, &next_offset))
541				goto failed_read;
542
543			length += sizeof(dirh);
544		}
545
546		dir_count = dirh.count + 1;
547		while (dir_count--) {
548			if (msblk->swap) {
549				struct squashfs_dir_entry_2 sdire;
550				if (!squashfs_get_cached_block(i->i_sb, (char *)
551						&sdire, next_block, next_offset,
552						sizeof(sdire), &next_block,
553						&next_offset))
554					goto failed_read;
555
556				length += sizeof(sdire);
557				SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
558			} else {
559				if (!squashfs_get_cached_block(i->i_sb, (char *)
560						dire, next_block, next_offset,
561						sizeof(*dire), &next_block,
562						&next_offset))
563					goto failed_read;
564
565				length += sizeof(*dire);
566			}
567
568			if (!squashfs_get_cached_block(i->i_sb, dire->name,
569						next_block, next_offset,
570						dire->size + 1, &next_block,
571						&next_offset))
572				goto failed_read;
573
574			length += dire->size + 1;
575
576			if (file->f_pos >= length)
577				continue;
578
579			dire->name[dire->size + 1] = '\0';
580
581			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
582					(unsigned int) dirent, dire->name,
583					dire->size + 1, (int) file->f_pos,
584					dirh.start_block, dire->offset,
585					squashfs_filetype_table[dire->type]);
586
587			if (filldir(dirent, dire->name, dire->size + 1,
588					file->f_pos, SQUASHFS_MK_VFS_INODE(
589					dirh.start_block, dire->offset),
590					squashfs_filetype_table[dire->type])
591					< 0) {
592				TRACE("Filldir returned less than 0\n");
593				goto finish;
594			}
595			file->f_pos = length;
596		}
597	}
598
599finish:
600	kfree(dire);
601	return 0;
602
603failed_read:
604	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
605		next_offset);
606	kfree(dire);
607	return 0;
608}
609
610
611static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
612				struct nameidata *nd)
613{
614	const unsigned char *name = dentry->d_name.name;
615	int len = dentry->d_name.len;
616	struct inode *inode = NULL;
617	struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
618	struct squashfs_super_block *sblk = &msblk->sblk;
619	long long next_block = SQUASHFS_I(i)->start_block +
620				sblk->directory_table_start;
621	int next_offset = SQUASHFS_I(i)->offset, length = 0,
622				dir_count;
623	struct squashfs_dir_header_2 dirh;
624	struct squashfs_dir_entry_2 *dire;
625	int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
626
627	TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
628
629	if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
630		SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
631		ERROR("Failed to allocate squashfs_dir_entry\n");
632		goto exit_loop;
633	}
634
635	if (len > SQUASHFS_NAME_LEN)
636		goto exit_loop;
637
638	length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
639				SQUASHFS_I(i)->u.s2.directory_index_start,
640				SQUASHFS_I(i)->u.s2.directory_index_offset,
641				SQUASHFS_I(i)->u.s2.directory_index_count, name,
642				len);
643
644	while (length < i_size_read(i)) {
645		/* read directory header */
646		if (msblk->swap) {
647			struct squashfs_dir_header_2 sdirh;
648			if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
649					next_block, next_offset, sizeof(sdirh),
650					&next_block, &next_offset))
651				goto failed_read;
652
653			length += sizeof(sdirh);
654			SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
655		} else {
656			if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
657					next_block, next_offset, sizeof(dirh),
658					&next_block, &next_offset))
659				goto failed_read;
660
661			length += sizeof(dirh);
662		}
663
664		dir_count = dirh.count + 1;
665		while (dir_count--) {
666			if (msblk->swap) {
667				struct squashfs_dir_entry_2 sdire;
668				if (!squashfs_get_cached_block(i->i_sb, (char *)
669						&sdire, next_block,next_offset,
670						sizeof(sdire), &next_block,
671						&next_offset))
672					goto failed_read;
673
674				length += sizeof(sdire);
675				SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
676			} else {
677				if (!squashfs_get_cached_block(i->i_sb, (char *)
678						dire, next_block,next_offset,
679						sizeof(*dire), &next_block,
680						&next_offset))
681					goto failed_read;
682
683				length += sizeof(*dire);
684			}
685
686			if (!squashfs_get_cached_block(i->i_sb, dire->name,
687					next_block, next_offset, dire->size + 1,
688					&next_block, &next_offset))
689				goto failed_read;
690
691			length += dire->size + 1;
692
693			if (sorted && name[0] < dire->name[0])
694				goto exit_loop;
695
696			if ((len == dire->size + 1) && !strncmp(name,
697						dire->name, len)) {
698				squashfs_inode_t ino =
699					SQUASHFS_MKINODE(dirh.start_block,
700					dire->offset);
701				unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
702					dire->offset);
703
704				TRACE("calling squashfs_iget for directory "
705					"entry %s, inode %x:%x, %lld\n", name,
706					dirh.start_block, dire->offset, ino);
707
708				inode = squashfs_iget(i->i_sb, ino, inode_number);
709
710				goto exit_loop;
711			}
712		}
713	}
714
715exit_loop:
716	kfree(dire);
717	d_add(dentry, inode);
718	return ERR_PTR(0);
719
720failed_read:
721	ERROR("Unable to read directory block [%llx:%x]\n", next_block,
722		next_offset);
723	goto exit_loop;
724}
725
726
727int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
728{
729	struct squashfs_super_block *sblk = &msblk->sblk;
730
731	msblk->read_inode = squashfs_read_inode_2;
732	msblk->read_fragment_index_table = read_fragment_index_table_2;
733
734	sblk->bytes_used = sblk->bytes_used_2;
735	sblk->uid_start = sblk->uid_start_2;
736	sblk->guid_start = sblk->guid_start_2;
737	sblk->inode_table_start = sblk->inode_table_start_2;
738	sblk->directory_table_start = sblk->directory_table_start_2;
739	sblk->fragment_table_start = sblk->fragment_table_start_2;
740
741	return 1;
742}
743