xref: /aosp_15_r20/external/squashfs-tools/kernel/fs/squashfs/inode.c (revision 79398b2563bcbbbab54656397863972d8fa68df1)
1*79398b25SAndroid Build Coastguard Worker /*
2*79398b25SAndroid Build Coastguard Worker  * Squashfs - a compressed read only filesystem for Linux
3*79398b25SAndroid Build Coastguard Worker  *
4*79398b25SAndroid Build Coastguard Worker  * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008
5*79398b25SAndroid Build Coastguard Worker  * Phillip Lougher <[email protected]>
6*79398b25SAndroid Build Coastguard Worker  *
7*79398b25SAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
8*79398b25SAndroid Build Coastguard Worker  * modify it under the terms of the GNU General Public License
9*79398b25SAndroid Build Coastguard Worker  * as published by the Free Software Foundation; either version 2,
10*79398b25SAndroid Build Coastguard Worker  * or (at your option) any later version.
11*79398b25SAndroid Build Coastguard Worker  *
12*79398b25SAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
13*79398b25SAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*79398b25SAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*79398b25SAndroid Build Coastguard Worker  * GNU General Public License for more details.
16*79398b25SAndroid Build Coastguard Worker  *
17*79398b25SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
18*79398b25SAndroid Build Coastguard Worker  * along with this program; if not, write to the Free Software
19*79398b25SAndroid Build Coastguard Worker  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20*79398b25SAndroid Build Coastguard Worker  *
21*79398b25SAndroid Build Coastguard Worker  * inode.c
22*79398b25SAndroid Build Coastguard Worker  */
23*79398b25SAndroid Build Coastguard Worker 
24*79398b25SAndroid Build Coastguard Worker /*
25*79398b25SAndroid Build Coastguard Worker  * This file implements code to create and read inodes from disk.
26*79398b25SAndroid Build Coastguard Worker  *
27*79398b25SAndroid Build Coastguard Worker  * Inodes in Squashfs are identified by a 48-bit inode which encodes the
28*79398b25SAndroid Build Coastguard Worker  * location of the compressed metadata block containing the inode, and the byte
29*79398b25SAndroid Build Coastguard Worker  * offset into that block where the inode is placed (<block, offset>).
30*79398b25SAndroid Build Coastguard Worker  *
31*79398b25SAndroid Build Coastguard Worker  * To maximise compression there are different inodes for each file type
32*79398b25SAndroid Build Coastguard Worker  * (regular file, directory, device, etc.), the inode contents and length
33*79398b25SAndroid Build Coastguard Worker  * varying with the type.
34*79398b25SAndroid Build Coastguard Worker  *
35*79398b25SAndroid Build Coastguard Worker  * To further maximise compression, two types of regular file inode and
36*79398b25SAndroid Build Coastguard Worker  * directory inode are defined: inodes optimised for frequently occurring
37*79398b25SAndroid Build Coastguard Worker  * regular files and directories, and extended types where extra
38*79398b25SAndroid Build Coastguard Worker  * information has to be stored.
39*79398b25SAndroid Build Coastguard Worker  */
40*79398b25SAndroid Build Coastguard Worker 
41*79398b25SAndroid Build Coastguard Worker #include <linux/fs.h>
42*79398b25SAndroid Build Coastguard Worker #include <linux/vfs.h>
43*79398b25SAndroid Build Coastguard Worker #include <linux/zlib.h>
44*79398b25SAndroid Build Coastguard Worker 
45*79398b25SAndroid Build Coastguard Worker #include "squashfs_fs.h"
46*79398b25SAndroid Build Coastguard Worker #include "squashfs_fs_sb.h"
47*79398b25SAndroid Build Coastguard Worker #include "squashfs_fs_i.h"
48*79398b25SAndroid Build Coastguard Worker #include "squashfs.h"
49*79398b25SAndroid Build Coastguard Worker 
50*79398b25SAndroid Build Coastguard Worker /*
51*79398b25SAndroid Build Coastguard Worker  * Initialise VFS inode with the base inode information common to all
52*79398b25SAndroid Build Coastguard Worker  * Squashfs inode types.  Sqsh_ino contains the unswapped base inode
53*79398b25SAndroid Build Coastguard Worker  * off disk.
54*79398b25SAndroid Build Coastguard Worker  */
squashfs_new_inode(struct super_block * sb,struct inode * inode,struct squashfs_base_inode * sqsh_ino)55*79398b25SAndroid Build Coastguard Worker static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
56*79398b25SAndroid Build Coastguard Worker 				struct squashfs_base_inode *sqsh_ino)
57*79398b25SAndroid Build Coastguard Worker {
58*79398b25SAndroid Build Coastguard Worker 	int err;
59*79398b25SAndroid Build Coastguard Worker 
60*79398b25SAndroid Build Coastguard Worker 	err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &inode->i_uid);
61*79398b25SAndroid Build Coastguard Worker 	if (err)
62*79398b25SAndroid Build Coastguard Worker 		return err;
63*79398b25SAndroid Build Coastguard Worker 
64*79398b25SAndroid Build Coastguard Worker 	err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->guid), &inode->i_gid);
65*79398b25SAndroid Build Coastguard Worker 	if (err)
66*79398b25SAndroid Build Coastguard Worker 		return err;
67*79398b25SAndroid Build Coastguard Worker 
68*79398b25SAndroid Build Coastguard Worker 	inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
69*79398b25SAndroid Build Coastguard Worker 	inode->i_mtime.tv_sec = le32_to_cpu(sqsh_ino->mtime);
70*79398b25SAndroid Build Coastguard Worker 	inode->i_atime.tv_sec = inode->i_mtime.tv_sec;
71*79398b25SAndroid Build Coastguard Worker 	inode->i_ctime.tv_sec = inode->i_mtime.tv_sec;
72*79398b25SAndroid Build Coastguard Worker 	inode->i_mode = le16_to_cpu(sqsh_ino->mode);
73*79398b25SAndroid Build Coastguard Worker 	inode->i_size = 0;
74*79398b25SAndroid Build Coastguard Worker 
75*79398b25SAndroid Build Coastguard Worker 	return err;
76*79398b25SAndroid Build Coastguard Worker }
77*79398b25SAndroid Build Coastguard Worker 
78*79398b25SAndroid Build Coastguard Worker 
squashfs_iget(struct super_block * sb,long long ino,unsigned int ino_number)79*79398b25SAndroid Build Coastguard Worker struct inode *squashfs_iget(struct super_block *sb, long long ino,
80*79398b25SAndroid Build Coastguard Worker 				unsigned int ino_number)
81*79398b25SAndroid Build Coastguard Worker {
82*79398b25SAndroid Build Coastguard Worker 	struct inode *inode = iget_locked(sb, ino_number);
83*79398b25SAndroid Build Coastguard Worker 	int err;
84*79398b25SAndroid Build Coastguard Worker 
85*79398b25SAndroid Build Coastguard Worker 	TRACE("Entered squashfs_iget\n");
86*79398b25SAndroid Build Coastguard Worker 
87*79398b25SAndroid Build Coastguard Worker 	if (!inode)
88*79398b25SAndroid Build Coastguard Worker 		return ERR_PTR(-ENOMEM);
89*79398b25SAndroid Build Coastguard Worker 	if (!(inode->i_state & I_NEW))
90*79398b25SAndroid Build Coastguard Worker 		return inode;
91*79398b25SAndroid Build Coastguard Worker 
92*79398b25SAndroid Build Coastguard Worker 	err = squashfs_read_inode(inode, ino);
93*79398b25SAndroid Build Coastguard Worker 	if (err) {
94*79398b25SAndroid Build Coastguard Worker 		iget_failed(inode);
95*79398b25SAndroid Build Coastguard Worker 		return ERR_PTR(err);
96*79398b25SAndroid Build Coastguard Worker 	}
97*79398b25SAndroid Build Coastguard Worker 
98*79398b25SAndroid Build Coastguard Worker 	unlock_new_inode(inode);
99*79398b25SAndroid Build Coastguard Worker 	return inode;
100*79398b25SAndroid Build Coastguard Worker }
101*79398b25SAndroid Build Coastguard Worker 
102*79398b25SAndroid Build Coastguard Worker 
103*79398b25SAndroid Build Coastguard Worker /*
104*79398b25SAndroid Build Coastguard Worker  * Initialise VFS inode by reading inode from inode table (compressed
105*79398b25SAndroid Build Coastguard Worker  * metadata).  The format and amount of data read depends on type.
106*79398b25SAndroid Build Coastguard Worker  */
squashfs_read_inode(struct inode * inode,long long ino)107*79398b25SAndroid Build Coastguard Worker int squashfs_read_inode(struct inode *inode, long long ino)
108*79398b25SAndroid Build Coastguard Worker {
109*79398b25SAndroid Build Coastguard Worker 	struct super_block *sb = inode->i_sb;
110*79398b25SAndroid Build Coastguard Worker 	struct squashfs_sb_info *msblk = sb->s_fs_info;
111*79398b25SAndroid Build Coastguard Worker 	u64 block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
112*79398b25SAndroid Build Coastguard Worker 	int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
113*79398b25SAndroid Build Coastguard Worker 	union squashfs_inode squashfs_ino;
114*79398b25SAndroid Build Coastguard Worker 	struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
115*79398b25SAndroid Build Coastguard Worker 
116*79398b25SAndroid Build Coastguard Worker 	TRACE("Entered squashfs_read_inode\n");
117*79398b25SAndroid Build Coastguard Worker 
118*79398b25SAndroid Build Coastguard Worker 	/*
119*79398b25SAndroid Build Coastguard Worker 	 * Read inode base common to all inode types.
120*79398b25SAndroid Build Coastguard Worker 	 */
121*79398b25SAndroid Build Coastguard Worker 	err = squashfs_read_metadata(sb, sqshb_ino, &block,
122*79398b25SAndroid Build Coastguard Worker 				&offset, sizeof(*sqshb_ino));
123*79398b25SAndroid Build Coastguard Worker 	if (err < 0)
124*79398b25SAndroid Build Coastguard Worker 		goto failed_read;
125*79398b25SAndroid Build Coastguard Worker 
126*79398b25SAndroid Build Coastguard Worker 	err = squashfs_new_inode(sb, inode, sqshb_ino);
127*79398b25SAndroid Build Coastguard Worker 	if (err)
128*79398b25SAndroid Build Coastguard Worker 		goto failed_read;
129*79398b25SAndroid Build Coastguard Worker 
130*79398b25SAndroid Build Coastguard Worker 	block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
131*79398b25SAndroid Build Coastguard Worker 	offset = SQUASHFS_INODE_OFFSET(ino);
132*79398b25SAndroid Build Coastguard Worker 
133*79398b25SAndroid Build Coastguard Worker 	type = le16_to_cpu(sqshb_ino->inode_type);
134*79398b25SAndroid Build Coastguard Worker 	switch (type) {
135*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_REG_TYPE: {
136*79398b25SAndroid Build Coastguard Worker 		unsigned int frag_offset, frag_size, frag;
137*79398b25SAndroid Build Coastguard Worker 		u64 frag_blk;
138*79398b25SAndroid Build Coastguard Worker 		struct squashfs_reg_inode *sqsh_ino = &squashfs_ino.reg;
139*79398b25SAndroid Build Coastguard Worker 
140*79398b25SAndroid Build Coastguard Worker 		err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
141*79398b25SAndroid Build Coastguard Worker 							sizeof(*sqsh_ino));
142*79398b25SAndroid Build Coastguard Worker 		if (err < 0)
143*79398b25SAndroid Build Coastguard Worker 			goto failed_read;
144*79398b25SAndroid Build Coastguard Worker 
145*79398b25SAndroid Build Coastguard Worker 		frag = le32_to_cpu(sqsh_ino->fragment);
146*79398b25SAndroid Build Coastguard Worker 		if (frag != SQUASHFS_INVALID_FRAG) {
147*79398b25SAndroid Build Coastguard Worker 			frag_offset = le32_to_cpu(sqsh_ino->offset);
148*79398b25SAndroid Build Coastguard Worker 			frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
149*79398b25SAndroid Build Coastguard Worker 			if (frag_size < 0) {
150*79398b25SAndroid Build Coastguard Worker 				err = frag_size;
151*79398b25SAndroid Build Coastguard Worker 				goto failed_read;
152*79398b25SAndroid Build Coastguard Worker 			}
153*79398b25SAndroid Build Coastguard Worker 		} else {
154*79398b25SAndroid Build Coastguard Worker 			frag_blk = SQUASHFS_INVALID_BLK;
155*79398b25SAndroid Build Coastguard Worker 			frag_size = 0;
156*79398b25SAndroid Build Coastguard Worker 			frag_offset = 0;
157*79398b25SAndroid Build Coastguard Worker 		}
158*79398b25SAndroid Build Coastguard Worker 
159*79398b25SAndroid Build Coastguard Worker 		inode->i_nlink = 1;
160*79398b25SAndroid Build Coastguard Worker 		inode->i_size = le32_to_cpu(sqsh_ino->file_size);
161*79398b25SAndroid Build Coastguard Worker 		inode->i_fop = &generic_ro_fops;
162*79398b25SAndroid Build Coastguard Worker 		inode->i_mode |= S_IFREG;
163*79398b25SAndroid Build Coastguard Worker 		inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
164*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->fragment_block = frag_blk;
165*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->fragment_size = frag_size;
166*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->fragment_offset = frag_offset;
167*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
168*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->block_list_start = block;
169*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->offset = offset;
170*79398b25SAndroid Build Coastguard Worker 		inode->i_data.a_ops = &squashfs_aops;
171*79398b25SAndroid Build Coastguard Worker 
172*79398b25SAndroid Build Coastguard Worker 		TRACE("File inode %x:%x, start_block %llx, block_list_start "
173*79398b25SAndroid Build Coastguard Worker 			"%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
174*79398b25SAndroid Build Coastguard Worker 			offset, squashfs_i(inode)->start, block, offset);
175*79398b25SAndroid Build Coastguard Worker 		break;
176*79398b25SAndroid Build Coastguard Worker 	}
177*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_LREG_TYPE: {
178*79398b25SAndroid Build Coastguard Worker 		unsigned int frag_offset, frag_size, frag;
179*79398b25SAndroid Build Coastguard Worker 		u64 frag_blk;
180*79398b25SAndroid Build Coastguard Worker 		struct squashfs_lreg_inode *sqsh_ino = &squashfs_ino.lreg;
181*79398b25SAndroid Build Coastguard Worker 
182*79398b25SAndroid Build Coastguard Worker 		err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
183*79398b25SAndroid Build Coastguard Worker 							sizeof(*sqsh_ino));
184*79398b25SAndroid Build Coastguard Worker 		if (err < 0)
185*79398b25SAndroid Build Coastguard Worker 			goto failed_read;
186*79398b25SAndroid Build Coastguard Worker 
187*79398b25SAndroid Build Coastguard Worker 		frag = le32_to_cpu(sqsh_ino->fragment);
188*79398b25SAndroid Build Coastguard Worker 		if (frag != SQUASHFS_INVALID_FRAG) {
189*79398b25SAndroid Build Coastguard Worker 			frag_offset = le32_to_cpu(sqsh_ino->offset);
190*79398b25SAndroid Build Coastguard Worker 			frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
191*79398b25SAndroid Build Coastguard Worker 			if (frag_size < 0) {
192*79398b25SAndroid Build Coastguard Worker 				err = frag_size;
193*79398b25SAndroid Build Coastguard Worker 				goto failed_read;
194*79398b25SAndroid Build Coastguard Worker 			}
195*79398b25SAndroid Build Coastguard Worker 		} else {
196*79398b25SAndroid Build Coastguard Worker 			frag_blk = SQUASHFS_INVALID_BLK;
197*79398b25SAndroid Build Coastguard Worker 			frag_size = 0;
198*79398b25SAndroid Build Coastguard Worker 			frag_offset = 0;
199*79398b25SAndroid Build Coastguard Worker 		}
200*79398b25SAndroid Build Coastguard Worker 
201*79398b25SAndroid Build Coastguard Worker 		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
202*79398b25SAndroid Build Coastguard Worker 		inode->i_size = le64_to_cpu(sqsh_ino->file_size);
203*79398b25SAndroid Build Coastguard Worker 		inode->i_fop = &generic_ro_fops;
204*79398b25SAndroid Build Coastguard Worker 		inode->i_mode |= S_IFREG;
205*79398b25SAndroid Build Coastguard Worker 		inode->i_blocks = ((inode->i_size -
206*79398b25SAndroid Build Coastguard Worker 				le64_to_cpu(sqsh_ino->sparse) - 1) >> 9) + 1;
207*79398b25SAndroid Build Coastguard Worker 
208*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->fragment_block = frag_blk;
209*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->fragment_size = frag_size;
210*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->fragment_offset = frag_offset;
211*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->start = le64_to_cpu(sqsh_ino->start_block);
212*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->block_list_start = block;
213*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->offset = offset;
214*79398b25SAndroid Build Coastguard Worker 		inode->i_data.a_ops = &squashfs_aops;
215*79398b25SAndroid Build Coastguard Worker 
216*79398b25SAndroid Build Coastguard Worker 		TRACE("File inode %x:%x, start_block %llx, block_list_start "
217*79398b25SAndroid Build Coastguard Worker 			"%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
218*79398b25SAndroid Build Coastguard Worker 			offset, squashfs_i(inode)->start, block, offset);
219*79398b25SAndroid Build Coastguard Worker 		break;
220*79398b25SAndroid Build Coastguard Worker 	}
221*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_DIR_TYPE: {
222*79398b25SAndroid Build Coastguard Worker 		struct squashfs_dir_inode *sqsh_ino = &squashfs_ino.dir;
223*79398b25SAndroid Build Coastguard Worker 
224*79398b25SAndroid Build Coastguard Worker 		err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
225*79398b25SAndroid Build Coastguard Worker 				sizeof(*sqsh_ino));
226*79398b25SAndroid Build Coastguard Worker 		if (err < 0)
227*79398b25SAndroid Build Coastguard Worker 			goto failed_read;
228*79398b25SAndroid Build Coastguard Worker 
229*79398b25SAndroid Build Coastguard Worker 		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
230*79398b25SAndroid Build Coastguard Worker 		inode->i_size = le16_to_cpu(sqsh_ino->file_size);
231*79398b25SAndroid Build Coastguard Worker 		inode->i_op = &squashfs_dir_inode_ops;
232*79398b25SAndroid Build Coastguard Worker 		inode->i_fop = &squashfs_dir_ops;
233*79398b25SAndroid Build Coastguard Worker 		inode->i_mode |= S_IFDIR;
234*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
235*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
236*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->dir_idx_cnt = 0;
237*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
238*79398b25SAndroid Build Coastguard Worker 
239*79398b25SAndroid Build Coastguard Worker 		TRACE("Directory inode %x:%x, start_block %llx, offset %x\n",
240*79398b25SAndroid Build Coastguard Worker 				SQUASHFS_INODE_BLK(ino), offset,
241*79398b25SAndroid Build Coastguard Worker 				squashfs_i(inode)->start,
242*79398b25SAndroid Build Coastguard Worker 				le16_to_cpu(sqsh_ino->offset));
243*79398b25SAndroid Build Coastguard Worker 		break;
244*79398b25SAndroid Build Coastguard Worker 	}
245*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_LDIR_TYPE: {
246*79398b25SAndroid Build Coastguard Worker 		struct squashfs_ldir_inode *sqsh_ino = &squashfs_ino.ldir;
247*79398b25SAndroid Build Coastguard Worker 
248*79398b25SAndroid Build Coastguard Worker 		err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
249*79398b25SAndroid Build Coastguard Worker 				sizeof(*sqsh_ino));
250*79398b25SAndroid Build Coastguard Worker 		if (err < 0)
251*79398b25SAndroid Build Coastguard Worker 			goto failed_read;
252*79398b25SAndroid Build Coastguard Worker 
253*79398b25SAndroid Build Coastguard Worker 		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
254*79398b25SAndroid Build Coastguard Worker 		inode->i_size = le32_to_cpu(sqsh_ino->file_size);
255*79398b25SAndroid Build Coastguard Worker 		inode->i_op = &squashfs_dir_inode_ops;
256*79398b25SAndroid Build Coastguard Worker 		inode->i_fop = &squashfs_dir_ops;
257*79398b25SAndroid Build Coastguard Worker 		inode->i_mode |= S_IFDIR;
258*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
259*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
260*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->dir_idx_start = block;
261*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->dir_idx_offset = offset;
262*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->dir_idx_cnt = le16_to_cpu(sqsh_ino->i_count);
263*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
264*79398b25SAndroid Build Coastguard Worker 
265*79398b25SAndroid Build Coastguard Worker 		TRACE("Long directory inode %x:%x, start_block %llx, offset "
266*79398b25SAndroid Build Coastguard Worker 				"%x\n", SQUASHFS_INODE_BLK(ino), offset,
267*79398b25SAndroid Build Coastguard Worker 				squashfs_i(inode)->start,
268*79398b25SAndroid Build Coastguard Worker 				le16_to_cpu(sqsh_ino->offset));
269*79398b25SAndroid Build Coastguard Worker 		break;
270*79398b25SAndroid Build Coastguard Worker 	}
271*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_SYMLINK_TYPE:
272*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_LSYMLINK_TYPE: {
273*79398b25SAndroid Build Coastguard Worker 		struct squashfs_symlink_inode *sqsh_ino = &squashfs_ino.symlink;
274*79398b25SAndroid Build Coastguard Worker 
275*79398b25SAndroid Build Coastguard Worker 		err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
276*79398b25SAndroid Build Coastguard Worker 				sizeof(*sqsh_ino));
277*79398b25SAndroid Build Coastguard Worker 		if (err < 0)
278*79398b25SAndroid Build Coastguard Worker 			goto failed_read;
279*79398b25SAndroid Build Coastguard Worker 
280*79398b25SAndroid Build Coastguard Worker 		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
281*79398b25SAndroid Build Coastguard Worker 		inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
282*79398b25SAndroid Build Coastguard Worker 		inode->i_op = &page_symlink_inode_operations;
283*79398b25SAndroid Build Coastguard Worker 		inode->i_data.a_ops = &squashfs_symlink_aops;
284*79398b25SAndroid Build Coastguard Worker 		inode->i_mode |= S_IFLNK;
285*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->start = block;
286*79398b25SAndroid Build Coastguard Worker 		squashfs_i(inode)->offset = offset;
287*79398b25SAndroid Build Coastguard Worker 
288*79398b25SAndroid Build Coastguard Worker 		TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
289*79398b25SAndroid Build Coastguard Worker 				"%x\n", SQUASHFS_INODE_BLK(ino), offset,
290*79398b25SAndroid Build Coastguard Worker 				block, offset);
291*79398b25SAndroid Build Coastguard Worker 		break;
292*79398b25SAndroid Build Coastguard Worker 	}
293*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_BLKDEV_TYPE:
294*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_CHRDEV_TYPE:
295*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_LBLKDEV_TYPE:
296*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_LCHRDEV_TYPE: {
297*79398b25SAndroid Build Coastguard Worker 		struct squashfs_dev_inode *sqsh_ino = &squashfs_ino.dev;
298*79398b25SAndroid Build Coastguard Worker 		unsigned int rdev;
299*79398b25SAndroid Build Coastguard Worker 
300*79398b25SAndroid Build Coastguard Worker 		err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
301*79398b25SAndroid Build Coastguard Worker 				sizeof(*sqsh_ino));
302*79398b25SAndroid Build Coastguard Worker 		if (err < 0)
303*79398b25SAndroid Build Coastguard Worker 			goto failed_read;
304*79398b25SAndroid Build Coastguard Worker 
305*79398b25SAndroid Build Coastguard Worker 		if (type == SQUASHFS_CHRDEV_TYPE)
306*79398b25SAndroid Build Coastguard Worker 			inode->i_mode |= S_IFCHR;
307*79398b25SAndroid Build Coastguard Worker 		else
308*79398b25SAndroid Build Coastguard Worker 			inode->i_mode |= S_IFBLK;
309*79398b25SAndroid Build Coastguard Worker 		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
310*79398b25SAndroid Build Coastguard Worker 		rdev = le32_to_cpu(sqsh_ino->rdev);
311*79398b25SAndroid Build Coastguard Worker 		init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
312*79398b25SAndroid Build Coastguard Worker 
313*79398b25SAndroid Build Coastguard Worker 		TRACE("Device inode %x:%x, rdev %x\n",
314*79398b25SAndroid Build Coastguard Worker 				SQUASHFS_INODE_BLK(ino), offset, rdev);
315*79398b25SAndroid Build Coastguard Worker 		break;
316*79398b25SAndroid Build Coastguard Worker 	}
317*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_FIFO_TYPE:
318*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_SOCKET_TYPE:
319*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_LFIFO_TYPE:
320*79398b25SAndroid Build Coastguard Worker 	case SQUASHFS_LSOCKET_TYPE: {
321*79398b25SAndroid Build Coastguard Worker 		struct squashfs_ipc_inode *sqsh_ino = &squashfs_ino.ipc;
322*79398b25SAndroid Build Coastguard Worker 
323*79398b25SAndroid Build Coastguard Worker 		err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
324*79398b25SAndroid Build Coastguard Worker 				sizeof(*sqsh_ino));
325*79398b25SAndroid Build Coastguard Worker 		if (err < 0)
326*79398b25SAndroid Build Coastguard Worker 			goto failed_read;
327*79398b25SAndroid Build Coastguard Worker 
328*79398b25SAndroid Build Coastguard Worker 		if (type == SQUASHFS_FIFO_TYPE)
329*79398b25SAndroid Build Coastguard Worker 			inode->i_mode |= S_IFIFO;
330*79398b25SAndroid Build Coastguard Worker 		else
331*79398b25SAndroid Build Coastguard Worker 			inode->i_mode |= S_IFSOCK;
332*79398b25SAndroid Build Coastguard Worker 		inode->i_nlink = le32_to_cpu(sqsh_ino->nlink);
333*79398b25SAndroid Build Coastguard Worker 		init_special_inode(inode, inode->i_mode, 0);
334*79398b25SAndroid Build Coastguard Worker 		break;
335*79398b25SAndroid Build Coastguard Worker 	}
336*79398b25SAndroid Build Coastguard Worker 	default:
337*79398b25SAndroid Build Coastguard Worker 		ERROR("Unknown inode type %d in squashfs_iget!\n", type);
338*79398b25SAndroid Build Coastguard Worker 		return -EINVAL;
339*79398b25SAndroid Build Coastguard Worker 	}
340*79398b25SAndroid Build Coastguard Worker 
341*79398b25SAndroid Build Coastguard Worker 	return 0;
342*79398b25SAndroid Build Coastguard Worker 
343*79398b25SAndroid Build Coastguard Worker failed_read:
344*79398b25SAndroid Build Coastguard Worker 	ERROR("Unable to read inode 0x%llx\n", ino);
345*79398b25SAndroid Build Coastguard Worker 	return err;
346*79398b25SAndroid Build Coastguard Worker }
347