📄 inode.c
字号:
const char *name; /* got from dentry */ int len; res = -EACCES; /* placeholder for "no data here" */ offset = dir->i_ino & ROMFH_MASK; if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) goto out; maxoff = dir->i_sb->u.romfs_sb.s_maxsize; offset = ntohl(ri.spec) & ROMFH_MASK; /* OK, now find the file whose name is in "dentry" in the * directory specified by "dir". */ name = dentry->d_name.name; len = dentry->d_name.len; for(;;) { if (!offset || offset >= maxoff) goto out0; if (romfs_copyfrom(dir, &ri, offset, ROMFH_SIZE) <= 0) goto out; /* try to match the first 16 bytes of name */ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, ROMFH_SIZE); if (len < ROMFH_SIZE) { if (len == fslen) { /* both are shorter, and same size */ romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1); if (strncmp (name, fsname, len) == 0) break; } } else if (fslen >= ROMFH_SIZE) { /* both are longer; XXX optimize max size */ fslen = romfs_strnlen(dir, offset+ROMFH_SIZE, sizeof(fsname)-1); if (len == fslen) { romfs_copyfrom(dir, fsname, offset+ROMFH_SIZE, len+1); if (strncmp(name, fsname, len) == 0) break; } } /* next entry */ offset = ntohl(ri.next) & ROMFH_MASK; } /* Hard link handling */ if ((ntohl(ri.next) & ROMFH_TYPE) == ROMFH_HRD) offset = ntohl(ri.spec) & ROMFH_MASK; if ((inode = iget(dir->i_sb, offset))) goto outi; /* * it's a bit funky, _lookup needs to return an error code * (negative) or a NULL, both as a dentry. ENOENT should not * be returned, instead we need to create a negative dentry by * d_add(dentry, NULL); and return 0 as no error. * (Although as I see, it only matters on writable file * systems). */out0: inode = NULL;outi: res = 0; d_add (dentry, inode);out: return ERR_PTR(res);}/* * Ok, we do readpage, to be able to execute programs. Unfortunately, * we can't use bmap, since we may have looser alignments. */static intromfs_readpage(struct file *file, struct page * page){ struct inode *inode = page->mapping->host; unsigned long offset, avail, readlen; void *buf; int result = -EIO; page_cache_get(page); lock_kernel(); buf = kmap(page); if (!buf) goto err_out; /* 32 bit warning -- but not for us :) */ offset = page->index << PAGE_CACHE_SHIFT; if (offset < inode->i_size) { avail = inode->i_size-offset; readlen = min_t(unsigned long, avail, PAGE_SIZE); if (romfs_copyfrom(inode, buf, inode->u.romfs_i.i_dataoffset+offset, readlen) == readlen) { if (readlen < PAGE_SIZE) { memset(buf + readlen,0,PAGE_SIZE-readlen); } SetPageUptodate(page); result = 0; } } if (result) { memset(buf, 0, PAGE_SIZE); SetPageError(page); } flush_dcache_page(page); UnlockPage(page); kunmap(page);err_out: page_cache_release(page); unlock_kernel(); return result;}/* Mapping from our types to the kernel */static struct address_space_operations romfs_aops = { readpage: romfs_readpage};static struct file_operations romfs_dir_operations = { read: generic_read_dir, readdir: romfs_readdir,};static struct inode_operations romfs_dir_inode_operations = { lookup: romfs_lookup,};static mode_t romfs_modemap[] ={ 0, S_IFDIR+0644, S_IFREG+0644, S_IFLNK+0777, S_IFBLK+0600, S_IFCHR+0600, S_IFSOCK+0644, S_IFIFO+0644};static voidromfs_read_inode(struct inode *i){ int nextfh, ino; struct romfs_inode ri; ino = i->i_ino & ROMFH_MASK; i->i_mode = 0; /* Loop for finding the real hard link */ for(;;) { if (romfs_copyfrom(i, &ri, ino, ROMFH_SIZE) <= 0) { printk("romfs: read error for inode 0x%x\n", ino); return; } /* XXX: do romfs_checksum here too (with name) */ nextfh = ntohl(ri.next); if ((nextfh & ROMFH_TYPE) != ROMFH_HRD) break; ino = ntohl(ri.spec) & ROMFH_MASK; } i->i_nlink = 1; /* Hard to decide.. */ i->i_size = ntohl(ri.size); i->i_mtime = i->i_atime = i->i_ctime = 0; i->i_uid = i->i_gid = 0; /* Precalculate the data offset */ ino = romfs_strnlen(i, ino+ROMFH_SIZE, ROMFS_MAXFN); if (ino >= 0) ino = ((ROMFH_SIZE+ino+1+ROMFH_PAD)&ROMFH_MASK); else ino = 0; i->u.romfs_i.i_metasize = ino; i->u.romfs_i.i_dataoffset = ino+(i->i_ino&ROMFH_MASK); /* Compute permissions */ ino = romfs_modemap[nextfh & ROMFH_TYPE]; /* only "normal" files have ops */ switch (nextfh & ROMFH_TYPE) { case 1: i->i_size = i->u.romfs_i.i_metasize; i->i_op = &romfs_dir_inode_operations; i->i_fop = &romfs_dir_operations; if (nextfh & ROMFH_EXEC) ino |= S_IXUGO; i->i_mode = ino; break; case 2: i->i_fop = &generic_ro_fops; i->i_data.a_ops = &romfs_aops; if (nextfh & ROMFH_EXEC) ino |= S_IXUGO; i->i_mode = ino; break; case 3: i->i_op = &page_symlink_inode_operations; i->i_data.a_ops = &romfs_aops; i->i_mode = ino | S_IRWXUGO; break; default: /* depending on MBZ for sock/fifos */ nextfh = ntohl(ri.spec); nextfh = kdev_t_to_nr(MKDEV(nextfh>>16,nextfh&0xffff)); init_special_inode(i, ino, nextfh); }}static struct super_operations romfs_ops = { read_inode: romfs_read_inode, statfs: romfs_statfs,};static DECLARE_FSTYPE_DEV(romfs_fs_type, "romfs", romfs_read_super);static int __init init_romfs_fs(void){ return register_filesystem(&romfs_fs_type);}static void __exit exit_romfs_fs(void){ unregister_filesystem(&romfs_fs_type);}/* Yes, works even as a module... :) */EXPORT_NO_SYMBOLS;module_init(init_romfs_fs)module_exit(exit_romfs_fs)MODULE_LICENSE("GPL");inding the real hard link */ for(;;) { if (romfs_copyfrom(i, &ri, ino, ROMFH_SIZE) <= 0) { printk("romfs: read error for inode 0x%x\n", ino); return; } /* XXX: do romfs_checksum here too (with name) */ nextfh = ntohl(ri.next); if ((nextfh & ROMFH_TYPE) != ROMFH_HRD) break; ino = ntohl(ri.spec) & ROMFH_MASK; } i->i_nlink = 1; /* Hard to decide.. */ i->i_size = ntohl(ri.size); i->i_mtime = i->i_atime = i->i_ctime = 0; i->i_uid = i->i_gid = 0; /* Precalculate the data offset */ ino = romfs_strnlen(i, ino+ROMFH_SIZE, ROMFS_MAXFN); if (ino >= 0) ino = ((ROMFH_SIZE+ino+1+ROMFH_PAD)&ROMFH_MASK); else ino = 0; i->u.romfs_i.i_metasize = ino; i->u.romfs_i.i_dataoffset = ino+(i->i_ino&ROMFH_MASK); /* Compute permissions */ ino = romfs_modemap[nextfh & ROMFH_TYPE]; /* only "normal" files have ops */ switch (nextfh & ROMFH_TYPE) { case 1: i->i_size = i->u.romfs_i.i_metasize; i->i_op = &romfs_dir_inode_operations; i->i_fop = &romfs_dir_operations; if (nextfh & ROMFH_EXEC) ino |= S_IXUGO; i->i_mode = ino; break; case 2: i->i_fop = &generic_ro_fops; i->i_data.a_ops = &romfs_aops; if (nextfh & ROMFH_EXEC) ino |= S_IXUGO; i->i_mode = ino; break; case 3: i->i_op = &page_symlink_inode_operations; i->i_data.a_ops = &romfs_aops; i->i_mode = ino | S_IRWXUGO; break; default: /* depending on MBZ for sock/fifos */ nextfh = ntohl(ri.spec); nextfh = kdev_t_to_nr(MKDEV(nextfh>>16,nextfh&0xffff)); init_special_inode(i, ino, nextfh); }}static struct super_operations romfs_ops = { read_inode: romfs_read_inode, statfs: romfs_statfs,};static DECLARE_FSTYPE_DEV(romfs_fs_type, "romfs", romfs_read_super);static int __init init_romfs_fs(void){ return register_filesystem(&romfs_fs_type);}static void __exit exit_romfs_fs(void){ unregister_filesystem(&romfs_fs_type);}/* Yes, works even as a module... :) */EXPORT_NO_SYMBOLS;module_init(init_romfs_fs)module_exit(exit_romfs_fs)MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -