inode.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,013 行 · 第 1/2 页

C
1,013
字号
		sock_inode = server->info_filp->f_dentry->d_inode;		if (!S_ISSOCK(sock_inode->i_mode))			goto out_fput2;		info_sock = SOCKET_I(sock_inode);		if (!info_sock)			goto out_fput2;		error = -EBADFD;		if (info_sock->type != SOCK_STREAM)			goto out_fput2;		server->info_sock = info_sock;	}/*	server->lock = 0;	*/	init_MUTEX(&server->sem);	server->packet = NULL;/*	server->buffer_size = 0;	*//*	server->conn_status = 0;	*//*	server->root_dentry = NULL;	*//*	server->root_setuped = 0;	*/#ifdef CONFIG_NCPFS_PACKET_SIGNING/*	server->sign_wanted = 0;	*//*	server->sign_active = 0;	*/#endif	server->auth.auth_type = NCP_AUTH_NONE;/*	server->auth.object_name_len = 0;	*//*	server->auth.object_name = NULL;	*//*	server->auth.object_type = 0;		*//*	server->priv.len = 0;			*//*	server->priv.data = NULL;		*/	server->m = data;	/* Althought anything producing this is buggy, it happens	   now because of PATH_MAX changes.. */	if (server->m.time_out < 1) {		server->m.time_out = 10;		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");	}	server->m.time_out = server->m.time_out * HZ / 100;	server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;	server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;#ifdef CONFIG_NCPFS_NLS	/* load the default NLS charsets */	server->nls_vol = load_nls_default();	server->nls_io = load_nls_default();#endif /* CONFIG_NCPFS_NLS */	server->dentry_ttl = 0;	/* no caching */	INIT_LIST_HEAD(&server->tx.requests);	init_MUTEX(&server->rcv.creq_sem);	server->tx.creq		= NULL;	server->rcv.creq	= NULL;	server->data_ready	= sock->sk->sk_data_ready;	server->write_space	= sock->sk->sk_write_space;	server->error_report	= sock->sk->sk_error_report;	sock->sk->sk_user_data	= server;	init_timer(&server->timeout_tm);#undef NCP_PACKET_SIZE#define NCP_PACKET_SIZE 131072	error = -ENOMEM;	server->packet_size = NCP_PACKET_SIZE;	server->packet = vmalloc(NCP_PACKET_SIZE);	if (server->packet == NULL)		goto out_nls;	sock->sk->sk_data_ready	  = ncp_tcp_data_ready;	sock->sk->sk_error_report = ncp_tcp_error_report;	if (sock->type == SOCK_STREAM) {		server->rcv.ptr = (unsigned char*)&server->rcv.buf;		server->rcv.len = 10;		server->rcv.state = 0;		INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc, server);		INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc, server);		sock->sk->sk_write_space = ncp_tcp_write_space;	} else {		INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc, server);		INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc, server);		server->timeout_tm.data = (unsigned long)server;		server->timeout_tm.function = ncpdgram_timeout_call;	}	ncp_lock_server(server);	error = ncp_connect(server);	ncp_unlock_server(server);	if (error < 0)		goto out_packet;	DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));	error = -EMSGSIZE;	/* -EREMOTESIDEINCOMPATIBLE */#ifdef CONFIG_NCPFS_PACKET_SIGNING	if (ncp_negotiate_size_and_options(server, default_bufsize,		NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)	{		if (options != NCP_DEFAULT_OPTIONS)		{			if (ncp_negotiate_size_and_options(server, 				default_bufsize,				options & 2, 				&(server->buffer_size), &options) != 0)							{				goto out_disconnect;			}		}		if (options & 2)			server->sign_wanted = 1;	}	else #endif	/* CONFIG_NCPFS_PACKET_SIGNING */	if (ncp_negotiate_buffersize(server, default_bufsize,  				     &(server->buffer_size)) != 0)		goto out_disconnect;	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);	memset(&finfo, 0, sizeof(finfo));	finfo.i.attributes	= aDIR;	finfo.i.dataStreamSize	= 0;	/* ignored */	finfo.i.dirEntNum	= 0;	finfo.i.DosDirNum	= 0;#ifdef CONFIG_NCPFS_SMALLDOS	finfo.i.NSCreator	= NW_NS_DOS;#endif	finfo.volume		= NCP_NUMBER_OF_VOLUMES;	/* set dates of mountpoint to Jan 1, 1986; 00:00 */	finfo.i.creationTime	= finfo.i.modifyTime				= cpu_to_le16(0x0000);	finfo.i.creationDate	= finfo.i.modifyDate				= finfo.i.lastAccessDate				= cpu_to_le16(0x0C21);	finfo.i.nameLen		= 0;	finfo.i.entryName[0]	= '\0';	finfo.opened		= 0;	finfo.ino		= 2;	/* tradition */	server->name_space[finfo.volume] = NW_NS_DOS;	error = -ENOMEM;        root_inode = ncp_iget(sb, &finfo);        if (!root_inode)		goto out_disconnect;	DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);	sb->s_root = d_alloc_root(root_inode);        if (!sb->s_root)		goto out_no_root;	sb->s_root->d_op = &ncp_root_dentry_operations;	return 0;out_no_root:	iput(root_inode);out_disconnect:	ncp_lock_server(server);	ncp_disconnect(server);	ncp_unlock_server(server);out_packet:	ncp_stop_tasks(server);	vfree(server->packet);out_nls:#ifdef CONFIG_NCPFS_NLS	unload_nls(server->nls_io);	unload_nls(server->nls_vol);#endifout_fput2:	if (server->info_filp)		fput(server->info_filp);out_fput:	/* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:	 * 	 * The previously used put_filp(ncp_filp); was bogous, since	 * it doesn't proper unlocking.	 */	fput(ncp_filp);out:	sb->s_fs_info = NULL;	kfree(server);	return error;}static void ncp_put_super(struct super_block *sb){	struct ncp_server *server = NCP_SBP(sb);	ncp_lock_server(server);	ncp_disconnect(server);	ncp_unlock_server(server);	ncp_stop_tasks(server);#ifdef CONFIG_NCPFS_NLS	/* unload the NLS charsets */	if (server->nls_vol)	{		unload_nls(server->nls_vol);		server->nls_vol = NULL;	}	if (server->nls_io)	{		unload_nls(server->nls_io);		server->nls_io = NULL;	}#endif /* CONFIG_NCPFS_NLS */	if (server->info_filp)		fput(server->info_filp);	fput(server->ncp_filp);	kill_proc(server->m.wdog_pid, SIGTERM, 1);	if (server->priv.data) 		ncp_kfree_s(server->priv.data, server->priv.len);	if (server->auth.object_name)		ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);	vfree(server->packet);	sb->s_fs_info = NULL;	kfree(server);}static int ncp_statfs(struct super_block *sb, struct kstatfs *buf){	struct dentry* d;	struct inode* i;	struct ncp_inode_info* ni;	struct ncp_server* s;	struct ncp_volume_info vi;	int err;	__u8 dh;		d = sb->s_root;	if (!d) {		goto dflt;	}	i = d->d_inode;	if (!i) {		goto dflt;	}	ni = NCP_FINFO(i);	if (!ni) {		goto dflt;	}	s = NCP_SBP(sb);	if (!s) {		goto dflt;	}	if (!s->m.mounted_vol[0]) {		goto dflt;	}	err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);	if (err) {		goto dflt;	}	err = ncp_get_directory_info(s, dh, &vi);	ncp_dirhandle_free(s, dh);	if (err) {		goto dflt;	}	buf->f_type = NCP_SUPER_MAGIC;	buf->f_bsize = vi.sectors_per_block * 512;	buf->f_blocks = vi.total_blocks;	buf->f_bfree = vi.free_blocks;	buf->f_bavail = vi.free_blocks;	buf->f_files = vi.total_dir_entries;	buf->f_ffree = vi.available_dir_entries;	buf->f_namelen = 12;	return 0;	/* We cannot say how much disk space is left on a mounted	   NetWare Server, because free space is distributed over	   volumes, and the current user might have disk quotas. So	   free space is not that simple to determine. Our decision	   here is to err conservatively. */dflt:;	buf->f_type = NCP_SUPER_MAGIC;	buf->f_bsize = NCP_BLOCK_SIZE;	buf->f_blocks = 0;	buf->f_bfree = 0;	buf->f_bavail = 0;	buf->f_namelen = 12;	return 0;}int ncp_notify_change(struct dentry *dentry, struct iattr *attr){	struct inode *inode = dentry->d_inode;	int result = 0;	__le32 info_mask;	struct nw_modify_dos_info info;	struct ncp_server *server;	result = -EIO;	lock_kernel();		server = NCP_SERVER(inode);	if ((!server) || !ncp_conn_valid(server))		goto out;	/* ageing the dentry to force validation */	ncp_age_dentry(server, dentry);	result = inode_change_ok(inode, attr);	if (result < 0)		goto out;	result = -EPERM;	if (((attr->ia_valid & ATTR_UID) &&	     (attr->ia_uid != server->m.uid)))		goto out;	if (((attr->ia_valid & ATTR_GID) &&	     (attr->ia_gid != server->m.gid)))		goto out;	if (((attr->ia_valid & ATTR_MODE) &&	     (attr->ia_mode &	      ~(S_IFREG | S_IFDIR | S_IRWXUGO))))		goto out;	info_mask = 0;	memset(&info, 0, sizeof(info));#if 1         if ((attr->ia_valid & ATTR_MODE) != 0)        {		umode_t newmode = attr->ia_mode;		info_mask |= DM_ATTRIBUTES;                if (S_ISDIR(inode->i_mode)) {                	newmode &= server->m.dir_mode;		} else {#ifdef CONFIG_NCPFS_EXTRAS						if (server->m.flags & NCP_MOUNT_EXTRAS) {				/* any non-default execute bit set */				if (newmode & ~server->m.file_mode & S_IXUGO)					info.attributes |= aSHARED | aSYSTEM;				/* read for group/world and not in default file_mode */				else if (newmode & ~server->m.file_mode & S_IRUGO)					info.attributes |= aSHARED;			} else#endif				newmode &= server->m.file_mode;			                }                if (newmode & S_IWUGO)                	info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);                else			info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);#ifdef CONFIG_NCPFS_NFS_NS		if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {			result = ncp_modify_nfs_info(server,						     NCP_FINFO(inode)->volNumber,						     NCP_FINFO(inode)->dirEntNum,						     attr->ia_mode, 0);			if (result != 0)				goto out;			info.attributes &= ~(aSHARED | aSYSTEM);			{				/* mark partial success */				struct iattr tmpattr;								tmpattr.ia_valid = ATTR_MODE;				tmpattr.ia_mode = attr->ia_mode;				result = inode_setattr(inode, &tmpattr);				if (result)					goto out;			}		}#endif        }#endif	/* Do SIZE before attributes, otherwise mtime together with size does not work...	 */	if ((attr->ia_valid & ATTR_SIZE) != 0) {		int written;		DPRINTK("ncpfs: trying to change size to %ld\n",			attr->ia_size);		if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {			result = -EACCES;			goto out;		}		ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,			  attr->ia_size, 0, "", &written);		/* According to ndir, the changes only take effect after		   closing the file */		ncp_inode_close(inode);		result = ncp_make_closed(inode);		if (result)			goto out;		{			struct iattr tmpattr;						tmpattr.ia_valid = ATTR_SIZE;			tmpattr.ia_size = attr->ia_size;						result = inode_setattr(inode, &tmpattr);			if (result)				goto out;		}	}	if ((attr->ia_valid & ATTR_CTIME) != 0) {		info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);		ncp_date_unix2dos(attr->ia_ctime.tv_sec,			     &info.creationTime, &info.creationDate);	}	if ((attr->ia_valid & ATTR_MTIME) != 0) {		info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);		ncp_date_unix2dos(attr->ia_mtime.tv_sec,				  &info.modifyTime, &info.modifyDate);	}	if ((attr->ia_valid & ATTR_ATIME) != 0) {		__le16 dummy;		info_mask |= (DM_LAST_ACCESS_DATE);		ncp_date_unix2dos(attr->ia_atime.tv_sec,				  &dummy, &info.lastAccessDate);	}	if (info_mask != 0) {		result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),				      inode, info_mask, &info);		if (result != 0) {			result = -EACCES;			if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {				/* NetWare seems not to allow this. I				   do not know why. So, just tell the				   user everything went fine. This is				   a terrible hack, but I do not know				   how to do this correctly. */				result = 0;			} else				goto out;		}#ifdef CONFIG_NCPFS_STRONG				if ((!result) && (info_mask & DM_ATTRIBUTES))			NCP_FINFO(inode)->nwattr = info.attributes;#endif	}	if (!result)		result = inode_setattr(inode, attr);out:	unlock_kernel();	return result;}#ifdef DEBUG_NCP_MALLOCint ncp_malloced;int ncp_current_malloced;#endifstatic struct super_block *ncp_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *data){	return get_sb_nodev(fs_type, flags, data, ncp_fill_super);}static struct file_system_type ncp_fs_type = {	.owner		= THIS_MODULE,	.name		= "ncpfs",	.get_sb		= ncp_get_sb,	.kill_sb	= kill_anon_super,};static int __init init_ncp_fs(void){	int err;	DPRINTK("ncpfs: init_module called\n");#ifdef DEBUG_NCP_MALLOC	ncp_malloced = 0;	ncp_current_malloced = 0;#endif	err = init_inodecache();	if (err)		goto out1;	err = register_filesystem(&ncp_fs_type);	if (err)		goto out;	return 0;out:	destroy_inodecache();out1:	return err;}static void __exit exit_ncp_fs(void){	DPRINTK("ncpfs: cleanup_module called\n");	unregister_filesystem(&ncp_fs_type);	destroy_inodecache();#ifdef DEBUG_NCP_MALLOC	PRINTK("ncp_malloced: %d\n", ncp_malloced);	PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);#endif}module_init(init_ncp_fs)module_exit(exit_ncp_fs)MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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