/* * look up an entry in a directory
*/ staticstruct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry, unsignedint flags)
{ unsignedlong offset, maxoff; struct inode *inode = NULL; struct romfs_inode ri; constchar *name; /* got from dentry */ int len, ret;
offset = dir->i_ino & ROMFH_MASK;
ret = romfs_dev_read(dir->i_sb, offset, &ri, ROMFH_SIZE); if (ret < 0) goto error;
/* search all the file entries in the list starting from the one
* pointed to by the directory's special data */
maxoff = romfs_maxsize(dir->i_sb);
offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
name = dentry->d_name.name;
len = dentry->d_name.len;
for (;;) { if (!offset || offset >= maxoff) break;
ret = romfs_dev_read(dir->i_sb, offset, &ri, sizeof(ri)); if (ret < 0) goto error;
/* try to match the first 16 bytes of name */
ret = romfs_dev_strcmp(dir->i_sb, offset + ROMFH_SIZE, name,
len); if (ret < 0) goto error; if (ret == 1) { /* Hard link handling */ if ((be32_to_cpu(ri.next) & ROMFH_TYPE) == ROMFH_HRD)
offset = be32_to_cpu(ri.spec) & ROMFH_MASK;
inode = romfs_iget(dir->i_sb, offset); break;
}
/* next entry */
offset = be32_to_cpu(ri.next) & ROMFH_MASK;
}
/* * get a romfs inode based on its position in the image (which doubles as the * inode number)
*/ staticstruct inode *romfs_iget(struct super_block *sb, unsignedlong pos)
{ struct romfs_inode_info *inode; struct romfs_inode ri; struct inode *i; unsignedlong nlen; unsigned nextfh; int ret;
umode_t mode;
/* we might have to traverse a chain of "hard link" file entries to get
* to the actual file */ for (;;) {
ret = romfs_dev_read(sb, pos, &ri, sizeof(ri)); if (ret < 0) goto error;
/* XXX: do romfs_checksum here too (with name) */
nextfh = be32_to_cpu(ri.next); if ((nextfh & ROMFH_TYPE) != ROMFH_HRD) break;
pos = be32_to_cpu(ri.spec) & ROMFH_MASK;
}
/* determine the length of the filename */
nlen = romfs_dev_strnlen(sb, pos + ROMFH_SIZE, ROMFS_MAXFN); if (IS_ERR_VALUE(nlen)) goto eio;
/* get an inode for this image position */
i = iget_locked(sb, pos); if (!i) return ERR_PTR(-ENOMEM);
/* When calling huge_encode_dev(), * use sb->s_bdev->bd_dev when, * - CONFIG_ROMFS_ON_BLOCK defined * use sb->s_dev when, * - CONFIG_ROMFS_ON_BLOCK undefined and * - CONFIG_ROMFS_ON_MTD defined * leave id as 0 when, * - CONFIG_ROMFS_ON_BLOCK undefined and * - CONFIG_ROMFS_ON_MTD undefined
*/ if (sb->s_bdev)
id = huge_encode_dev(sb->s_bdev->bd_dev); elseif (sb->s_dev)
id = huge_encode_dev(sb->s_dev);
#ifdef CONFIG_ROMFS_ON_MTD /* Use same dev ID from the underlying mtdblock device */ if (sb->s_mtd)
sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index); #endif /* read the image superblock and check it */
rsb = kmalloc(512, GFP_KERNEL); if (!rsb) return -ENOMEM;
sb->s_fs_info = (void *) 512;
ret = romfs_dev_read(sb, 0, rsb, 512); if (ret < 0) goto error_rsb;
img_size = be32_to_cpu(rsb->size);
if (sb->s_mtd && img_size > sb->s_mtd->size) goto error_rsb_inval;
sb->s_fs_info = (void *) img_size;
if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 ||
img_size < ROMFH_SIZE) { if (!(fc->sb_flags & SB_SILENT))
errorf(fc, "VFS: Can't find a romfs filesystem on dev %s.\n",
sb->s_id); goto error_rsb_inval;
}
if (romfs_checksum(rsb, min_t(size_t, img_size, 512))) {
pr_err("bad initial checksum on dev %s.\n", sb->s_id); goto error_rsb_inval;
}
storage = sb->s_mtd ? "MTD" : "the block layer";
len = strnlen(rsb->name, ROMFS_MAXFN); if (!(fc->sb_flags & SB_SILENT))
pr_notice("Mounting image '%*.*s' through %s\n",
(unsigned) len, (unsigned) len, rsb->name, storage);
kfree(rsb);
rsb = NULL;
/* find the root directory */
pos = (ROMFH_SIZE + len + 1 + ROMFH_PAD) & ROMFH_MASK;
root = romfs_iget(sb, pos); if (IS_ERR(root)) return PTR_ERR(root);
sb->s_root = d_make_root(root); if (!sb->s_root) return -ENOMEM;
return 0;
error_rsb_inval:
ret = -EINVAL;
error_rsb:
kfree(rsb); return ret;
}
/* * get a superblock for mounting
*/ staticint romfs_get_tree(struct fs_context *fc)
{ int ret = -EINVAL;
#ifdef CONFIG_ROMFS_ON_MTD
ret = get_tree_mtd(fc, romfs_fill_super); #endif #ifdef CONFIG_ROMFS_ON_BLOCK if (ret == -EINVAL)
ret = get_tree_bdev(fc, romfs_fill_super); #endif return ret;
}
MODULE_DESCRIPTION("Direct-MTD Capable RomFS");
MODULE_AUTHOR("Red Hat, Inc.");
MODULE_LICENSE("GPL"); /* Actually dual-licensed, but it doesn't matter for */
Messung V0.5
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.