0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <linux/fs.h>
0029 #include <linux/vfs.h>
0030 #include <linux/xattr.h>
0031 #include <linux/pagemap.h>
0032
0033 #include "squashfs_fs.h"
0034 #include "squashfs_fs_sb.h"
0035 #include "squashfs_fs_i.h"
0036 #include "squashfs.h"
0037 #include "xattr.h"
0038
0039
0040
0041
0042
0043
0044 static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
0045 struct squashfs_base_inode *sqsh_ino)
0046 {
0047 uid_t i_uid;
0048 gid_t i_gid;
0049 int err;
0050
0051 err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid);
0052 if (err)
0053 return err;
0054
0055 err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->guid), &i_gid);
0056 if (err)
0057 return err;
0058
0059 i_uid_write(inode, i_uid);
0060 i_gid_write(inode, i_gid);
0061 inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
0062 inode->i_mtime.tv_sec = le32_to_cpu(sqsh_ino->mtime);
0063 inode->i_atime.tv_sec = inode->i_mtime.tv_sec;
0064 inode->i_ctime.tv_sec = inode->i_mtime.tv_sec;
0065 inode->i_mode = le16_to_cpu(sqsh_ino->mode);
0066 inode->i_size = 0;
0067
0068 return err;
0069 }
0070
0071
0072 struct inode *squashfs_iget(struct super_block *sb, long long ino,
0073 unsigned int ino_number)
0074 {
0075 struct inode *inode = iget_locked(sb, ino_number);
0076 int err;
0077
0078 TRACE("Entered squashfs_iget\n");
0079
0080 if (!inode)
0081 return ERR_PTR(-ENOMEM);
0082 if (!(inode->i_state & I_NEW))
0083 return inode;
0084
0085 err = squashfs_read_inode(inode, ino);
0086 if (err) {
0087 iget_failed(inode);
0088 return ERR_PTR(err);
0089 }
0090
0091 unlock_new_inode(inode);
0092 return inode;
0093 }
0094
0095
0096
0097
0098
0099
0100 int squashfs_read_inode(struct inode *inode, long long ino)
0101 {
0102 struct super_block *sb = inode->i_sb;
0103 struct squashfs_sb_info *msblk = sb->s_fs_info;
0104 u64 block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
0105 int err, type, offset = SQUASHFS_INODE_OFFSET(ino);
0106 union squashfs_inode squashfs_ino;
0107 struct squashfs_base_inode *sqshb_ino = &squashfs_ino.base;
0108 int xattr_id = SQUASHFS_INVALID_XATTR;
0109
0110 TRACE("Entered squashfs_read_inode\n");
0111
0112
0113
0114
0115 err = squashfs_read_metadata(sb, sqshb_ino, &block,
0116 &offset, sizeof(*sqshb_ino));
0117 if (err < 0)
0118 goto failed_read;
0119
0120 err = squashfs_new_inode(sb, inode, sqshb_ino);
0121 if (err)
0122 goto failed_read;
0123
0124 block = SQUASHFS_INODE_BLK(ino) + msblk->inode_table;
0125 offset = SQUASHFS_INODE_OFFSET(ino);
0126
0127 type = le16_to_cpu(sqshb_ino->inode_type);
0128 switch (type) {
0129 case SQUASHFS_REG_TYPE: {
0130 unsigned int frag_offset, frag;
0131 int frag_size;
0132 u64 frag_blk;
0133 struct squashfs_reg_inode *sqsh_ino = &squashfs_ino.reg;
0134
0135 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0136 sizeof(*sqsh_ino));
0137 if (err < 0)
0138 goto failed_read;
0139
0140 frag = le32_to_cpu(sqsh_ino->fragment);
0141 if (frag != SQUASHFS_INVALID_FRAG) {
0142 frag_offset = le32_to_cpu(sqsh_ino->offset);
0143 frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
0144 if (frag_size < 0) {
0145 err = frag_size;
0146 goto failed_read;
0147 }
0148 } else {
0149 frag_blk = SQUASHFS_INVALID_BLK;
0150 frag_size = 0;
0151 frag_offset = 0;
0152 }
0153
0154 set_nlink(inode, 1);
0155 inode->i_size = le32_to_cpu(sqsh_ino->file_size);
0156 inode->i_fop = &generic_ro_fops;
0157 inode->i_mode |= S_IFREG;
0158 inode->i_blocks = ((inode->i_size - 1) >> 9) + 1;
0159 squashfs_i(inode)->fragment_block = frag_blk;
0160 squashfs_i(inode)->fragment_size = frag_size;
0161 squashfs_i(inode)->fragment_offset = frag_offset;
0162 squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
0163 squashfs_i(inode)->block_list_start = block;
0164 squashfs_i(inode)->offset = offset;
0165 inode->i_data.a_ops = &squashfs_aops;
0166
0167 TRACE("File inode %x:%x, start_block %llx, block_list_start "
0168 "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
0169 offset, squashfs_i(inode)->start, block, offset);
0170 break;
0171 }
0172 case SQUASHFS_LREG_TYPE: {
0173 unsigned int frag_offset, frag;
0174 int frag_size;
0175 u64 frag_blk;
0176 struct squashfs_lreg_inode *sqsh_ino = &squashfs_ino.lreg;
0177
0178 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0179 sizeof(*sqsh_ino));
0180 if (err < 0)
0181 goto failed_read;
0182
0183 frag = le32_to_cpu(sqsh_ino->fragment);
0184 if (frag != SQUASHFS_INVALID_FRAG) {
0185 frag_offset = le32_to_cpu(sqsh_ino->offset);
0186 frag_size = squashfs_frag_lookup(sb, frag, &frag_blk);
0187 if (frag_size < 0) {
0188 err = frag_size;
0189 goto failed_read;
0190 }
0191 } else {
0192 frag_blk = SQUASHFS_INVALID_BLK;
0193 frag_size = 0;
0194 frag_offset = 0;
0195 }
0196
0197 xattr_id = le32_to_cpu(sqsh_ino->xattr);
0198 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0199 inode->i_size = le64_to_cpu(sqsh_ino->file_size);
0200 inode->i_op = &squashfs_inode_ops;
0201 inode->i_fop = &generic_ro_fops;
0202 inode->i_mode |= S_IFREG;
0203 inode->i_blocks = (inode->i_size -
0204 le64_to_cpu(sqsh_ino->sparse) + 511) >> 9;
0205
0206 squashfs_i(inode)->fragment_block = frag_blk;
0207 squashfs_i(inode)->fragment_size = frag_size;
0208 squashfs_i(inode)->fragment_offset = frag_offset;
0209 squashfs_i(inode)->start = le64_to_cpu(sqsh_ino->start_block);
0210 squashfs_i(inode)->block_list_start = block;
0211 squashfs_i(inode)->offset = offset;
0212 inode->i_data.a_ops = &squashfs_aops;
0213
0214 TRACE("File inode %x:%x, start_block %llx, block_list_start "
0215 "%llx, offset %x\n", SQUASHFS_INODE_BLK(ino),
0216 offset, squashfs_i(inode)->start, block, offset);
0217 break;
0218 }
0219 case SQUASHFS_DIR_TYPE: {
0220 struct squashfs_dir_inode *sqsh_ino = &squashfs_ino.dir;
0221
0222 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0223 sizeof(*sqsh_ino));
0224 if (err < 0)
0225 goto failed_read;
0226
0227 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0228 inode->i_size = le16_to_cpu(sqsh_ino->file_size);
0229 inode->i_op = &squashfs_dir_inode_ops;
0230 inode->i_fop = &squashfs_dir_ops;
0231 inode->i_mode |= S_IFDIR;
0232 squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
0233 squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
0234 squashfs_i(inode)->dir_idx_cnt = 0;
0235 squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
0236
0237 TRACE("Directory inode %x:%x, start_block %llx, offset %x\n",
0238 SQUASHFS_INODE_BLK(ino), offset,
0239 squashfs_i(inode)->start,
0240 le16_to_cpu(sqsh_ino->offset));
0241 break;
0242 }
0243 case SQUASHFS_LDIR_TYPE: {
0244 struct squashfs_ldir_inode *sqsh_ino = &squashfs_ino.ldir;
0245
0246 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0247 sizeof(*sqsh_ino));
0248 if (err < 0)
0249 goto failed_read;
0250
0251 xattr_id = le32_to_cpu(sqsh_ino->xattr);
0252 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0253 inode->i_size = le32_to_cpu(sqsh_ino->file_size);
0254 inode->i_op = &squashfs_dir_inode_ops;
0255 inode->i_fop = &squashfs_dir_ops;
0256 inode->i_mode |= S_IFDIR;
0257 squashfs_i(inode)->start = le32_to_cpu(sqsh_ino->start_block);
0258 squashfs_i(inode)->offset = le16_to_cpu(sqsh_ino->offset);
0259 squashfs_i(inode)->dir_idx_start = block;
0260 squashfs_i(inode)->dir_idx_offset = offset;
0261 squashfs_i(inode)->dir_idx_cnt = le16_to_cpu(sqsh_ino->i_count);
0262 squashfs_i(inode)->parent = le32_to_cpu(sqsh_ino->parent_inode);
0263
0264 TRACE("Long directory inode %x:%x, start_block %llx, offset "
0265 "%x\n", SQUASHFS_INODE_BLK(ino), offset,
0266 squashfs_i(inode)->start,
0267 le16_to_cpu(sqsh_ino->offset));
0268 break;
0269 }
0270 case SQUASHFS_SYMLINK_TYPE:
0271 case SQUASHFS_LSYMLINK_TYPE: {
0272 struct squashfs_symlink_inode *sqsh_ino = &squashfs_ino.symlink;
0273
0274 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0275 sizeof(*sqsh_ino));
0276 if (err < 0)
0277 goto failed_read;
0278
0279 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0280 inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
0281 inode->i_op = &squashfs_symlink_inode_ops;
0282 inode_nohighmem(inode);
0283 inode->i_data.a_ops = &squashfs_symlink_aops;
0284 inode->i_mode |= S_IFLNK;
0285 squashfs_i(inode)->start = block;
0286 squashfs_i(inode)->offset = offset;
0287
0288 if (type == SQUASHFS_LSYMLINK_TYPE) {
0289 __le32 xattr;
0290
0291 err = squashfs_read_metadata(sb, NULL, &block,
0292 &offset, inode->i_size);
0293 if (err < 0)
0294 goto failed_read;
0295 err = squashfs_read_metadata(sb, &xattr, &block,
0296 &offset, sizeof(xattr));
0297 if (err < 0)
0298 goto failed_read;
0299 xattr_id = le32_to_cpu(xattr);
0300 }
0301
0302 TRACE("Symbolic link inode %x:%x, start_block %llx, offset "
0303 "%x\n", SQUASHFS_INODE_BLK(ino), offset,
0304 block, offset);
0305 break;
0306 }
0307 case SQUASHFS_BLKDEV_TYPE:
0308 case SQUASHFS_CHRDEV_TYPE: {
0309 struct squashfs_dev_inode *sqsh_ino = &squashfs_ino.dev;
0310 unsigned int rdev;
0311
0312 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0313 sizeof(*sqsh_ino));
0314 if (err < 0)
0315 goto failed_read;
0316
0317 if (type == SQUASHFS_CHRDEV_TYPE)
0318 inode->i_mode |= S_IFCHR;
0319 else
0320 inode->i_mode |= S_IFBLK;
0321 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0322 rdev = le32_to_cpu(sqsh_ino->rdev);
0323 init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
0324
0325 TRACE("Device inode %x:%x, rdev %x\n",
0326 SQUASHFS_INODE_BLK(ino), offset, rdev);
0327 break;
0328 }
0329 case SQUASHFS_LBLKDEV_TYPE:
0330 case SQUASHFS_LCHRDEV_TYPE: {
0331 struct squashfs_ldev_inode *sqsh_ino = &squashfs_ino.ldev;
0332 unsigned int rdev;
0333
0334 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0335 sizeof(*sqsh_ino));
0336 if (err < 0)
0337 goto failed_read;
0338
0339 if (type == SQUASHFS_LCHRDEV_TYPE)
0340 inode->i_mode |= S_IFCHR;
0341 else
0342 inode->i_mode |= S_IFBLK;
0343 xattr_id = le32_to_cpu(sqsh_ino->xattr);
0344 inode->i_op = &squashfs_inode_ops;
0345 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0346 rdev = le32_to_cpu(sqsh_ino->rdev);
0347 init_special_inode(inode, inode->i_mode, new_decode_dev(rdev));
0348
0349 TRACE("Device inode %x:%x, rdev %x\n",
0350 SQUASHFS_INODE_BLK(ino), offset, rdev);
0351 break;
0352 }
0353 case SQUASHFS_FIFO_TYPE:
0354 case SQUASHFS_SOCKET_TYPE: {
0355 struct squashfs_ipc_inode *sqsh_ino = &squashfs_ino.ipc;
0356
0357 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0358 sizeof(*sqsh_ino));
0359 if (err < 0)
0360 goto failed_read;
0361
0362 if (type == SQUASHFS_FIFO_TYPE)
0363 inode->i_mode |= S_IFIFO;
0364 else
0365 inode->i_mode |= S_IFSOCK;
0366 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0367 init_special_inode(inode, inode->i_mode, 0);
0368 break;
0369 }
0370 case SQUASHFS_LFIFO_TYPE:
0371 case SQUASHFS_LSOCKET_TYPE: {
0372 struct squashfs_lipc_inode *sqsh_ino = &squashfs_ino.lipc;
0373
0374 err = squashfs_read_metadata(sb, sqsh_ino, &block, &offset,
0375 sizeof(*sqsh_ino));
0376 if (err < 0)
0377 goto failed_read;
0378
0379 if (type == SQUASHFS_LFIFO_TYPE)
0380 inode->i_mode |= S_IFIFO;
0381 else
0382 inode->i_mode |= S_IFSOCK;
0383 xattr_id = le32_to_cpu(sqsh_ino->xattr);
0384 inode->i_op = &squashfs_inode_ops;
0385 set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
0386 init_special_inode(inode, inode->i_mode, 0);
0387 break;
0388 }
0389 default:
0390 ERROR("Unknown inode type %d in squashfs_iget!\n", type);
0391 return -EINVAL;
0392 }
0393
0394 if (xattr_id != SQUASHFS_INVALID_XATTR && msblk->xattr_id_table) {
0395 err = squashfs_xattr_lookup(sb, xattr_id,
0396 &squashfs_i(inode)->xattr_count,
0397 &squashfs_i(inode)->xattr_size,
0398 &squashfs_i(inode)->xattr);
0399 if (err < 0)
0400 goto failed_read;
0401 inode->i_blocks += ((squashfs_i(inode)->xattr_size - 1) >> 9)
0402 + 1;
0403 } else
0404 squashfs_i(inode)->xattr_count = 0;
0405
0406 return 0;
0407
0408 failed_read:
0409 ERROR("Unable to read inode 0x%llx\n", ino);
0410 return err;
0411 }
0412
0413
0414 const struct inode_operations squashfs_inode_ops = {
0415 .listxattr = squashfs_listxattr
0416 };
0417