⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hppfs_kern.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		*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 + -