xref: /rk3399_rockchip-uboot/fs/ext4/ext4_common.c (revision a1596438a68921d2c9b1fdec70a720d38c85ca7d)
1*a1596438SUma Shankar /*
2*a1596438SUma Shankar  * (C) Copyright 2011 - 2012 Samsung Electronics
3*a1596438SUma Shankar  * EXT4 filesystem implementation in Uboot by
4*a1596438SUma Shankar  * Uma Shankar <uma.shankar@samsung.com>
5*a1596438SUma Shankar  * Manjunatha C Achar <a.manjunatha@samsung.com>
6*a1596438SUma Shankar  *
7*a1596438SUma Shankar  * ext4ls and ext4load : Based on ext2 ls load support in Uboot.
8*a1596438SUma Shankar  *
9*a1596438SUma Shankar  * (C) Copyright 2004
10*a1596438SUma Shankar  * esd gmbh <www.esd-electronics.com>
11*a1596438SUma Shankar  * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
12*a1596438SUma Shankar  *
13*a1596438SUma Shankar  * based on code from grub2 fs/ext2.c and fs/fshelp.c by
14*a1596438SUma Shankar  * GRUB  --  GRand Unified Bootloader
15*a1596438SUma Shankar  * Copyright (C) 2003, 2004  Free Software Foundation, Inc.
16*a1596438SUma Shankar  *
17*a1596438SUma Shankar  * This program is free software; you can redistribute it and/or modify
18*a1596438SUma Shankar  * it under the terms of the GNU General Public License as published by
19*a1596438SUma Shankar  * the Free Software Foundation; either version 2 of the License, or
20*a1596438SUma Shankar  * (at your option) any later version.
21*a1596438SUma Shankar  *
22*a1596438SUma Shankar  * This program is distributed in the hope that it will be useful,
23*a1596438SUma Shankar  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24*a1596438SUma Shankar  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25*a1596438SUma Shankar  * GNU General Public License for more details.
26*a1596438SUma Shankar  *
27*a1596438SUma Shankar  * You should have received a copy of the GNU General Public License
28*a1596438SUma Shankar  * along with this program; if not, write to the Free Software
29*a1596438SUma Shankar  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30*a1596438SUma Shankar  */
31*a1596438SUma Shankar 
32*a1596438SUma Shankar #include <common.h>
33*a1596438SUma Shankar #include <ext_common.h>
34*a1596438SUma Shankar #include <ext4fs.h>
35*a1596438SUma Shankar #include <malloc.h>
36*a1596438SUma Shankar #include <stddef.h>
37*a1596438SUma Shankar #include <linux/stat.h>
38*a1596438SUma Shankar #include <linux/time.h>
39*a1596438SUma Shankar #include <asm/byteorder.h>
40*a1596438SUma Shankar #include "ext4_common.h"
41*a1596438SUma Shankar 
42*a1596438SUma Shankar struct ext2_data *ext4fs_root;
43*a1596438SUma Shankar struct ext2fs_node *ext4fs_file;
44*a1596438SUma Shankar uint32_t *ext4fs_indir1_block;
45*a1596438SUma Shankar int ext4fs_indir1_size;
46*a1596438SUma Shankar int ext4fs_indir1_blkno = -1;
47*a1596438SUma Shankar uint32_t *ext4fs_indir2_block;
48*a1596438SUma Shankar int ext4fs_indir2_size;
49*a1596438SUma Shankar int ext4fs_indir2_blkno = -1;
50*a1596438SUma Shankar 
51*a1596438SUma Shankar uint32_t *ext4fs_indir3_block;
52*a1596438SUma Shankar int ext4fs_indir3_size;
53*a1596438SUma Shankar int ext4fs_indir3_blkno = -1;
54*a1596438SUma Shankar struct ext2_inode *g_parent_inode;
55*a1596438SUma Shankar static int symlinknest;
56*a1596438SUma Shankar 
57*a1596438SUma Shankar static struct ext4_extent_header *ext4fs_get_extent_block
58*a1596438SUma Shankar 	(struct ext2_data *data, char *buf,
59*a1596438SUma Shankar 		struct ext4_extent_header *ext_block,
60*a1596438SUma Shankar 		uint32_t fileblock, int log2_blksz)
61*a1596438SUma Shankar {
62*a1596438SUma Shankar 	struct ext4_extent_idx *index;
63*a1596438SUma Shankar 	unsigned long long block;
64*a1596438SUma Shankar 	struct ext_filesystem *fs = get_fs();
65*a1596438SUma Shankar 	int i;
66*a1596438SUma Shankar 
67*a1596438SUma Shankar 	while (1) {
68*a1596438SUma Shankar 		index = (struct ext4_extent_idx *)(ext_block + 1);
69*a1596438SUma Shankar 
70*a1596438SUma Shankar 		if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
71*a1596438SUma Shankar 			return 0;
72*a1596438SUma Shankar 
73*a1596438SUma Shankar 		if (ext_block->eh_depth == 0)
74*a1596438SUma Shankar 			return ext_block;
75*a1596438SUma Shankar 		i = -1;
76*a1596438SUma Shankar 		do {
77*a1596438SUma Shankar 			i++;
78*a1596438SUma Shankar 			if (i >= le32_to_cpu(ext_block->eh_entries))
79*a1596438SUma Shankar 				break;
80*a1596438SUma Shankar 		} while (fileblock > le32_to_cpu(index[i].ei_block));
81*a1596438SUma Shankar 
82*a1596438SUma Shankar 		if (--i < 0)
83*a1596438SUma Shankar 			return 0;
84*a1596438SUma Shankar 
85*a1596438SUma Shankar 		block = le32_to_cpu(index[i].ei_leaf_hi);
86*a1596438SUma Shankar 		block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
87*a1596438SUma Shankar 
88*a1596438SUma Shankar 		if (ext4fs_devread(block << log2_blksz, 0, fs->blksz, buf))
89*a1596438SUma Shankar 			ext_block = (struct ext4_extent_header *)buf;
90*a1596438SUma Shankar 		else
91*a1596438SUma Shankar 			return 0;
92*a1596438SUma Shankar 	}
93*a1596438SUma Shankar }
94*a1596438SUma Shankar 
95*a1596438SUma Shankar static int ext4fs_blockgroup
96*a1596438SUma Shankar 	(struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
97*a1596438SUma Shankar {
98*a1596438SUma Shankar 	long int blkno;
99*a1596438SUma Shankar 	unsigned int blkoff, desc_per_blk;
100*a1596438SUma Shankar 
101*a1596438SUma Shankar 	desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
102*a1596438SUma Shankar 
103*a1596438SUma Shankar 	blkno = __le32_to_cpu(data->sblock.first_data_block) + 1 +
104*a1596438SUma Shankar 			group / desc_per_blk;
105*a1596438SUma Shankar 	blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
106*a1596438SUma Shankar 
107*a1596438SUma Shankar 	debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
108*a1596438SUma Shankar 	      group, blkno, blkoff);
109*a1596438SUma Shankar 
110*a1596438SUma Shankar 	return ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data),
111*a1596438SUma Shankar 			      blkoff, sizeof(struct ext2_block_group),
112*a1596438SUma Shankar 			      (char *)blkgrp);
113*a1596438SUma Shankar }
114*a1596438SUma Shankar 
115*a1596438SUma Shankar int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
116*a1596438SUma Shankar {
117*a1596438SUma Shankar 	struct ext2_block_group blkgrp;
118*a1596438SUma Shankar 	struct ext2_sblock *sblock = &data->sblock;
119*a1596438SUma Shankar 	struct ext_filesystem *fs = get_fs();
120*a1596438SUma Shankar 	int inodes_per_block, status;
121*a1596438SUma Shankar 	long int blkno;
122*a1596438SUma Shankar 	unsigned int blkoff;
123*a1596438SUma Shankar 
124*a1596438SUma Shankar 	/* It is easier to calculate if the first inode is 0. */
125*a1596438SUma Shankar 	ino--;
126*a1596438SUma Shankar 	status = ext4fs_blockgroup(data, ino / __le32_to_cpu
127*a1596438SUma Shankar 				   (sblock->inodes_per_group), &blkgrp);
128*a1596438SUma Shankar 	if (status == 0)
129*a1596438SUma Shankar 		return 0;
130*a1596438SUma Shankar 
131*a1596438SUma Shankar 	inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
132*a1596438SUma Shankar 	blkno = __le32_to_cpu(blkgrp.inode_table_id) +
133*a1596438SUma Shankar 	    (ino % __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
134*a1596438SUma Shankar 	blkoff = (ino % inodes_per_block) * fs->inodesz;
135*a1596438SUma Shankar 	/* Read the inode. */
136*a1596438SUma Shankar 	status = ext4fs_devread(blkno << LOG2_EXT2_BLOCK_SIZE(data), blkoff,
137*a1596438SUma Shankar 				sizeof(struct ext2_inode), (char *)inode);
138*a1596438SUma Shankar 	if (status == 0)
139*a1596438SUma Shankar 		return 0;
140*a1596438SUma Shankar 
141*a1596438SUma Shankar 	return 1;
142*a1596438SUma Shankar }
143*a1596438SUma Shankar 
144*a1596438SUma Shankar long int read_allocated_block(struct ext2_inode *inode, int fileblock)
145*a1596438SUma Shankar {
146*a1596438SUma Shankar 	long int blknr;
147*a1596438SUma Shankar 	int blksz;
148*a1596438SUma Shankar 	int log2_blksz;
149*a1596438SUma Shankar 	int status;
150*a1596438SUma Shankar 	long int rblock;
151*a1596438SUma Shankar 	long int perblock_parent;
152*a1596438SUma Shankar 	long int perblock_child;
153*a1596438SUma Shankar 	unsigned long long start;
154*a1596438SUma Shankar 	/* get the blocksize of the filesystem */
155*a1596438SUma Shankar 	blksz = EXT2_BLOCK_SIZE(ext4fs_root);
156*a1596438SUma Shankar 	log2_blksz = LOG2_EXT2_BLOCK_SIZE(ext4fs_root);
157*a1596438SUma Shankar 	if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
158*a1596438SUma Shankar 		char *buf = zalloc(blksz);
159*a1596438SUma Shankar 		if (!buf)
160*a1596438SUma Shankar 			return -ENOMEM;
161*a1596438SUma Shankar 		struct ext4_extent_header *ext_block;
162*a1596438SUma Shankar 		struct ext4_extent *extent;
163*a1596438SUma Shankar 		int i = -1;
164*a1596438SUma Shankar 		ext_block = ext4fs_get_extent_block(ext4fs_root, buf,
165*a1596438SUma Shankar 						    (struct ext4_extent_header
166*a1596438SUma Shankar 						     *)inode->b.
167*a1596438SUma Shankar 						    blocks.dir_blocks,
168*a1596438SUma Shankar 						    fileblock, log2_blksz);
169*a1596438SUma Shankar 		if (!ext_block) {
170*a1596438SUma Shankar 			printf("invalid extent block\n");
171*a1596438SUma Shankar 			free(buf);
172*a1596438SUma Shankar 			return -EINVAL;
173*a1596438SUma Shankar 		}
174*a1596438SUma Shankar 
175*a1596438SUma Shankar 		extent = (struct ext4_extent *)(ext_block + 1);
176*a1596438SUma Shankar 
177*a1596438SUma Shankar 		do {
178*a1596438SUma Shankar 			i++;
179*a1596438SUma Shankar 			if (i >= le32_to_cpu(ext_block->eh_entries))
180*a1596438SUma Shankar 				break;
181*a1596438SUma Shankar 		} while (fileblock >= le32_to_cpu(extent[i].ee_block));
182*a1596438SUma Shankar 		if (--i >= 0) {
183*a1596438SUma Shankar 			fileblock -= le32_to_cpu(extent[i].ee_block);
184*a1596438SUma Shankar 			if (fileblock >= le32_to_cpu(extent[i].ee_len)) {
185*a1596438SUma Shankar 				free(buf);
186*a1596438SUma Shankar 				return 0;
187*a1596438SUma Shankar 			}
188*a1596438SUma Shankar 
189*a1596438SUma Shankar 			start = le32_to_cpu(extent[i].ee_start_hi);
190*a1596438SUma Shankar 			start = (start << 32) +
191*a1596438SUma Shankar 					le32_to_cpu(extent[i].ee_start_lo);
192*a1596438SUma Shankar 			free(buf);
193*a1596438SUma Shankar 			return fileblock + start;
194*a1596438SUma Shankar 		}
195*a1596438SUma Shankar 
196*a1596438SUma Shankar 		printf("Extent Error\n");
197*a1596438SUma Shankar 		free(buf);
198*a1596438SUma Shankar 		return -1;
199*a1596438SUma Shankar 	}
200*a1596438SUma Shankar 
201*a1596438SUma Shankar 	/* Direct blocks. */
202*a1596438SUma Shankar 	if (fileblock < INDIRECT_BLOCKS)
203*a1596438SUma Shankar 		blknr = __le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
204*a1596438SUma Shankar 
205*a1596438SUma Shankar 	/* Indirect. */
206*a1596438SUma Shankar 	else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
207*a1596438SUma Shankar 		if (ext4fs_indir1_block == NULL) {
208*a1596438SUma Shankar 			ext4fs_indir1_block = zalloc(blksz);
209*a1596438SUma Shankar 			if (ext4fs_indir1_block == NULL) {
210*a1596438SUma Shankar 				printf("** SI ext2fs read block (indir 1)"
211*a1596438SUma Shankar 					"malloc failed. **\n");
212*a1596438SUma Shankar 				return -1;
213*a1596438SUma Shankar 			}
214*a1596438SUma Shankar 			ext4fs_indir1_size = blksz;
215*a1596438SUma Shankar 			ext4fs_indir1_blkno = -1;
216*a1596438SUma Shankar 		}
217*a1596438SUma Shankar 		if (blksz != ext4fs_indir1_size) {
218*a1596438SUma Shankar 			free(ext4fs_indir1_block);
219*a1596438SUma Shankar 			ext4fs_indir1_block = NULL;
220*a1596438SUma Shankar 			ext4fs_indir1_size = 0;
221*a1596438SUma Shankar 			ext4fs_indir1_blkno = -1;
222*a1596438SUma Shankar 			ext4fs_indir1_block = zalloc(blksz);
223*a1596438SUma Shankar 			if (ext4fs_indir1_block == NULL) {
224*a1596438SUma Shankar 				printf("** SI ext2fs read block (indir 1):"
225*a1596438SUma Shankar 					"malloc failed. **\n");
226*a1596438SUma Shankar 				return -1;
227*a1596438SUma Shankar 			}
228*a1596438SUma Shankar 			ext4fs_indir1_size = blksz;
229*a1596438SUma Shankar 		}
230*a1596438SUma Shankar 		if ((__le32_to_cpu(inode->b.blocks.indir_block) <<
231*a1596438SUma Shankar 		     log2_blksz) != ext4fs_indir1_blkno) {
232*a1596438SUma Shankar 			status =
233*a1596438SUma Shankar 			    ext4fs_devread(__le32_to_cpu
234*a1596438SUma Shankar 					   (inode->b.blocks.
235*a1596438SUma Shankar 					    indir_block) << log2_blksz, 0,
236*a1596438SUma Shankar 					   blksz, (char *)ext4fs_indir1_block);
237*a1596438SUma Shankar 			if (status == 0) {
238*a1596438SUma Shankar 				printf("** SI ext2fs read block (indir 1)"
239*a1596438SUma Shankar 					"failed. **\n");
240*a1596438SUma Shankar 				return 0;
241*a1596438SUma Shankar 			}
242*a1596438SUma Shankar 			ext4fs_indir1_blkno =
243*a1596438SUma Shankar 				__le32_to_cpu(inode->b.blocks.
244*a1596438SUma Shankar 					       indir_block) << log2_blksz;
245*a1596438SUma Shankar 		}
246*a1596438SUma Shankar 		blknr = __le32_to_cpu(ext4fs_indir1_block
247*a1596438SUma Shankar 				      [fileblock - INDIRECT_BLOCKS]);
248*a1596438SUma Shankar 	}
249*a1596438SUma Shankar 	/* Double indirect. */
250*a1596438SUma Shankar 	else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 *
251*a1596438SUma Shankar 					(blksz / 4 + 1)))) {
252*a1596438SUma Shankar 
253*a1596438SUma Shankar 		long int perblock = blksz / 4;
254*a1596438SUma Shankar 		long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
255*a1596438SUma Shankar 
256*a1596438SUma Shankar 		if (ext4fs_indir1_block == NULL) {
257*a1596438SUma Shankar 			ext4fs_indir1_block = zalloc(blksz);
258*a1596438SUma Shankar 			if (ext4fs_indir1_block == NULL) {
259*a1596438SUma Shankar 				printf("** DI ext2fs read block (indir 2 1)"
260*a1596438SUma Shankar 					"malloc failed. **\n");
261*a1596438SUma Shankar 				return -1;
262*a1596438SUma Shankar 			}
263*a1596438SUma Shankar 			ext4fs_indir1_size = blksz;
264*a1596438SUma Shankar 			ext4fs_indir1_blkno = -1;
265*a1596438SUma Shankar 		}
266*a1596438SUma Shankar 		if (blksz != ext4fs_indir1_size) {
267*a1596438SUma Shankar 			free(ext4fs_indir1_block);
268*a1596438SUma Shankar 			ext4fs_indir1_block = NULL;
269*a1596438SUma Shankar 			ext4fs_indir1_size = 0;
270*a1596438SUma Shankar 			ext4fs_indir1_blkno = -1;
271*a1596438SUma Shankar 			ext4fs_indir1_block = zalloc(blksz);
272*a1596438SUma Shankar 			if (ext4fs_indir1_block == NULL) {
273*a1596438SUma Shankar 				printf("** DI ext2fs read block (indir 2 1)"
274*a1596438SUma Shankar 					"malloc failed. **\n");
275*a1596438SUma Shankar 				return -1;
276*a1596438SUma Shankar 			}
277*a1596438SUma Shankar 			ext4fs_indir1_size = blksz;
278*a1596438SUma Shankar 		}
279*a1596438SUma Shankar 		if ((__le32_to_cpu(inode->b.blocks.double_indir_block) <<
280*a1596438SUma Shankar 		     log2_blksz) != ext4fs_indir1_blkno) {
281*a1596438SUma Shankar 			status =
282*a1596438SUma Shankar 			    ext4fs_devread(__le32_to_cpu
283*a1596438SUma Shankar 					   (inode->b.blocks.
284*a1596438SUma Shankar 					    double_indir_block) << log2_blksz,
285*a1596438SUma Shankar 					   0, blksz,
286*a1596438SUma Shankar 					   (char *)ext4fs_indir1_block);
287*a1596438SUma Shankar 			if (status == 0) {
288*a1596438SUma Shankar 				printf("** DI ext2fs read block (indir 2 1)"
289*a1596438SUma Shankar 					"failed. **\n");
290*a1596438SUma Shankar 				return -1;
291*a1596438SUma Shankar 			}
292*a1596438SUma Shankar 			ext4fs_indir1_blkno =
293*a1596438SUma Shankar 			    __le32_to_cpu(inode->b.blocks.double_indir_block) <<
294*a1596438SUma Shankar 			    log2_blksz;
295*a1596438SUma Shankar 		}
296*a1596438SUma Shankar 
297*a1596438SUma Shankar 		if (ext4fs_indir2_block == NULL) {
298*a1596438SUma Shankar 			ext4fs_indir2_block = zalloc(blksz);
299*a1596438SUma Shankar 			if (ext4fs_indir2_block == NULL) {
300*a1596438SUma Shankar 				printf("** DI ext2fs read block (indir 2 2)"
301*a1596438SUma Shankar 					"malloc failed. **\n");
302*a1596438SUma Shankar 				return -1;
303*a1596438SUma Shankar 			}
304*a1596438SUma Shankar 			ext4fs_indir2_size = blksz;
305*a1596438SUma Shankar 			ext4fs_indir2_blkno = -1;
306*a1596438SUma Shankar 		}
307*a1596438SUma Shankar 		if (blksz != ext4fs_indir2_size) {
308*a1596438SUma Shankar 			free(ext4fs_indir2_block);
309*a1596438SUma Shankar 			ext4fs_indir2_block = NULL;
310*a1596438SUma Shankar 			ext4fs_indir2_size = 0;
311*a1596438SUma Shankar 			ext4fs_indir2_blkno = -1;
312*a1596438SUma Shankar 			ext4fs_indir2_block = zalloc(blksz);
313*a1596438SUma Shankar 			if (ext4fs_indir2_block == NULL) {
314*a1596438SUma Shankar 				printf("** DI ext2fs read block (indir 2 2)"
315*a1596438SUma Shankar 					"malloc failed. **\n");
316*a1596438SUma Shankar 				return -1;
317*a1596438SUma Shankar 			}
318*a1596438SUma Shankar 			ext4fs_indir2_size = blksz;
319*a1596438SUma Shankar 		}
320*a1596438SUma Shankar 		if ((__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) <<
321*a1596438SUma Shankar 		     log2_blksz) != ext4fs_indir2_blkno) {
322*a1596438SUma Shankar 			status = ext4fs_devread(__le32_to_cpu
323*a1596438SUma Shankar 						(ext4fs_indir1_block
324*a1596438SUma Shankar 						 [rblock /
325*a1596438SUma Shankar 						  perblock]) << log2_blksz, 0,
326*a1596438SUma Shankar 						blksz,
327*a1596438SUma Shankar 						(char *)ext4fs_indir2_block);
328*a1596438SUma Shankar 			if (status == 0) {
329*a1596438SUma Shankar 				printf("** DI ext2fs read block (indir 2 2)"
330*a1596438SUma Shankar 					"failed. **\n");
331*a1596438SUma Shankar 				return -1;
332*a1596438SUma Shankar 			}
333*a1596438SUma Shankar 			ext4fs_indir2_blkno =
334*a1596438SUma Shankar 			    __le32_to_cpu(ext4fs_indir1_block[rblock
335*a1596438SUma Shankar 							      /
336*a1596438SUma Shankar 							      perblock]) <<
337*a1596438SUma Shankar 			    log2_blksz;
338*a1596438SUma Shankar 		}
339*a1596438SUma Shankar 		blknr = __le32_to_cpu(ext4fs_indir2_block[rblock % perblock]);
340*a1596438SUma Shankar 	}
341*a1596438SUma Shankar 	/* Tripple indirect. */
342*a1596438SUma Shankar 	else {
343*a1596438SUma Shankar 		rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 +
344*a1596438SUma Shankar 				      (blksz / 4 * blksz / 4));
345*a1596438SUma Shankar 		perblock_child = blksz / 4;
346*a1596438SUma Shankar 		perblock_parent = ((blksz / 4) * (blksz / 4));
347*a1596438SUma Shankar 
348*a1596438SUma Shankar 		if (ext4fs_indir1_block == NULL) {
349*a1596438SUma Shankar 			ext4fs_indir1_block = zalloc(blksz);
350*a1596438SUma Shankar 			if (ext4fs_indir1_block == NULL) {
351*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 1)"
352*a1596438SUma Shankar 					"malloc failed. **\n");
353*a1596438SUma Shankar 				return -1;
354*a1596438SUma Shankar 			}
355*a1596438SUma Shankar 			ext4fs_indir1_size = blksz;
356*a1596438SUma Shankar 			ext4fs_indir1_blkno = -1;
357*a1596438SUma Shankar 		}
358*a1596438SUma Shankar 		if (blksz != ext4fs_indir1_size) {
359*a1596438SUma Shankar 			free(ext4fs_indir1_block);
360*a1596438SUma Shankar 			ext4fs_indir1_block = NULL;
361*a1596438SUma Shankar 			ext4fs_indir1_size = 0;
362*a1596438SUma Shankar 			ext4fs_indir1_blkno = -1;
363*a1596438SUma Shankar 			ext4fs_indir1_block = zalloc(blksz);
364*a1596438SUma Shankar 			if (ext4fs_indir1_block == NULL) {
365*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 1)"
366*a1596438SUma Shankar 					"malloc failed. **\n");
367*a1596438SUma Shankar 				return -1;
368*a1596438SUma Shankar 			}
369*a1596438SUma Shankar 			ext4fs_indir1_size = blksz;
370*a1596438SUma Shankar 		}
371*a1596438SUma Shankar 		if ((__le32_to_cpu(inode->b.blocks.triple_indir_block) <<
372*a1596438SUma Shankar 		     log2_blksz) != ext4fs_indir1_blkno) {
373*a1596438SUma Shankar 			status = ext4fs_devread
374*a1596438SUma Shankar 			    (__le32_to_cpu(inode->b.blocks.triple_indir_block)
375*a1596438SUma Shankar 			     << log2_blksz, 0, blksz,
376*a1596438SUma Shankar 			     (char *)ext4fs_indir1_block);
377*a1596438SUma Shankar 			if (status == 0) {
378*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 1)"
379*a1596438SUma Shankar 					"failed. **\n");
380*a1596438SUma Shankar 				return -1;
381*a1596438SUma Shankar 			}
382*a1596438SUma Shankar 			ext4fs_indir1_blkno =
383*a1596438SUma Shankar 			    __le32_to_cpu(inode->b.blocks.triple_indir_block) <<
384*a1596438SUma Shankar 			    log2_blksz;
385*a1596438SUma Shankar 		}
386*a1596438SUma Shankar 
387*a1596438SUma Shankar 		if (ext4fs_indir2_block == NULL) {
388*a1596438SUma Shankar 			ext4fs_indir2_block = zalloc(blksz);
389*a1596438SUma Shankar 			if (ext4fs_indir2_block == NULL) {
390*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 2)"
391*a1596438SUma Shankar 					"malloc failed. **\n");
392*a1596438SUma Shankar 				return -1;
393*a1596438SUma Shankar 			}
394*a1596438SUma Shankar 			ext4fs_indir2_size = blksz;
395*a1596438SUma Shankar 			ext4fs_indir2_blkno = -1;
396*a1596438SUma Shankar 		}
397*a1596438SUma Shankar 		if (blksz != ext4fs_indir2_size) {
398*a1596438SUma Shankar 			free(ext4fs_indir2_block);
399*a1596438SUma Shankar 			ext4fs_indir2_block = NULL;
400*a1596438SUma Shankar 			ext4fs_indir2_size = 0;
401*a1596438SUma Shankar 			ext4fs_indir2_blkno = -1;
402*a1596438SUma Shankar 			ext4fs_indir2_block = zalloc(blksz);
403*a1596438SUma Shankar 			if (ext4fs_indir2_block == NULL) {
404*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 2)"
405*a1596438SUma Shankar 					"malloc failed. **\n");
406*a1596438SUma Shankar 				return -1;
407*a1596438SUma Shankar 			}
408*a1596438SUma Shankar 			ext4fs_indir2_size = blksz;
409*a1596438SUma Shankar 		}
410*a1596438SUma Shankar 		if ((__le32_to_cpu(ext4fs_indir1_block[rblock /
411*a1596438SUma Shankar 						       perblock_parent]) <<
412*a1596438SUma Shankar 		     log2_blksz)
413*a1596438SUma Shankar 		    != ext4fs_indir2_blkno) {
414*a1596438SUma Shankar 			status = ext4fs_devread(__le32_to_cpu
415*a1596438SUma Shankar 						(ext4fs_indir1_block
416*a1596438SUma Shankar 						 [rblock /
417*a1596438SUma Shankar 						  perblock_parent]) <<
418*a1596438SUma Shankar 						log2_blksz, 0, blksz,
419*a1596438SUma Shankar 						(char *)ext4fs_indir2_block);
420*a1596438SUma Shankar 			if (status == 0) {
421*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 2)"
422*a1596438SUma Shankar 					"failed. **\n");
423*a1596438SUma Shankar 				return -1;
424*a1596438SUma Shankar 			}
425*a1596438SUma Shankar 			ext4fs_indir2_blkno =
426*a1596438SUma Shankar 			    __le32_to_cpu(ext4fs_indir1_block[rblock /
427*a1596438SUma Shankar 							      perblock_parent])
428*a1596438SUma Shankar 			    << log2_blksz;
429*a1596438SUma Shankar 		}
430*a1596438SUma Shankar 
431*a1596438SUma Shankar 		if (ext4fs_indir3_block == NULL) {
432*a1596438SUma Shankar 			ext4fs_indir3_block = zalloc(blksz);
433*a1596438SUma Shankar 			if (ext4fs_indir3_block == NULL) {
434*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 2)"
435*a1596438SUma Shankar 					"malloc failed. **\n");
436*a1596438SUma Shankar 				return -1;
437*a1596438SUma Shankar 			}
438*a1596438SUma Shankar 			ext4fs_indir3_size = blksz;
439*a1596438SUma Shankar 			ext4fs_indir3_blkno = -1;
440*a1596438SUma Shankar 		}
441*a1596438SUma Shankar 		if (blksz != ext4fs_indir3_size) {
442*a1596438SUma Shankar 			free(ext4fs_indir3_block);
443*a1596438SUma Shankar 			ext4fs_indir3_block = NULL;
444*a1596438SUma Shankar 			ext4fs_indir3_size = 0;
445*a1596438SUma Shankar 			ext4fs_indir3_blkno = -1;
446*a1596438SUma Shankar 			ext4fs_indir3_block = zalloc(blksz);
447*a1596438SUma Shankar 			if (ext4fs_indir3_block == NULL) {
448*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 2)"
449*a1596438SUma Shankar 					"malloc failed. **\n");
450*a1596438SUma Shankar 				return -1;
451*a1596438SUma Shankar 			}
452*a1596438SUma Shankar 			ext4fs_indir3_size = blksz;
453*a1596438SUma Shankar 		}
454*a1596438SUma Shankar 		if ((__le32_to_cpu(ext4fs_indir2_block[rblock
455*a1596438SUma Shankar 						       /
456*a1596438SUma Shankar 						       perblock_child]) <<
457*a1596438SUma Shankar 		     log2_blksz) != ext4fs_indir3_blkno) {
458*a1596438SUma Shankar 			status =
459*a1596438SUma Shankar 			    ext4fs_devread(__le32_to_cpu
460*a1596438SUma Shankar 					   (ext4fs_indir2_block
461*a1596438SUma Shankar 					    [(rblock / perblock_child)
462*a1596438SUma Shankar 					     % (blksz / 4)]) << log2_blksz, 0,
463*a1596438SUma Shankar 					   blksz, (char *)ext4fs_indir3_block);
464*a1596438SUma Shankar 			if (status == 0) {
465*a1596438SUma Shankar 				printf("** TI ext2fs read block (indir 2 2)"
466*a1596438SUma Shankar 				       "failed. **\n");
467*a1596438SUma Shankar 				return -1;
468*a1596438SUma Shankar 			}
469*a1596438SUma Shankar 			ext4fs_indir3_blkno =
470*a1596438SUma Shankar 			    __le32_to_cpu(ext4fs_indir2_block[(rblock /
471*a1596438SUma Shankar 							       perblock_child) %
472*a1596438SUma Shankar 							      (blksz /
473*a1596438SUma Shankar 							       4)]) <<
474*a1596438SUma Shankar 			    log2_blksz;
475*a1596438SUma Shankar 		}
476*a1596438SUma Shankar 
477*a1596438SUma Shankar 		blknr = __le32_to_cpu(ext4fs_indir3_block
478*a1596438SUma Shankar 				      [rblock % perblock_child]);
479*a1596438SUma Shankar 	}
480*a1596438SUma Shankar 	debug("ext4fs_read_block %ld\n", blknr);
481*a1596438SUma Shankar 
482*a1596438SUma Shankar 	return blknr;
483*a1596438SUma Shankar }
484*a1596438SUma Shankar 
485*a1596438SUma Shankar void ext4fs_close(void)
486*a1596438SUma Shankar {
487*a1596438SUma Shankar 	if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
488*a1596438SUma Shankar 		ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen);
489*a1596438SUma Shankar 		ext4fs_file = NULL;
490*a1596438SUma Shankar 	}
491*a1596438SUma Shankar 	if (ext4fs_root != NULL) {
492*a1596438SUma Shankar 		free(ext4fs_root);
493*a1596438SUma Shankar 		ext4fs_root = NULL;
494*a1596438SUma Shankar 	}
495*a1596438SUma Shankar 	if (ext4fs_indir1_block != NULL) {
496*a1596438SUma Shankar 		free(ext4fs_indir1_block);
497*a1596438SUma Shankar 		ext4fs_indir1_block = NULL;
498*a1596438SUma Shankar 		ext4fs_indir1_size = 0;
499*a1596438SUma Shankar 		ext4fs_indir1_blkno = -1;
500*a1596438SUma Shankar 	}
501*a1596438SUma Shankar 	if (ext4fs_indir2_block != NULL) {
502*a1596438SUma Shankar 		free(ext4fs_indir2_block);
503*a1596438SUma Shankar 		ext4fs_indir2_block = NULL;
504*a1596438SUma Shankar 		ext4fs_indir2_size = 0;
505*a1596438SUma Shankar 		ext4fs_indir2_blkno = -1;
506*a1596438SUma Shankar 	}
507*a1596438SUma Shankar 	if (ext4fs_indir3_block != NULL) {
508*a1596438SUma Shankar 		free(ext4fs_indir3_block);
509*a1596438SUma Shankar 		ext4fs_indir3_block = NULL;
510*a1596438SUma Shankar 		ext4fs_indir3_size = 0;
511*a1596438SUma Shankar 		ext4fs_indir3_blkno = -1;
512*a1596438SUma Shankar 	}
513*a1596438SUma Shankar }
514*a1596438SUma Shankar 
515*a1596438SUma Shankar int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
516*a1596438SUma Shankar 				struct ext2fs_node **fnode, int *ftype)
517*a1596438SUma Shankar {
518*a1596438SUma Shankar 	unsigned int fpos = 0;
519*a1596438SUma Shankar 	int status;
520*a1596438SUma Shankar 	struct ext2fs_node *diro = (struct ext2fs_node *) dir;
521*a1596438SUma Shankar 
522*a1596438SUma Shankar #ifdef DEBUG
523*a1596438SUma Shankar 	if (name != NULL)
524*a1596438SUma Shankar 		printf("Iterate dir %s\n", name);
525*a1596438SUma Shankar #endif /* of DEBUG */
526*a1596438SUma Shankar 	if (!diro->inode_read) {
527*a1596438SUma Shankar 		status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
528*a1596438SUma Shankar 		if (status == 0)
529*a1596438SUma Shankar 			return 0;
530*a1596438SUma Shankar 	}
531*a1596438SUma Shankar 	/* Search the file.  */
532*a1596438SUma Shankar 	while (fpos < __le32_to_cpu(diro->inode.size)) {
533*a1596438SUma Shankar 		struct ext2_dirent dirent;
534*a1596438SUma Shankar 
535*a1596438SUma Shankar 		status = ext4fs_read_file(diro, fpos,
536*a1596438SUma Shankar 					   sizeof(struct ext2_dirent),
537*a1596438SUma Shankar 					   (char *) &dirent);
538*a1596438SUma Shankar 		if (status < 1)
539*a1596438SUma Shankar 			return 0;
540*a1596438SUma Shankar 
541*a1596438SUma Shankar 		if (dirent.namelen != 0) {
542*a1596438SUma Shankar 			char filename[dirent.namelen + 1];
543*a1596438SUma Shankar 			struct ext2fs_node *fdiro;
544*a1596438SUma Shankar 			int type = FILETYPE_UNKNOWN;
545*a1596438SUma Shankar 
546*a1596438SUma Shankar 			status = ext4fs_read_file(diro,
547*a1596438SUma Shankar 						  fpos +
548*a1596438SUma Shankar 						  sizeof(struct ext2_dirent),
549*a1596438SUma Shankar 						  dirent.namelen, filename);
550*a1596438SUma Shankar 			if (status < 1)
551*a1596438SUma Shankar 				return 0;
552*a1596438SUma Shankar 
553*a1596438SUma Shankar 			fdiro = zalloc(sizeof(struct ext2fs_node));
554*a1596438SUma Shankar 			if (!fdiro)
555*a1596438SUma Shankar 				return 0;
556*a1596438SUma Shankar 
557*a1596438SUma Shankar 			fdiro->data = diro->data;
558*a1596438SUma Shankar 			fdiro->ino = __le32_to_cpu(dirent.inode);
559*a1596438SUma Shankar 
560*a1596438SUma Shankar 			filename[dirent.namelen] = '\0';
561*a1596438SUma Shankar 
562*a1596438SUma Shankar 			if (dirent.filetype != FILETYPE_UNKNOWN) {
563*a1596438SUma Shankar 				fdiro->inode_read = 0;
564*a1596438SUma Shankar 
565*a1596438SUma Shankar 				if (dirent.filetype == FILETYPE_DIRECTORY)
566*a1596438SUma Shankar 					type = FILETYPE_DIRECTORY;
567*a1596438SUma Shankar 				else if (dirent.filetype == FILETYPE_SYMLINK)
568*a1596438SUma Shankar 					type = FILETYPE_SYMLINK;
569*a1596438SUma Shankar 				else if (dirent.filetype == FILETYPE_REG)
570*a1596438SUma Shankar 					type = FILETYPE_REG;
571*a1596438SUma Shankar 			} else {
572*a1596438SUma Shankar 				status = ext4fs_read_inode(diro->data,
573*a1596438SUma Shankar 							   __le32_to_cpu
574*a1596438SUma Shankar 							   (dirent.inode),
575*a1596438SUma Shankar 							   &fdiro->inode);
576*a1596438SUma Shankar 				if (status == 0) {
577*a1596438SUma Shankar 					free(fdiro);
578*a1596438SUma Shankar 					return 0;
579*a1596438SUma Shankar 				}
580*a1596438SUma Shankar 				fdiro->inode_read = 1;
581*a1596438SUma Shankar 
582*a1596438SUma Shankar 				if ((__le16_to_cpu(fdiro->inode.mode) &
583*a1596438SUma Shankar 				     FILETYPE_INO_MASK) ==
584*a1596438SUma Shankar 				    FILETYPE_INO_DIRECTORY) {
585*a1596438SUma Shankar 					type = FILETYPE_DIRECTORY;
586*a1596438SUma Shankar 				} else if ((__le16_to_cpu(fdiro->inode.mode)
587*a1596438SUma Shankar 					    & FILETYPE_INO_MASK) ==
588*a1596438SUma Shankar 					   FILETYPE_INO_SYMLINK) {
589*a1596438SUma Shankar 					type = FILETYPE_SYMLINK;
590*a1596438SUma Shankar 				} else if ((__le16_to_cpu(fdiro->inode.mode)
591*a1596438SUma Shankar 					    & FILETYPE_INO_MASK) ==
592*a1596438SUma Shankar 					   FILETYPE_INO_REG) {
593*a1596438SUma Shankar 					type = FILETYPE_REG;
594*a1596438SUma Shankar 				}
595*a1596438SUma Shankar 			}
596*a1596438SUma Shankar #ifdef DEBUG
597*a1596438SUma Shankar 			printf("iterate >%s<\n", filename);
598*a1596438SUma Shankar #endif /* of DEBUG */
599*a1596438SUma Shankar 			if ((name != NULL) && (fnode != NULL)
600*a1596438SUma Shankar 			    && (ftype != NULL)) {
601*a1596438SUma Shankar 				if (strcmp(filename, name) == 0) {
602*a1596438SUma Shankar 					*ftype = type;
603*a1596438SUma Shankar 					*fnode = fdiro;
604*a1596438SUma Shankar 					return 1;
605*a1596438SUma Shankar 				}
606*a1596438SUma Shankar 			} else {
607*a1596438SUma Shankar 				if (fdiro->inode_read == 0) {
608*a1596438SUma Shankar 					status = ext4fs_read_inode(diro->data,
609*a1596438SUma Shankar 								 __le32_to_cpu(
610*a1596438SUma Shankar 								 dirent.inode),
611*a1596438SUma Shankar 								 &fdiro->inode);
612*a1596438SUma Shankar 					if (status == 0) {
613*a1596438SUma Shankar 						free(fdiro);
614*a1596438SUma Shankar 						return 0;
615*a1596438SUma Shankar 					}
616*a1596438SUma Shankar 					fdiro->inode_read = 1;
617*a1596438SUma Shankar 				}
618*a1596438SUma Shankar 				switch (type) {
619*a1596438SUma Shankar 				case FILETYPE_DIRECTORY:
620*a1596438SUma Shankar 					printf("<DIR> ");
621*a1596438SUma Shankar 					break;
622*a1596438SUma Shankar 				case FILETYPE_SYMLINK:
623*a1596438SUma Shankar 					printf("<SYM> ");
624*a1596438SUma Shankar 					break;
625*a1596438SUma Shankar 				case FILETYPE_REG:
626*a1596438SUma Shankar 					printf("      ");
627*a1596438SUma Shankar 					break;
628*a1596438SUma Shankar 				default:
629*a1596438SUma Shankar 					printf("< ? > ");
630*a1596438SUma Shankar 					break;
631*a1596438SUma Shankar 				}
632*a1596438SUma Shankar 				printf("%10d %s\n",
633*a1596438SUma Shankar 					__le32_to_cpu(fdiro->inode.size),
634*a1596438SUma Shankar 					filename);
635*a1596438SUma Shankar 			}
636*a1596438SUma Shankar 			free(fdiro);
637*a1596438SUma Shankar 		}
638*a1596438SUma Shankar 		fpos += __le16_to_cpu(dirent.direntlen);
639*a1596438SUma Shankar 	}
640*a1596438SUma Shankar 	return 0;
641*a1596438SUma Shankar }
642*a1596438SUma Shankar 
643*a1596438SUma Shankar static char *ext4fs_read_symlink(struct ext2fs_node *node)
644*a1596438SUma Shankar {
645*a1596438SUma Shankar 	char *symlink;
646*a1596438SUma Shankar 	struct ext2fs_node *diro = node;
647*a1596438SUma Shankar 	int status;
648*a1596438SUma Shankar 
649*a1596438SUma Shankar 	if (!diro->inode_read) {
650*a1596438SUma Shankar 		status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
651*a1596438SUma Shankar 		if (status == 0)
652*a1596438SUma Shankar 			return 0;
653*a1596438SUma Shankar 	}
654*a1596438SUma Shankar 	symlink = zalloc(__le32_to_cpu(diro->inode.size) + 1);
655*a1596438SUma Shankar 	if (!symlink)
656*a1596438SUma Shankar 		return 0;
657*a1596438SUma Shankar 
658*a1596438SUma Shankar 	if (__le32_to_cpu(diro->inode.size) <= 60) {
659*a1596438SUma Shankar 		strncpy(symlink, diro->inode.b.symlink,
660*a1596438SUma Shankar 			 __le32_to_cpu(diro->inode.size));
661*a1596438SUma Shankar 	} else {
662*a1596438SUma Shankar 		status = ext4fs_read_file(diro, 0,
663*a1596438SUma Shankar 					   __le32_to_cpu(diro->inode.size),
664*a1596438SUma Shankar 					   symlink);
665*a1596438SUma Shankar 		if (status == 0) {
666*a1596438SUma Shankar 			free(symlink);
667*a1596438SUma Shankar 			return 0;
668*a1596438SUma Shankar 		}
669*a1596438SUma Shankar 	}
670*a1596438SUma Shankar 	symlink[__le32_to_cpu(diro->inode.size)] = '\0';
671*a1596438SUma Shankar 	return symlink;
672*a1596438SUma Shankar }
673*a1596438SUma Shankar 
674*a1596438SUma Shankar static int ext4fs_find_file1(const char *currpath,
675*a1596438SUma Shankar 			     struct ext2fs_node *currroot,
676*a1596438SUma Shankar 			     struct ext2fs_node **currfound, int *foundtype)
677*a1596438SUma Shankar {
678*a1596438SUma Shankar 	char fpath[strlen(currpath) + 1];
679*a1596438SUma Shankar 	char *name = fpath;
680*a1596438SUma Shankar 	char *next;
681*a1596438SUma Shankar 	int status;
682*a1596438SUma Shankar 	int type = FILETYPE_DIRECTORY;
683*a1596438SUma Shankar 	struct ext2fs_node *currnode = currroot;
684*a1596438SUma Shankar 	struct ext2fs_node *oldnode = currroot;
685*a1596438SUma Shankar 
686*a1596438SUma Shankar 	strncpy(fpath, currpath, strlen(currpath) + 1);
687*a1596438SUma Shankar 
688*a1596438SUma Shankar 	/* Remove all leading slashes. */
689*a1596438SUma Shankar 	while (*name == '/')
690*a1596438SUma Shankar 		name++;
691*a1596438SUma Shankar 
692*a1596438SUma Shankar 	if (!*name) {
693*a1596438SUma Shankar 		*currfound = currnode;
694*a1596438SUma Shankar 		return 1;
695*a1596438SUma Shankar 	}
696*a1596438SUma Shankar 
697*a1596438SUma Shankar 	for (;;) {
698*a1596438SUma Shankar 		int found;
699*a1596438SUma Shankar 
700*a1596438SUma Shankar 		/* Extract the actual part from the pathname. */
701*a1596438SUma Shankar 		next = strchr(name, '/');
702*a1596438SUma Shankar 		if (next) {
703*a1596438SUma Shankar 			/* Remove all leading slashes. */
704*a1596438SUma Shankar 			while (*next == '/')
705*a1596438SUma Shankar 				*(next++) = '\0';
706*a1596438SUma Shankar 		}
707*a1596438SUma Shankar 
708*a1596438SUma Shankar 		if (type != FILETYPE_DIRECTORY) {
709*a1596438SUma Shankar 			ext4fs_free_node(currnode, currroot);
710*a1596438SUma Shankar 			return 0;
711*a1596438SUma Shankar 		}
712*a1596438SUma Shankar 
713*a1596438SUma Shankar 		oldnode = currnode;
714*a1596438SUma Shankar 
715*a1596438SUma Shankar 		/* Iterate over the directory. */
716*a1596438SUma Shankar 		found = ext4fs_iterate_dir(currnode, name, &currnode, &type);
717*a1596438SUma Shankar 		if (found == 0)
718*a1596438SUma Shankar 			return 0;
719*a1596438SUma Shankar 
720*a1596438SUma Shankar 		if (found == -1)
721*a1596438SUma Shankar 			break;
722*a1596438SUma Shankar 
723*a1596438SUma Shankar 		/* Read in the symlink and follow it. */
724*a1596438SUma Shankar 		if (type == FILETYPE_SYMLINK) {
725*a1596438SUma Shankar 			char *symlink;
726*a1596438SUma Shankar 
727*a1596438SUma Shankar 			/* Test if the symlink does not loop. */
728*a1596438SUma Shankar 			if (++symlinknest == 8) {
729*a1596438SUma Shankar 				ext4fs_free_node(currnode, currroot);
730*a1596438SUma Shankar 				ext4fs_free_node(oldnode, currroot);
731*a1596438SUma Shankar 				return 0;
732*a1596438SUma Shankar 			}
733*a1596438SUma Shankar 
734*a1596438SUma Shankar 			symlink = ext4fs_read_symlink(currnode);
735*a1596438SUma Shankar 			ext4fs_free_node(currnode, currroot);
736*a1596438SUma Shankar 
737*a1596438SUma Shankar 			if (!symlink) {
738*a1596438SUma Shankar 				ext4fs_free_node(oldnode, currroot);
739*a1596438SUma Shankar 				return 0;
740*a1596438SUma Shankar 			}
741*a1596438SUma Shankar 
742*a1596438SUma Shankar 			debug("Got symlink >%s<\n", symlink);
743*a1596438SUma Shankar 
744*a1596438SUma Shankar 			if (symlink[0] == '/') {
745*a1596438SUma Shankar 				ext4fs_free_node(oldnode, currroot);
746*a1596438SUma Shankar 				oldnode = &ext4fs_root->diropen;
747*a1596438SUma Shankar 			}
748*a1596438SUma Shankar 
749*a1596438SUma Shankar 			/* Lookup the node the symlink points to. */
750*a1596438SUma Shankar 			status = ext4fs_find_file1(symlink, oldnode,
751*a1596438SUma Shankar 						    &currnode, &type);
752*a1596438SUma Shankar 
753*a1596438SUma Shankar 			free(symlink);
754*a1596438SUma Shankar 
755*a1596438SUma Shankar 			if (status == 0) {
756*a1596438SUma Shankar 				ext4fs_free_node(oldnode, currroot);
757*a1596438SUma Shankar 				return 0;
758*a1596438SUma Shankar 			}
759*a1596438SUma Shankar 		}
760*a1596438SUma Shankar 
761*a1596438SUma Shankar 		ext4fs_free_node(oldnode, currroot);
762*a1596438SUma Shankar 
763*a1596438SUma Shankar 		/* Found the node! */
764*a1596438SUma Shankar 		if (!next || *next == '\0') {
765*a1596438SUma Shankar 			*currfound = currnode;
766*a1596438SUma Shankar 			*foundtype = type;
767*a1596438SUma Shankar 			return 1;
768*a1596438SUma Shankar 		}
769*a1596438SUma Shankar 		name = next;
770*a1596438SUma Shankar 	}
771*a1596438SUma Shankar 	return -1;
772*a1596438SUma Shankar }
773*a1596438SUma Shankar 
774*a1596438SUma Shankar int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
775*a1596438SUma Shankar 	struct ext2fs_node **foundnode, int expecttype)
776*a1596438SUma Shankar {
777*a1596438SUma Shankar 	int status;
778*a1596438SUma Shankar 	int foundtype = FILETYPE_DIRECTORY;
779*a1596438SUma Shankar 
780*a1596438SUma Shankar 	symlinknest = 0;
781*a1596438SUma Shankar 	if (!path)
782*a1596438SUma Shankar 		return 0;
783*a1596438SUma Shankar 
784*a1596438SUma Shankar 	status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype);
785*a1596438SUma Shankar 	if (status == 0)
786*a1596438SUma Shankar 		return 0;
787*a1596438SUma Shankar 
788*a1596438SUma Shankar 	/* Check if the node that was found was of the expected type. */
789*a1596438SUma Shankar 	if ((expecttype == FILETYPE_REG) && (foundtype != expecttype))
790*a1596438SUma Shankar 		return 0;
791*a1596438SUma Shankar 	else if ((expecttype == FILETYPE_DIRECTORY)
792*a1596438SUma Shankar 		   && (foundtype != expecttype))
793*a1596438SUma Shankar 		return 0;
794*a1596438SUma Shankar 
795*a1596438SUma Shankar 	return 1;
796*a1596438SUma Shankar }
797*a1596438SUma Shankar 
798*a1596438SUma Shankar int ext4fs_open(const char *filename)
799*a1596438SUma Shankar {
800*a1596438SUma Shankar 	struct ext2fs_node *fdiro = NULL;
801*a1596438SUma Shankar 	int status;
802*a1596438SUma Shankar 	int len;
803*a1596438SUma Shankar 
804*a1596438SUma Shankar 	if (ext4fs_root == NULL)
805*a1596438SUma Shankar 		return -1;
806*a1596438SUma Shankar 
807*a1596438SUma Shankar 	ext4fs_file = NULL;
808*a1596438SUma Shankar 	status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro,
809*a1596438SUma Shankar 				  FILETYPE_REG);
810*a1596438SUma Shankar 	if (status == 0)
811*a1596438SUma Shankar 		goto fail;
812*a1596438SUma Shankar 
813*a1596438SUma Shankar 	if (!fdiro->inode_read) {
814*a1596438SUma Shankar 		status = ext4fs_read_inode(fdiro->data, fdiro->ino,
815*a1596438SUma Shankar 				&fdiro->inode);
816*a1596438SUma Shankar 		if (status == 0)
817*a1596438SUma Shankar 			goto fail;
818*a1596438SUma Shankar 	}
819*a1596438SUma Shankar 	len = __le32_to_cpu(fdiro->inode.size);
820*a1596438SUma Shankar 	ext4fs_file = fdiro;
821*a1596438SUma Shankar 
822*a1596438SUma Shankar 	return len;
823*a1596438SUma Shankar fail:
824*a1596438SUma Shankar 	ext4fs_free_node(fdiro, &ext4fs_root->diropen);
825*a1596438SUma Shankar 
826*a1596438SUma Shankar 	return -1;
827*a1596438SUma Shankar }
828*a1596438SUma Shankar 
829*a1596438SUma Shankar int ext4fs_mount(unsigned part_length)
830*a1596438SUma Shankar {
831*a1596438SUma Shankar 	struct ext2_data *data;
832*a1596438SUma Shankar 	int status;
833*a1596438SUma Shankar 	struct ext_filesystem *fs = get_fs();
834*a1596438SUma Shankar 	data = zalloc(sizeof(struct ext2_data));
835*a1596438SUma Shankar 	if (!data)
836*a1596438SUma Shankar 		return 0;
837*a1596438SUma Shankar 
838*a1596438SUma Shankar 	/* Read the superblock. */
839*a1596438SUma Shankar 	status = ext4fs_devread(1 * 2, 0, sizeof(struct ext2_sblock),
840*a1596438SUma Shankar 				(char *)&data->sblock);
841*a1596438SUma Shankar 
842*a1596438SUma Shankar 	if (status == 0)
843*a1596438SUma Shankar 		goto fail;
844*a1596438SUma Shankar 
845*a1596438SUma Shankar 	/* Make sure this is an ext2 filesystem. */
846*a1596438SUma Shankar 	if (__le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
847*a1596438SUma Shankar 		goto fail;
848*a1596438SUma Shankar 
849*a1596438SUma Shankar 	if (__le32_to_cpu(data->sblock.revision_level == 0))
850*a1596438SUma Shankar 		fs->inodesz = 128;
851*a1596438SUma Shankar 	else
852*a1596438SUma Shankar 		fs->inodesz = __le16_to_cpu(data->sblock.inode_size);
853*a1596438SUma Shankar 
854*a1596438SUma Shankar 	debug("EXT2 rev %d, inode_size %d\n",
855*a1596438SUma Shankar 	       __le32_to_cpu(data->sblock.revision_level), fs->inodesz);
856*a1596438SUma Shankar 
857*a1596438SUma Shankar 	data->diropen.data = data;
858*a1596438SUma Shankar 	data->diropen.ino = 2;
859*a1596438SUma Shankar 	data->diropen.inode_read = 1;
860*a1596438SUma Shankar 	data->inode = &data->diropen.inode;
861*a1596438SUma Shankar 
862*a1596438SUma Shankar 	status = ext4fs_read_inode(data, 2, data->inode);
863*a1596438SUma Shankar 	if (status == 0)
864*a1596438SUma Shankar 		goto fail;
865*a1596438SUma Shankar 
866*a1596438SUma Shankar 	ext4fs_root = data;
867*a1596438SUma Shankar 
868*a1596438SUma Shankar 	return 1;
869*a1596438SUma Shankar fail:
870*a1596438SUma Shankar 	printf("Failed to mount ext2 filesystem...\n");
871*a1596438SUma Shankar 	free(data);
872*a1596438SUma Shankar 	ext4fs_root = NULL;
873*a1596438SUma Shankar 
874*a1596438SUma Shankar 	return 0;
875*a1596438SUma Shankar }
876