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

📄 inode.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
字号:
/* *  inode.c * *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * */#include <linux/module.h>#include <asm/system.h>#include <asm/segment.h>#include <linux/sched.h>#include <linux/smb_fs.h>#include <linux/smbno.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/locks.h>#include <linux/fcntl.h>#include <linux/malloc.h>extern int close_fp(struct file *filp);static void smb_put_inode(struct inode *);static void smb_read_inode(struct inode *);static void smb_put_super(struct super_block *);static void smb_statfs(struct super_block *, struct statfs *, int bufsiz);static struct super_operations smb_sops ={	smb_read_inode,		/* read inode */	smb_notify_change,	/* notify change */	NULL,			/* write inode */	smb_put_inode,		/* put inode */	smb_put_super,		/* put superblock */	NULL,			/* write superblock */	smb_statfs,		/* stat filesystem */	NULL};/* smb_read_inode: Called from iget, it only traverses the allocated   smb_inode_info's and initializes the inode from the data found   there.  It does not allocate or deallocate anything. */static voidsmb_read_inode(struct inode *inode){	/* Our task should be extremely simple here. We only have to	   look up the information somebody else (smb_iget) put into	   the inode tree. */	struct smb_server *server = SMB_SERVER(inode);	struct smb_inode_info *inode_info	= smb_find_inode(server, inode->i_ino);	if (inode_info == NULL)	{		/* Ok, now we're in trouble. The inode info is not		   there. What should we do now??? */		printk("smb_read_inode: inode %ld info not found\n",			inode->i_ino);		return;	}	inode_info->state = SMB_INODE_VALID;	SMB_INOP(inode) = inode_info;	inode->i_mode = inode_info->finfo.f_mode;	inode->i_nlink = inode_info->finfo.f_nlink;	inode->i_uid = inode_info->finfo.f_uid;	inode->i_gid = inode_info->finfo.f_gid;	inode->i_rdev = inode_info->finfo.f_rdev;	inode->i_size = inode_info->finfo.f_size;	inode->i_mtime = inode_info->finfo.f_mtime;	inode->i_ctime = inode_info->finfo.f_ctime;	inode->i_atime = inode_info->finfo.f_atime;	inode->i_blksize = inode_info->finfo.f_blksize;	inode->i_blocks = inode_info->finfo.f_blocks;	if (S_ISREG(inode->i_mode))	{		inode->i_op = &smb_file_inode_operations;	} else if (S_ISDIR(inode->i_mode))	{		inode->i_op = &smb_dir_inode_operations;	} else	{		inode->i_op = NULL;	}}static voidsmb_put_inode(struct inode *inode){	struct smb_server *server = SMB_SERVER(inode);	struct smb_inode_info *info = SMB_INOP(inode);	__u32 mtime = inode->i_mtime;	if (inode->i_count > 1) {		printk("smb_put_inode: in use device %s, inode %ld count=%ld\n",			kdevname(inode->i_dev), inode->i_ino, inode->i_count);		return;	}	if (S_ISDIR(inode->i_mode))	{		smb_invalid_dir_cache(inode->i_ino);	} else	{		/*		 * Clear the length so the info structure can't be found.		 */		info->finfo.len = 0;	}	clear_inode(inode);	/*	 * We don't want the inode to be reused as free if we block here,	 * so temporarily increment i_count.	 */	inode->i_count++;	if (info) {		if (info->finfo.opened != 0)		{			if (smb_proc_close(server, info->finfo.fileid, mtime))			{				/* We can't do anything but complain. */				printk("smb_put_inode: could not close %s\n",					info->finfo.name);			}		}		smb_free_inode_info(info);	} else		printk("smb_put_inode: no inode info??\n");	inode->i_count--;}static voidsmb_put_super(struct super_block *sb){	struct smb_server *server = &(SMB_SBP(sb)->s_server);	smb_proc_disconnect(server);	smb_dont_catch_keepalive(server);	close_fp(server->sock_file);	lock_super(sb);	smb_free_all_inodes(server);	smb_vfree(server->packet);	server->packet = NULL;	sb->s_dev = 0;	smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));	unlock_super(sb);	MOD_DEC_USE_COUNT;}struct smb_mount_data_v4{	int version;	unsigned int fd;	uid_t mounted_uid;	struct sockaddr_in addr;	char server_name[17];	char client_name[17];	char service[64];	char root_path[64];	char username[64];	char password[64];	unsigned short max_xmit;	uid_t uid;	gid_t gid;	mode_t file_mode;	mode_t dir_mode;};static intsmb_get_mount_data(struct smb_mount_data *target, void *source){	struct smb_mount_data_v4 *v4 = (struct smb_mount_data_v4 *) source;	struct smb_mount_data *cur = (struct smb_mount_data *) source;	if (source == NULL)	{		return 1;	}	if (cur->version == SMB_MOUNT_VERSION)	{		memcpy(target, cur, sizeof(struct smb_mount_data));		return 0;	}	if (v4->version == 4)	{		target->version = 5;		target->fd = v4->fd;		target->mounted_uid = v4->mounted_uid;		target->addr = v4->addr;		memcpy(target->server_name, v4->server_name, 17);		memcpy(target->client_name, v4->client_name, 17);		memcpy(target->service, v4->service, 64);		memcpy(target->root_path, v4->root_path, 64);		memcpy(target->username, v4->username, 64);		memcpy(target->password, v4->password, 64);		target->max_xmit = v4->max_xmit;		target->uid = v4->uid;		target->gid = v4->gid;		target->file_mode = v4->file_mode;		target->dir_mode = v4->dir_mode;		memset(target->domain, 0, 64);		strcpy(target->domain, "?");		return 0;	}	return 1;}struct super_block *smb_read_super(struct super_block *sb, void *raw_data, int silent){	struct smb_mount_data data;	struct smb_server *server;	struct smb_sb_info *smb_sb;	unsigned int fd;	struct file *filp;	kdev_t dev = sb->s_dev;	int error;	MOD_INC_USE_COUNT;	if (smb_get_mount_data(&data, raw_data) != 0)	{		printk("smb_read_super: wrong data argument\n");		sb->s_dev = 0;		MOD_DEC_USE_COUNT;		return NULL;	}	fd = data.fd;	if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))	{		printk("smb_read_super: invalid file descriptor\n");		sb->s_dev = 0;		MOD_DEC_USE_COUNT;		return NULL;	}	if (!S_ISSOCK(filp->f_inode->i_mode))	{		printk("smb_read_super: not a socket!\n");		sb->s_dev = 0;		MOD_DEC_USE_COUNT;		return NULL;	}	/* We must malloc our own super-block info */	smb_sb = (struct smb_sb_info *) smb_kmalloc(sizeof(struct smb_sb_info),						    GFP_KERNEL);	if (smb_sb == NULL)	{		printk("smb_read_super: could not alloc smb_sb_info\n");		sb->s_dev = 0;		MOD_DEC_USE_COUNT;		return NULL;	}	filp->f_count += 1;	lock_super(sb);	SMB_SBP(sb) = smb_sb;	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */	sb->s_blocksize_bits = 10;	sb->s_magic = SMB_SUPER_MAGIC;	sb->s_dev = dev;	sb->s_op = &smb_sops;	server = &(SMB_SBP(sb)->s_server);	server->sock_file = filp;	server->lock = 0;	server->wait = NULL;	server->packet = NULL;	server->max_xmit = data.max_xmit;	if (server->max_xmit <= 0)	{		server->max_xmit = SMB_DEF_MAX_XMIT;	}	server->tid = 0;	server->pid = current->pid;	server->mid = current->pid + 20;	server->m = data;	server->m.file_mode = (server->m.file_mode &			       (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;	server->m.dir_mode = (server->m.dir_mode &			      (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;	smb_init_root(server);	error = smb_proc_connect(server);	unlock_super(sb);	if (error < 0)	{		sb->s_dev = 0;		DPRINTK("smb_read_super: Failed connection, bailing out "			"(error = %d).\n", -error);		goto fail;	}	if (server->protocol >= PROTOCOL_LANMAN2)	{		server->case_handling = CASE_DEFAULT;	} else	{		server->case_handling = CASE_LOWER;	}	if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0)	{		sb->s_dev = 0;		printk("smb_read_super: could not get super block "		       "attributes\n");		goto fail;	}	smb_init_root_dirent(server, &(server->root.finfo));	if (!(sb->s_mounted = iget(sb, smb_info_ino(&(server->root)))))	{		sb->s_dev = 0;		printk("smb_read_super: get root inode failed\n");		goto fail;	}	return sb;      fail:	if (server->packet != NULL)	{		smb_vfree(server->packet);		server->packet = NULL;	}	filp->f_count -= 1;	smb_dont_catch_keepalive(server);	smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));	MOD_DEC_USE_COUNT;	return NULL;}static voidsmb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz){	int error;	struct smb_dskattr attr;	struct statfs tmp;	error = smb_proc_dskattr(sb, &attr);	if (error)	{		printk("smb_statfs: dskattr error = %d\n", -error);		attr.total = attr.allocblocks = attr.blocksize =		    attr.free = 0;	}	tmp.f_type = SMB_SUPER_MAGIC;	tmp.f_bsize = attr.blocksize * attr.allocblocks;	tmp.f_blocks = attr.total;	tmp.f_bfree = attr.free;	tmp.f_bavail = attr.free;	tmp.f_files = -1;	tmp.f_ffree = -1;	tmp.f_namelen = SMB_MAXPATHLEN;	memcpy_tofs(buf, &tmp, bufsiz);}intsmb_notify_change(struct inode *inode, struct iattr *attr){	int error = 0;	if ((error = inode_change_ok(inode, attr)) < 0)		return error;	if (((attr->ia_valid & ATTR_UID) &&	     (attr->ia_uid != SMB_SERVER(inode)->m.uid)))		return -EPERM;	if (((attr->ia_valid & ATTR_GID) &&	     (attr->ia_gid != SMB_SERVER(inode)->m.gid)))		return -EPERM;	if (attr->ia_valid & ATTR_MODE) {		struct smb_dirent *fold = SMB_FINFO(inode);		struct smb_dirent finfo;		if (attr->ia_mode & ~(S_IFREG | S_IFDIR |				      S_IRWXU | S_IRWXG | S_IRWXO))			return -EPERM;		memset((char *)&finfo, 0, sizeof(finfo));		finfo.attr = fold->attr;		if((attr->ia_mode & 0200) == 0)		    finfo.attr |= aRONLY;		else		    finfo.attr &= ~aRONLY;		if ((error = smb_proc_setattr(SMB_SERVER(inode),					      inode, &finfo)) >= 0)		{			fold->attr = finfo.attr;			if ((attr->ia_mode & 0200) == 0)				inode->i_mode &= ~0222;			else				inode->i_mode |= 0222;		}	}	if ((attr->ia_valid & ATTR_SIZE) != 0)	{		if ((error = smb_make_open(inode, O_WRONLY)) < 0)			goto fail;		if ((error = smb_proc_trunc(SMB_SERVER(inode),					    SMB_FINFO(inode)->fileid,					    attr->ia_size)) < 0)			goto fail;	}	/* ATTR_CTIME and ATTR_ATIME can not be set via SMB, so ignore it. */	if (attr->ia_valid & ATTR_MTIME)	{		if (smb_make_open(inode, O_WRONLY) != 0)			error = -EACCES;		else			inode->i_mtime = attr->ia_mtime;	}      fail:	smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));	return error;}#ifdef DEBUG_SMB_MALLOCint smb_malloced;int smb_current_kmalloced;int smb_current_vmalloced;#endifstatic struct file_system_type smb_fs_type ={	smb_read_super, "smbfs", 0, NULL};intinit_smb_fs(void){	return register_filesystem(&smb_fs_type);}#ifdef MODULEintinit_module(void){	int status;	DPRINTK("smbfs: init_module called\n");#ifdef DEBUG_SMB_MALLOC	smb_malloced = 0;	smb_current_kmalloced = 0;	smb_current_vmalloced = 0;#endif	smb_init_dir_cache();	if ((status = init_smb_fs()) == 0)		register_symtab(0);	return status;}voidcleanup_module(void){	DPRINTK("smbfs: cleanup_module called\n");	smb_free_dir_cache();	unregister_filesystem(&smb_fs_type);#ifdef DEBUG_SMB_MALLOC	printk("smb_malloced: %d\n", smb_malloced);	printk("smb_current_kmalloced: %d\n", smb_current_kmalloced);	printk("smb_current_vmalloced: %d\n", smb_current_vmalloced);#endif}#endif

⌨️ 快捷键说明

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