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