📄 hppfs_kern.c
字号:
*size_out += n; if(n < sizeof(data->contents)) break; new = kmalloc(sizeof(*data), GFP_KERNEL); if(new == 0){ printk("hppfs_get_data : data allocation failed\n"); err = -ENOMEM; goto failed_free; } INIT_LIST_HEAD(&new->list); list_add(&new->list, &data->list); data = new; } return(head); failed_free: free_contents(head); failed: return(ERR_PTR(err));}static struct hppfs_private *hppfs_data(void){ struct hppfs_private *data; data = kmalloc(sizeof(*data), GFP_KERNEL); if(data == NULL) return(data); *data = ((struct hppfs_private ) { .host_fd = -1, .len = -1, .contents = NULL } ); return(data);}static int file_mode(int fmode){ if(fmode == (FMODE_READ | FMODE_WRITE)) return(O_RDWR); if(fmode == FMODE_READ) return(O_RDONLY); if(fmode == FMODE_WRITE) return(O_WRONLY); return(0);}static int hppfs_open(struct inode *inode, struct file *file){ struct hppfs_private *data; struct dentry *proc_dentry; char *host_file; int err, fd, type, filter; err = -ENOMEM; data = hppfs_data(); if(data == NULL) goto out; host_file = dentry_name(file->f_path.dentry, strlen("/rw")); if(host_file == NULL) goto out_free2; proc_dentry = HPPFS_I(inode)->proc_dentry; /* XXX This isn't closed anywhere */ data->proc_file = dentry_open(dget(proc_dentry), NULL, file_mode(file->f_mode)); err = PTR_ERR(data->proc_file); if(IS_ERR(data->proc_file)) goto out_free1; type = os_file_type(host_file); if(type == OS_TYPE_FILE){ fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); if(fd >= 0) data->host_fd = fd; else printk("hppfs_open : failed to open '%s', errno = %d\n", host_file, -fd); data->contents = NULL; } else if(type == OS_TYPE_DIR){ fd = open_host_sock(host_file, &filter); if(fd > 0){ data->contents = hppfs_get_data(fd, filter, data->proc_file, file, &data->len); if(!IS_ERR(data->contents)) data->host_fd = fd; } else printk("hppfs_open : failed to open a socket in " "'%s', errno = %d\n", host_file, -fd); } kfree(host_file); file->private_data = data; return(0); out_free1: kfree(host_file); out_free2: free_contents(data->contents); kfree(data); out: return(err);}static int hppfs_dir_open(struct inode *inode, struct file *file){ struct hppfs_private *data; struct dentry *proc_dentry; int err; err = -ENOMEM; data = hppfs_data(); if(data == NULL) goto out; proc_dentry = HPPFS_I(inode)->proc_dentry; data->proc_file = dentry_open(dget(proc_dentry), NULL, file_mode(file->f_mode)); err = PTR_ERR(data->proc_file); if(IS_ERR(data->proc_file)) goto out_free; file->private_data = data; return(0); out_free: kfree(data); out: return(err);}static loff_t hppfs_llseek(struct file *file, loff_t off, int where){ struct hppfs_private *data = file->private_data; struct file *proc_file = data->proc_file; loff_t (*llseek)(struct file *, loff_t, int); loff_t ret; llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; if(llseek != NULL){ ret = (*llseek)(proc_file, off, where); if(ret < 0) return(ret); } return(default_llseek(file, off, where));}static const struct file_operations hppfs_file_fops = { .owner = NULL, .llseek = hppfs_llseek, .read = hppfs_read, .write = hppfs_write, .open = hppfs_open,};struct hppfs_dirent { void *vfs_dirent; filldir_t filldir; struct dentry *dentry;};static int hppfs_filldir(void *d, const char *name, int size, loff_t offset, u64 inode, unsigned int type){ struct hppfs_dirent *dirent = d; if(file_removed(dirent->dentry, name)) return(0); return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, inode, type));}static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir){ struct hppfs_private *data = file->private_data; struct file *proc_file = data->proc_file; int (*readdir)(struct file *, void *, filldir_t); struct hppfs_dirent dirent = ((struct hppfs_dirent) { .vfs_dirent = ent, .filldir = filldir, .dentry = file->f_path.dentry } ); int err; readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; proc_file->f_pos = file->f_pos; err = (*readdir)(proc_file, &dirent, hppfs_filldir); file->f_pos = proc_file->f_pos; return(err);}static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync){ return(0);}static const struct file_operations hppfs_dir_fops = { .owner = NULL, .readdir = hppfs_readdir, .open = hppfs_dir_open, .fsync = hppfs_fsync,};static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf){ sf->f_blocks = 0; sf->f_bfree = 0; sf->f_bavail = 0; sf->f_files = 0; sf->f_ffree = 0; sf->f_type = HPPFS_SUPER_MAGIC; return(0);}static struct inode *hppfs_alloc_inode(struct super_block *sb){ struct hppfs_inode_info *hi; hi = kmalloc(sizeof(*hi), GFP_KERNEL); if(hi == NULL) return(NULL); *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL }); inode_init_once(&hi->vfs_inode); return(&hi->vfs_inode);}void hppfs_delete_inode(struct inode *ino){ clear_inode(ino);}static void hppfs_destroy_inode(struct inode *inode){ kfree(HPPFS_I(inode));}static const struct super_operations hppfs_sbops = { .alloc_inode = hppfs_alloc_inode, .destroy_inode = hppfs_destroy_inode, .read_inode = hppfs_read_inode, .delete_inode = hppfs_delete_inode, .statfs = hppfs_statfs,};static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen){ struct file *proc_file; struct dentry *proc_dentry; int ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); if (IS_ERR(proc_file)) return PTR_ERR(proc_file); ret = proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, buflen); fput(proc_file); return ret;}static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd){ struct file *proc_file; struct dentry *proc_dentry; void *ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); if (IS_ERR(proc_file)) return proc_file; ret = proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); fput(proc_file); return ret;}static const struct inode_operations hppfs_dir_iops = { .lookup = hppfs_lookup,};static const struct inode_operations hppfs_link_iops = { .readlink = hppfs_readlink, .follow_link = hppfs_follow_link,};static int init_inode(struct inode *inode, struct dentry *dentry){ if(S_ISDIR(dentry->d_inode->i_mode)){ inode->i_op = &hppfs_dir_iops; inode->i_fop = &hppfs_dir_fops; } else if(S_ISLNK(dentry->d_inode->i_mode)){ inode->i_op = &hppfs_link_iops; inode->i_fop = &hppfs_file_fops; } else { inode->i_op = &hppfs_file_iops; inode->i_fop = &hppfs_file_fops; } HPPFS_I(inode)->proc_dentry = dentry; return(0);}static int hppfs_fill_super(struct super_block *sb, void *d, int silent){ struct inode *root_inode; struct file_system_type *procfs; struct super_block *proc_sb; int err; err = -ENOENT; procfs = get_fs_type("proc"); if(procfs == NULL) goto out; if(list_empty(&procfs->fs_supers)) goto out; proc_sb = list_entry(procfs->fs_supers.next, struct super_block, s_instances); sb->s_blocksize = 1024; sb->s_blocksize_bits = 10; sb->s_magic = HPPFS_SUPER_MAGIC; sb->s_op = &hppfs_sbops; root_inode = iget(sb, 0); if(root_inode == NULL) goto out; err = init_inode(root_inode, proc_sb->s_root); if(err) goto out_put; err = -ENOMEM; sb->s_root = d_alloc_root(root_inode); if(sb->s_root == NULL) goto out_put; hppfs_read_inode(root_inode); return(0); out_put: iput(root_inode); out: return(err);}static int hppfs_read_super(struct file_system_type *type, int flags, const char *dev_name, void *data, struct vfsmount *mnt){ return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt);}static struct file_system_type hppfs_type = { .owner = THIS_MODULE, .name = "hppfs", .get_sb = hppfs_read_super, .kill_sb = kill_anon_super, .fs_flags = 0,};static int __init init_hppfs(void){ return(register_filesystem(&hppfs_type));}static void __exit exit_hppfs(void){ unregister_filesystem(&hppfs_type);}module_init(init_hppfs)module_exit(exit_hppfs)MODULE_LICENSE("GPL");/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-file-style: "linux" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -