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

📄 inode.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************//* *	inode.c  --  Inode/Dentry functions for the USB device file system. * *	Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) *	Copyright (C) 2001,2002,2004 Greg Kroah-Hartman (greg@kroah.com) * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2 of the License, or *	(at your option) any later version. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *  History: *   0.1  04.01.2000  Created *   0.2  10.12.2001  converted to use the vfs layer better *//*****************************************************************************/#include <linux/config.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/mount.h>#include <linux/pagemap.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/usb.h>#include <linux/namei.h>#include <linux/usbdevice_fs.h>#include <linux/smp_lock.h>#include <linux/parser.h>#include <linux/notifier.h>#include <asm/byteorder.h>#include "usb.h"#include "hcd.h"static struct super_operations usbfs_ops;static struct file_operations default_file_operations;static struct vfsmount *usbfs_mount;static int usbfs_mount_count;	/* = 0 */static int ignore_mount = 0;static struct dentry *devices_usbfs_dentry;static int num_buses;	/* = 0 */static uid_t devuid;	/* = 0 */static uid_t busuid;	/* = 0 */static uid_t listuid;	/* = 0 */static gid_t devgid;	/* = 0 */static gid_t busgid;	/* = 0 */static gid_t listgid;	/* = 0 */static umode_t devmode = S_IWUSR | S_IRUGO;static umode_t busmode = S_IXUGO | S_IRUGO;static umode_t listmode = S_IRUGO;enum {	Opt_devuid, Opt_devgid, Opt_devmode,	Opt_busuid, Opt_busgid, Opt_busmode,	Opt_listuid, Opt_listgid, Opt_listmode,	Opt_err,};static match_table_t tokens = {	{Opt_devuid, "devuid=%u"},	{Opt_devgid, "devgid=%u"},	{Opt_devmode, "devmode=%o"},	{Opt_busuid, "busuid=%u"},	{Opt_busgid, "busgid=%u"},	{Opt_busmode, "busmode=%o"},	{Opt_listuid, "listuid=%u"},	{Opt_listgid, "listgid=%u"},	{Opt_listmode, "listmode=%o"},	{Opt_err, NULL}};static int parse_options(struct super_block *s, char *data){	char *p;	int option;	/* (re)set to defaults. */	devuid = 0;	busuid = 0;	listuid = 0;	devgid = 0;	busgid = 0;	listgid = 0;	devmode = S_IWUSR | S_IRUGO;	busmode = S_IXUGO | S_IRUGO;	listmode = S_IRUGO;	while ((p = strsep(&data, ",")) != NULL) {		substring_t args[MAX_OPT_ARGS];		int token;		if (!*p)			continue;		token = match_token(p, tokens, args);		switch (token) {		case Opt_devuid:			if (match_int(&args[0], &option))			       return -EINVAL;			devuid = option;			break;		case Opt_devgid:			if (match_int(&args[0], &option))			       return -EINVAL;			devgid = option;			break;		case Opt_devmode:			if (match_octal(&args[0], &option))				return -EINVAL;			devmode = option & S_IRWXUGO;			break;		case Opt_busuid:			if (match_int(&args[0], &option))			       return -EINVAL;			busuid = option;			break;		case Opt_busgid:			if (match_int(&args[0], &option))			       return -EINVAL;			busgid = option;			break;		case Opt_busmode:			if (match_octal(&args[0], &option))				return -EINVAL;			busmode = option & S_IRWXUGO;			break;		case Opt_listuid:			if (match_int(&args[0], &option))			       return -EINVAL;			listuid = option;			break;		case Opt_listgid:			if (match_int(&args[0], &option))			       return -EINVAL;			listgid = option;			break;		case Opt_listmode:			if (match_octal(&args[0], &option))				return -EINVAL;			listmode = option & S_IRWXUGO;			break;		default:			err("usbfs: unrecognised mount option \"%s\" "			    "or missing value\n", p);			return -EINVAL;		}	}	return 0;}static void update_special(struct dentry *special){	special->d_inode->i_uid = listuid;	special->d_inode->i_gid = listgid;	special->d_inode->i_mode = S_IFREG | listmode;}static void update_dev(struct dentry *dev){	dev->d_inode->i_uid = devuid;	dev->d_inode->i_gid = devgid;	dev->d_inode->i_mode = S_IFREG | devmode;}static void update_bus(struct dentry *bus){	struct dentry *dev = NULL;	bus->d_inode->i_uid = busuid;	bus->d_inode->i_gid = busgid;	bus->d_inode->i_mode = S_IFDIR | busmode;	down(&bus->d_inode->i_sem);	list_for_each_entry(dev, &bus->d_subdirs, d_child)		if (dev->d_inode)			update_dev(dev);	up(&bus->d_inode->i_sem);}static void update_sb(struct super_block *sb){	struct dentry *root = sb->s_root;	struct dentry *bus = NULL;	if (!root)		return;	down(&root->d_inode->i_sem);	list_for_each_entry(bus, &root->d_subdirs, d_child) {		if (bus->d_inode) {			switch (S_IFMT & bus->d_inode->i_mode) {			case S_IFDIR:				update_bus(bus);				break;			case S_IFREG:				update_special(bus);				break;			default:				warn("Unknown node %s mode %x found on remount!\n",bus->d_name.name,bus->d_inode->i_mode);				break;			}		}	}	up(&root->d_inode->i_sem);}static int remount(struct super_block *sb, int *flags, char *data){	/* If this is not a real mount,	 * i.e. it's a simple_pin_fs from create_special_files,	 * then ignore it.	 */	if (ignore_mount)		return 0;	if (parse_options(sb, data)) {		warn("usbfs: mount parameter error:");		return -EINVAL;	}	if (usbfs_mount && usbfs_mount->mnt_sb)		update_sb(usbfs_mount->mnt_sb);	return 0;}static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t dev){	struct inode *inode = new_inode(sb);	if (inode) {		inode->i_mode = mode;		inode->i_uid = current->fsuid;		inode->i_gid = current->fsgid;		inode->i_blksize = PAGE_CACHE_SIZE;		inode->i_blocks = 0;		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;		switch (mode & S_IFMT) {		default:			init_special_inode(inode, mode, dev);			break;		case S_IFREG:			inode->i_fop = &default_file_operations;			break;		case S_IFDIR:			inode->i_op = &simple_dir_inode_operations;			inode->i_fop = &simple_dir_operations;			/* directory inodes start off with i_nlink == 2 (for "." entry) */			inode->i_nlink++;			break;		}	}	return inode; }/* SMP-safe */static int usbfs_mknod (struct inode *dir, struct dentry *dentry, int mode,			dev_t dev){	struct inode *inode = usbfs_get_inode(dir->i_sb, mode, dev);	int error = -EPERM;	if (dentry->d_inode)		return -EEXIST;	if (inode) {		d_instantiate(dentry, inode);		dget(dentry);		error = 0;	}	return error;}static int usbfs_mkdir (struct inode *dir, struct dentry *dentry, int mode){	int res;	mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;	res = usbfs_mknod (dir, dentry, mode, 0);	if (!res)		dir->i_nlink++;	return res;}static int usbfs_create (struct inode *dir, struct dentry *dentry, int mode){	mode = (mode & S_IALLUGO) | S_IFREG;	return usbfs_mknod (dir, dentry, mode, 0);}static inline int usbfs_positive (struct dentry *dentry){	return dentry->d_inode && !d_unhashed(dentry);}static int usbfs_empty (struct dentry *dentry){	struct list_head *list;	spin_lock(&dcache_lock);	list_for_each(list, &dentry->d_subdirs) {		struct dentry *de = list_entry(list, struct dentry, d_child);		if (usbfs_positive(de)) {			spin_unlock(&dcache_lock);			return 0;		}	}	spin_unlock(&dcache_lock);	return 1;}static int usbfs_unlink (struct inode *dir, struct dentry *dentry){	struct inode *inode = dentry->d_inode;	down(&inode->i_sem);	dentry->d_inode->i_nlink--;	dput(dentry);	up(&inode->i_sem);	d_delete(dentry);	return 0;}static int usbfs_rmdir(struct inode *dir, struct dentry *dentry){	int error = -ENOTEMPTY;	struct inode * inode = dentry->d_inode;	down(&inode->i_sem);	dentry_unhash(dentry);	if (usbfs_empty(dentry)) {		dentry->d_inode->i_nlink -= 2;		dput(dentry);		inode->i_flags |= S_DEAD;		dir->i_nlink--;		error = 0;	}	up(&inode->i_sem);	if (!error)		d_delete(dentry);	dput(dentry);	return error;}/* default file operations */static ssize_t default_read_file (struct file *file, char __user *buf,				  size_t count, loff_t *ppos){	return 0;}static ssize_t default_write_file (struct file *file, const char __user *buf,				   size_t count, loff_t *ppos){	return count;}static loff_t default_file_lseek (struct file *file, loff_t offset, int orig){	loff_t retval = -EINVAL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -