inode.c revision 02b9984d640873b7b3809e63f81a0d7e13496886
1/*
2 *  inode.c
3 *
4 *  Copyright (C) 1995, 1996 by Volker Lendecke
5 *  Modified for big endian by J.F. Chadima and David S. Miller
6 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7 *  Modified 1998 Wolfram Pienkoss for NLS
8 *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
9 *
10 */
11
12#include <linux/module.h>
13
14#include <asm/uaccess.h>
15#include <asm/byteorder.h>
16
17#include <linux/time.h>
18#include <linux/kernel.h>
19#include <linux/mm.h>
20#include <linux/string.h>
21#include <linux/stat.h>
22#include <linux/errno.h>
23#include <linux/file.h>
24#include <linux/fcntl.h>
25#include <linux/slab.h>
26#include <linux/vmalloc.h>
27#include <linux/init.h>
28#include <linux/vfs.h>
29#include <linux/mount.h>
30#include <linux/seq_file.h>
31#include <linux/namei.h>
32
33#include <net/sock.h>
34
35#include "ncp_fs.h"
36#include "getopt.h"
37
38#define NCP_DEFAULT_FILE_MODE 0600
39#define NCP_DEFAULT_DIR_MODE 0700
40#define NCP_DEFAULT_TIME_OUT 10
41#define NCP_DEFAULT_RETRY_COUNT 20
42
43static void ncp_evict_inode(struct inode *);
44static void ncp_put_super(struct super_block *);
45static int  ncp_statfs(struct dentry *, struct kstatfs *);
46static int  ncp_show_options(struct seq_file *, struct dentry *);
47
48static struct kmem_cache * ncp_inode_cachep;
49
50static struct inode *ncp_alloc_inode(struct super_block *sb)
51{
52	struct ncp_inode_info *ei;
53	ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL);
54	if (!ei)
55		return NULL;
56	return &ei->vfs_inode;
57}
58
59static void ncp_i_callback(struct rcu_head *head)
60{
61	struct inode *inode = container_of(head, struct inode, i_rcu);
62	kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode));
63}
64
65static void ncp_destroy_inode(struct inode *inode)
66{
67	call_rcu(&inode->i_rcu, ncp_i_callback);
68}
69
70static void init_once(void *foo)
71{
72	struct ncp_inode_info *ei = (struct ncp_inode_info *) foo;
73
74	mutex_init(&ei->open_mutex);
75	inode_init_once(&ei->vfs_inode);
76}
77
78static int init_inodecache(void)
79{
80	ncp_inode_cachep = kmem_cache_create("ncp_inode_cache",
81					     sizeof(struct ncp_inode_info),
82					     0, (SLAB_RECLAIM_ACCOUNT|
83						SLAB_MEM_SPREAD),
84					     init_once);
85	if (ncp_inode_cachep == NULL)
86		return -ENOMEM;
87	return 0;
88}
89
90static void destroy_inodecache(void)
91{
92	/*
93	 * Make sure all delayed rcu free inodes are flushed before we
94	 * destroy cache.
95	 */
96	rcu_barrier();
97	kmem_cache_destroy(ncp_inode_cachep);
98}
99
100static int ncp_remount(struct super_block *sb, int *flags, char* data)
101{
102	sync_filesystem(sb);
103	*flags |= MS_NODIRATIME;
104	return 0;
105}
106
107static const struct super_operations ncp_sops =
108{
109	.alloc_inode	= ncp_alloc_inode,
110	.destroy_inode	= ncp_destroy_inode,
111	.drop_inode	= generic_delete_inode,
112	.evict_inode	= ncp_evict_inode,
113	.put_super	= ncp_put_super,
114	.statfs		= ncp_statfs,
115	.remount_fs	= ncp_remount,
116	.show_options	= ncp_show_options,
117};
118
119/*
120 * Fill in the ncpfs-specific information in the inode.
121 */
122static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo)
123{
124	NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
125	NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
126	NCP_FINFO(inode)->volNumber = nwinfo->volume;
127}
128
129void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
130{
131	ncp_update_dirent(inode, nwinfo);
132	NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
133	NCP_FINFO(inode)->access = nwinfo->access;
134	memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
135			sizeof(nwinfo->file_handle));
136	DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
137		nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
138		NCP_FINFO(inode)->dirEntNum);
139}
140
141static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
142{
143	/* NFS namespace mode overrides others if it's set. */
144	DPRINTK(KERN_DEBUG "ncp_update_dates_and_mode: (%s) nfs.mode=0%o\n",
145		nwi->entryName, nwi->nfs.mode);
146	if (nwi->nfs.mode) {
147		/* XXX Security? */
148		inode->i_mode = nwi->nfs.mode;
149	}
150
151	inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
152
153	inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
154	inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
155	inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate);
156	inode->i_atime.tv_nsec = 0;
157	inode->i_mtime.tv_nsec = 0;
158	inode->i_ctime.tv_nsec = 0;
159}
160
161static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
162{
163	struct nw_info_struct *nwi = &nwinfo->i;
164	struct ncp_server *server = NCP_SERVER(inode);
165
166	if (nwi->attributes & aDIR) {
167		inode->i_mode = server->m.dir_mode;
168		/* for directories dataStreamSize seems to be some
169		   Object ID ??? */
170		i_size_write(inode, NCP_BLOCK_SIZE);
171	} else {
172		u32 size;
173
174		inode->i_mode = server->m.file_mode;
175		size = le32_to_cpu(nwi->dataStreamSize);
176		i_size_write(inode, size);
177#ifdef CONFIG_NCPFS_EXTRAS
178		if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
179		 && (nwi->attributes & aSHARED)) {
180			switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
181				case aHIDDEN:
182					if (server->m.flags & NCP_MOUNT_SYMLINKS) {
183						if (/* (size >= NCP_MIN_SYMLINK_SIZE)
184						 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
185							inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
186							NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
187							break;
188						}
189					}
190					/* FALLTHROUGH */
191				case 0:
192					if (server->m.flags & NCP_MOUNT_EXTRAS)
193						inode->i_mode |= S_IRUGO;
194					break;
195				case aSYSTEM:
196					if (server->m.flags & NCP_MOUNT_EXTRAS)
197						inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO;
198					break;
199				/* case aSYSTEM|aHIDDEN: */
200				default:
201					/* reserved combination */
202					break;
203			}
204		}
205#endif
206	}
207	if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO;
208}
209
210void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
211{
212	NCP_FINFO(inode)->flags = 0;
213	if (!atomic_read(&NCP_FINFO(inode)->opened)) {
214		NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
215		ncp_update_attrs(inode, nwinfo);
216	}
217
218	ncp_update_dates(inode, &nwinfo->i);
219	ncp_update_dirent(inode, nwinfo);
220}
221
222/*
223 * Fill in the inode based on the ncp_entry_info structure.  Used only for brand new inodes.
224 */
225static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
226{
227	struct ncp_server *server = NCP_SERVER(inode);
228
229	NCP_FINFO(inode)->flags = 0;
230
231	ncp_update_attrs(inode, nwinfo);
232
233	DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
234
235	set_nlink(inode, 1);
236	inode->i_uid = server->m.uid;
237	inode->i_gid = server->m.gid;
238
239	ncp_update_dates(inode, &nwinfo->i);
240	ncp_update_inode(inode, nwinfo);
241}
242
243#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
244static const struct inode_operations ncp_symlink_inode_operations = {
245	.readlink	= generic_readlink,
246	.follow_link	= page_follow_link_light,
247	.put_link	= page_put_link,
248	.setattr	= ncp_notify_change,
249};
250#endif
251
252/*
253 * Get a new inode.
254 */
255struct inode *
256ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
257{
258	struct inode *inode;
259
260	if (info == NULL) {
261		printk(KERN_ERR "ncp_iget: info is NULL\n");
262		return NULL;
263	}
264
265	inode = new_inode(sb);
266	if (inode) {
267		atomic_set(&NCP_FINFO(inode)->opened, info->opened);
268
269		inode->i_mapping->backing_dev_info = sb->s_bdi;
270		inode->i_ino = info->ino;
271		ncp_set_attr(inode, info);
272		if (S_ISREG(inode->i_mode)) {
273			inode->i_op = &ncp_file_inode_operations;
274			inode->i_fop = &ncp_file_operations;
275		} else if (S_ISDIR(inode->i_mode)) {
276			inode->i_op = &ncp_dir_inode_operations;
277			inode->i_fop = &ncp_dir_operations;
278#ifdef CONFIG_NCPFS_NFS_NS
279		} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
280			init_special_inode(inode, inode->i_mode,
281				new_decode_dev(info->i.nfs.rdev));
282#endif
283#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
284		} else if (S_ISLNK(inode->i_mode)) {
285			inode->i_op = &ncp_symlink_inode_operations;
286			inode->i_data.a_ops = &ncp_symlink_aops;
287#endif
288		} else {
289			make_bad_inode(inode);
290		}
291		insert_inode_hash(inode);
292	} else
293		printk(KERN_ERR "ncp_iget: iget failed!\n");
294	return inode;
295}
296
297static void
298ncp_evict_inode(struct inode *inode)
299{
300	truncate_inode_pages(&inode->i_data, 0);
301	clear_inode(inode);
302
303	if (S_ISDIR(inode->i_mode)) {
304		DDPRINTK("ncp_evict_inode: put directory %ld\n", inode->i_ino);
305	}
306
307	if (ncp_make_closed(inode) != 0) {
308		/* We can't do anything but complain. */
309		printk(KERN_ERR "ncp_evict_inode: could not close\n");
310	}
311}
312
313static void ncp_stop_tasks(struct ncp_server *server) {
314	struct sock* sk = server->ncp_sock->sk;
315
316	lock_sock(sk);
317	sk->sk_error_report = server->error_report;
318	sk->sk_data_ready   = server->data_ready;
319	sk->sk_write_space  = server->write_space;
320	release_sock(sk);
321	del_timer_sync(&server->timeout_tm);
322
323	flush_work(&server->rcv.tq);
324	if (sk->sk_socket->type == SOCK_STREAM)
325		flush_work(&server->tx.tq);
326	else
327		flush_work(&server->timeout_tq);
328}
329
330static int  ncp_show_options(struct seq_file *seq, struct dentry *root)
331{
332	struct ncp_server *server = NCP_SBP(root->d_sb);
333	unsigned int tmp;
334
335	if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID))
336		seq_printf(seq, ",uid=%u",
337			   from_kuid_munged(&init_user_ns, server->m.uid));
338	if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID))
339		seq_printf(seq, ",gid=%u",
340			   from_kgid_munged(&init_user_ns, server->m.gid));
341	if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID))
342		seq_printf(seq, ",owner=%u",
343			   from_kuid_munged(&init_user_ns, server->m.mounted_uid));
344	tmp = server->m.file_mode & S_IALLUGO;
345	if (tmp != NCP_DEFAULT_FILE_MODE)
346		seq_printf(seq, ",mode=0%o", tmp);
347	tmp = server->m.dir_mode & S_IALLUGO;
348	if (tmp != NCP_DEFAULT_DIR_MODE)
349		seq_printf(seq, ",dirmode=0%o", tmp);
350	if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) {
351		tmp = server->m.time_out * 100 / HZ;
352		seq_printf(seq, ",timeout=%u", tmp);
353	}
354	if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT)
355		seq_printf(seq, ",retry=%u", server->m.retry_count);
356	if (server->m.flags != 0)
357		seq_printf(seq, ",flags=%lu", server->m.flags);
358	if (server->m.wdog_pid != NULL)
359		seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid));
360
361	return 0;
362}
363
364static const struct ncp_option ncp_opts[] = {
365	{ "uid",	OPT_INT,	'u' },
366	{ "gid",	OPT_INT,	'g' },
367	{ "owner",	OPT_INT,	'o' },
368	{ "mode",	OPT_INT,	'm' },
369	{ "dirmode",	OPT_INT,	'd' },
370	{ "timeout",	OPT_INT,	't' },
371	{ "retry",	OPT_INT,	'r' },
372	{ "flags",	OPT_INT,	'f' },
373	{ "wdogpid",	OPT_INT,	'w' },
374	{ "ncpfd",	OPT_INT,	'n' },
375	{ "infofd",	OPT_INT,	'i' },	/* v5 */
376	{ "version",	OPT_INT,	'v' },
377	{ NULL,		0,		0 } };
378
379static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) {
380	int optval;
381	char *optarg;
382	unsigned long optint;
383	int version = 0;
384	int ret;
385
386	data->flags = 0;
387	data->int_flags = 0;
388	data->mounted_uid = GLOBAL_ROOT_UID;
389	data->wdog_pid = NULL;
390	data->ncp_fd = ~0;
391	data->time_out = NCP_DEFAULT_TIME_OUT;
392	data->retry_count = NCP_DEFAULT_RETRY_COUNT;
393	data->uid = GLOBAL_ROOT_UID;
394	data->gid = GLOBAL_ROOT_GID;
395	data->file_mode = NCP_DEFAULT_FILE_MODE;
396	data->dir_mode = NCP_DEFAULT_DIR_MODE;
397	data->info_fd = -1;
398	data->mounted_vol[0] = 0;
399
400	while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) {
401		ret = optval;
402		if (ret < 0)
403			goto err;
404		switch (optval) {
405			case 'u':
406				data->uid = make_kuid(current_user_ns(), optint);
407				if (!uid_valid(data->uid)) {
408					ret = -EINVAL;
409					goto err;
410				}
411				break;
412			case 'g':
413				data->gid = make_kgid(current_user_ns(), optint);
414				if (!gid_valid(data->gid)) {
415					ret = -EINVAL;
416					goto err;
417				}
418				break;
419			case 'o':
420				data->mounted_uid = make_kuid(current_user_ns(), optint);
421				if (!uid_valid(data->mounted_uid)) {
422					ret = -EINVAL;
423					goto err;
424				}
425				break;
426			case 'm':
427				data->file_mode = optint;
428				break;
429			case 'd':
430				data->dir_mode = optint;
431				break;
432			case 't':
433				data->time_out = optint;
434				break;
435			case 'r':
436				data->retry_count = optint;
437				break;
438			case 'f':
439				data->flags = optint;
440				break;
441			case 'w':
442				data->wdog_pid = find_get_pid(optint);
443				break;
444			case 'n':
445				data->ncp_fd = optint;
446				break;
447			case 'i':
448				data->info_fd = optint;
449				break;
450			case 'v':
451				ret = -ECHRNG;
452				if (optint < NCP_MOUNT_VERSION_V4)
453					goto err;
454				if (optint > NCP_MOUNT_VERSION_V5)
455					goto err;
456				version = optint;
457				break;
458
459		}
460	}
461	return 0;
462err:
463	put_pid(data->wdog_pid);
464	data->wdog_pid = NULL;
465	return ret;
466}
467
468static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
469{
470	struct ncp_mount_data_kernel data;
471	struct ncp_server *server;
472	struct file *ncp_filp;
473	struct inode *root_inode;
474	struct inode *sock_inode;
475	struct socket *sock;
476	int error;
477	int default_bufsize;
478#ifdef CONFIG_NCPFS_PACKET_SIGNING
479	int options;
480#endif
481	struct ncp_entry_info finfo;
482
483	memset(&data, 0, sizeof(data));
484	server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
485	if (!server)
486		return -ENOMEM;
487	sb->s_fs_info = server;
488
489	error = -EFAULT;
490	if (raw_data == NULL)
491		goto out;
492	switch (*(int*)raw_data) {
493		case NCP_MOUNT_VERSION:
494			{
495				struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
496
497				data.flags = md->flags;
498				data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
499				data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
500				data.wdog_pid = find_get_pid(md->wdog_pid);
501				data.ncp_fd = md->ncp_fd;
502				data.time_out = md->time_out;
503				data.retry_count = md->retry_count;
504				data.uid = make_kuid(current_user_ns(), md->uid);
505				data.gid = make_kgid(current_user_ns(), md->gid);
506				data.file_mode = md->file_mode;
507				data.dir_mode = md->dir_mode;
508				data.info_fd = -1;
509				memcpy(data.mounted_vol, md->mounted_vol,
510					NCP_VOLNAME_LEN+1);
511			}
512			break;
513		case NCP_MOUNT_VERSION_V4:
514			{
515				struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
516
517				data.flags = md->flags;
518				data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
519				data.wdog_pid = find_get_pid(md->wdog_pid);
520				data.ncp_fd = md->ncp_fd;
521				data.time_out = md->time_out;
522				data.retry_count = md->retry_count;
523				data.uid = make_kuid(current_user_ns(), md->uid);
524				data.gid = make_kgid(current_user_ns(), md->gid);
525				data.file_mode = md->file_mode;
526				data.dir_mode = md->dir_mode;
527				data.info_fd = -1;
528			}
529			break;
530		default:
531			error = -ECHRNG;
532			if (memcmp(raw_data, "vers", 4) == 0) {
533				error = ncp_parse_options(&data, raw_data);
534			}
535			if (error)
536				goto out;
537			break;
538	}
539	error = -EINVAL;
540	if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
541	    !gid_valid(data.gid))
542		goto out;
543	error = -EBADF;
544	ncp_filp = fget(data.ncp_fd);
545	if (!ncp_filp)
546		goto out;
547	error = -ENOTSOCK;
548	sock_inode = file_inode(ncp_filp);
549	if (!S_ISSOCK(sock_inode->i_mode))
550		goto out_fput;
551	sock = SOCKET_I(sock_inode);
552	if (!sock)
553		goto out_fput;
554
555	if (sock->type == SOCK_STREAM)
556		default_bufsize = 0xF000;
557	else
558		default_bufsize = 1024;
559
560	sb->s_flags |= MS_NODIRATIME;	/* probably even noatime */
561	sb->s_maxbytes = 0xFFFFFFFFU;
562	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
563	sb->s_blocksize_bits = 10;
564	sb->s_magic = NCP_SUPER_MAGIC;
565	sb->s_op = &ncp_sops;
566	sb->s_d_op = &ncp_dentry_operations;
567	sb->s_bdi = &server->bdi;
568
569	server = NCP_SBP(sb);
570	memset(server, 0, sizeof(*server));
571
572	error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
573	if (error)
574		goto out_fput;
575
576	server->ncp_filp = ncp_filp;
577	server->ncp_sock = sock;
578
579	if (data.info_fd != -1) {
580		struct socket *info_sock;
581
582		error = -EBADF;
583		server->info_filp = fget(data.info_fd);
584		if (!server->info_filp)
585			goto out_bdi;
586		error = -ENOTSOCK;
587		sock_inode = file_inode(server->info_filp);
588		if (!S_ISSOCK(sock_inode->i_mode))
589			goto out_fput2;
590		info_sock = SOCKET_I(sock_inode);
591		if (!info_sock)
592			goto out_fput2;
593		error = -EBADFD;
594		if (info_sock->type != SOCK_STREAM)
595			goto out_fput2;
596		server->info_sock = info_sock;
597	}
598
599/*	server->lock = 0;	*/
600	mutex_init(&server->mutex);
601	server->packet = NULL;
602/*	server->buffer_size = 0;	*/
603/*	server->conn_status = 0;	*/
604/*	server->root_dentry = NULL;	*/
605/*	server->root_setuped = 0;	*/
606	mutex_init(&server->root_setup_lock);
607#ifdef CONFIG_NCPFS_PACKET_SIGNING
608/*	server->sign_wanted = 0;	*/
609/*	server->sign_active = 0;	*/
610#endif
611	init_rwsem(&server->auth_rwsem);
612	server->auth.auth_type = NCP_AUTH_NONE;
613/*	server->auth.object_name_len = 0;	*/
614/*	server->auth.object_name = NULL;	*/
615/*	server->auth.object_type = 0;		*/
616/*	server->priv.len = 0;			*/
617/*	server->priv.data = NULL;		*/
618
619	server->m = data;
620	/* Although anything producing this is buggy, it happens
621	   now because of PATH_MAX changes.. */
622	if (server->m.time_out < 1) {
623		server->m.time_out = 10;
624		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
625	}
626	server->m.time_out = server->m.time_out * HZ / 100;
627	server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
628	server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;
629
630#ifdef CONFIG_NCPFS_NLS
631	/* load the default NLS charsets */
632	server->nls_vol = load_nls_default();
633	server->nls_io = load_nls_default();
634#endif /* CONFIG_NCPFS_NLS */
635
636	atomic_set(&server->dentry_ttl, 0);	/* no caching */
637
638	INIT_LIST_HEAD(&server->tx.requests);
639	mutex_init(&server->rcv.creq_mutex);
640	server->tx.creq		= NULL;
641	server->rcv.creq	= NULL;
642
643	init_timer(&server->timeout_tm);
644#undef NCP_PACKET_SIZE
645#define NCP_PACKET_SIZE 131072
646	error = -ENOMEM;
647	server->packet_size = NCP_PACKET_SIZE;
648	server->packet = vmalloc(NCP_PACKET_SIZE);
649	if (server->packet == NULL)
650		goto out_nls;
651	server->txbuf = vmalloc(NCP_PACKET_SIZE);
652	if (server->txbuf == NULL)
653		goto out_packet;
654	server->rxbuf = vmalloc(NCP_PACKET_SIZE);
655	if (server->rxbuf == NULL)
656		goto out_txbuf;
657
658	lock_sock(sock->sk);
659	server->data_ready	= sock->sk->sk_data_ready;
660	server->write_space	= sock->sk->sk_write_space;
661	server->error_report	= sock->sk->sk_error_report;
662	sock->sk->sk_user_data	= server;
663	sock->sk->sk_data_ready	  = ncp_tcp_data_ready;
664	sock->sk->sk_error_report = ncp_tcp_error_report;
665	if (sock->type == SOCK_STREAM) {
666		server->rcv.ptr = (unsigned char*)&server->rcv.buf;
667		server->rcv.len = 10;
668		server->rcv.state = 0;
669		INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
670		INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
671		sock->sk->sk_write_space = ncp_tcp_write_space;
672	} else {
673		INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
674		INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
675		server->timeout_tm.data = (unsigned long)server;
676		server->timeout_tm.function = ncpdgram_timeout_call;
677	}
678	release_sock(sock->sk);
679
680	ncp_lock_server(server);
681	error = ncp_connect(server);
682	ncp_unlock_server(server);
683	if (error < 0)
684		goto out_rxbuf;
685	DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
686
687	error = -EMSGSIZE;	/* -EREMOTESIDEINCOMPATIBLE */
688#ifdef CONFIG_NCPFS_PACKET_SIGNING
689	if (ncp_negotiate_size_and_options(server, default_bufsize,
690		NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
691	{
692		if (options != NCP_DEFAULT_OPTIONS)
693		{
694			if (ncp_negotiate_size_and_options(server,
695				default_bufsize,
696				options & 2,
697				&(server->buffer_size), &options) != 0)
698
699			{
700				goto out_disconnect;
701			}
702		}
703		ncp_lock_server(server);
704		if (options & 2)
705			server->sign_wanted = 1;
706		ncp_unlock_server(server);
707	}
708	else
709#endif	/* CONFIG_NCPFS_PACKET_SIGNING */
710	if (ncp_negotiate_buffersize(server, default_bufsize,
711  				     &(server->buffer_size)) != 0)
712		goto out_disconnect;
713	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
714
715	memset(&finfo, 0, sizeof(finfo));
716	finfo.i.attributes	= aDIR;
717	finfo.i.dataStreamSize	= 0;	/* ignored */
718	finfo.i.dirEntNum	= 0;
719	finfo.i.DosDirNum	= 0;
720#ifdef CONFIG_NCPFS_SMALLDOS
721	finfo.i.NSCreator	= NW_NS_DOS;
722#endif
723	finfo.volume		= NCP_NUMBER_OF_VOLUMES;
724	/* set dates of mountpoint to Jan 1, 1986; 00:00 */
725	finfo.i.creationTime	= finfo.i.modifyTime
726				= cpu_to_le16(0x0000);
727	finfo.i.creationDate	= finfo.i.modifyDate
728				= finfo.i.lastAccessDate
729				= cpu_to_le16(0x0C21);
730	finfo.i.nameLen		= 0;
731	finfo.i.entryName[0]	= '\0';
732
733	finfo.opened		= 0;
734	finfo.ino		= 2;	/* tradition */
735
736	server->name_space[finfo.volume] = NW_NS_DOS;
737
738	error = -ENOMEM;
739        root_inode = ncp_iget(sb, &finfo);
740        if (!root_inode)
741		goto out_disconnect;
742	DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
743	sb->s_root = d_make_root(root_inode);
744        if (!sb->s_root)
745		goto out_disconnect;
746	return 0;
747
748out_disconnect:
749	ncp_lock_server(server);
750	ncp_disconnect(server);
751	ncp_unlock_server(server);
752out_rxbuf:
753	ncp_stop_tasks(server);
754	vfree(server->rxbuf);
755out_txbuf:
756	vfree(server->txbuf);
757out_packet:
758	vfree(server->packet);
759out_nls:
760#ifdef CONFIG_NCPFS_NLS
761	unload_nls(server->nls_io);
762	unload_nls(server->nls_vol);
763#endif
764	mutex_destroy(&server->rcv.creq_mutex);
765	mutex_destroy(&server->root_setup_lock);
766	mutex_destroy(&server->mutex);
767out_fput2:
768	if (server->info_filp)
769		fput(server->info_filp);
770out_bdi:
771	bdi_destroy(&server->bdi);
772out_fput:
773	/* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
774	 *
775	 * The previously used put_filp(ncp_filp); was bogus, since
776	 * it doesn't perform proper unlocking.
777	 */
778	fput(ncp_filp);
779out:
780	put_pid(data.wdog_pid);
781	sb->s_fs_info = NULL;
782	kfree(server);
783	return error;
784}
785
786static void delayed_free(struct rcu_head *p)
787{
788	struct ncp_server *server = container_of(p, struct ncp_server, rcu);
789#ifdef CONFIG_NCPFS_NLS
790	/* unload the NLS charsets */
791	unload_nls(server->nls_vol);
792	unload_nls(server->nls_io);
793#endif /* CONFIG_NCPFS_NLS */
794	kfree(server);
795}
796
797static void ncp_put_super(struct super_block *sb)
798{
799	struct ncp_server *server = NCP_SBP(sb);
800
801	ncp_lock_server(server);
802	ncp_disconnect(server);
803	ncp_unlock_server(server);
804
805	ncp_stop_tasks(server);
806
807	mutex_destroy(&server->rcv.creq_mutex);
808	mutex_destroy(&server->root_setup_lock);
809	mutex_destroy(&server->mutex);
810
811	if (server->info_filp)
812		fput(server->info_filp);
813	fput(server->ncp_filp);
814	kill_pid(server->m.wdog_pid, SIGTERM, 1);
815	put_pid(server->m.wdog_pid);
816
817	bdi_destroy(&server->bdi);
818	kfree(server->priv.data);
819	kfree(server->auth.object_name);
820	vfree(server->rxbuf);
821	vfree(server->txbuf);
822	vfree(server->packet);
823	call_rcu(&server->rcu, delayed_free);
824}
825
826static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
827{
828	struct dentry* d;
829	struct inode* i;
830	struct ncp_inode_info* ni;
831	struct ncp_server* s;
832	struct ncp_volume_info vi;
833	struct super_block *sb = dentry->d_sb;
834	int err;
835	__u8 dh;
836
837	d = sb->s_root;
838	if (!d) {
839		goto dflt;
840	}
841	i = d->d_inode;
842	if (!i) {
843		goto dflt;
844	}
845	ni = NCP_FINFO(i);
846	if (!ni) {
847		goto dflt;
848	}
849	s = NCP_SBP(sb);
850	if (!s) {
851		goto dflt;
852	}
853	if (!s->m.mounted_vol[0]) {
854		goto dflt;
855	}
856
857	err = ncp_dirhandle_alloc(s, ni->volNumber, ni->DosDirNum, &dh);
858	if (err) {
859		goto dflt;
860	}
861	err = ncp_get_directory_info(s, dh, &vi);
862	ncp_dirhandle_free(s, dh);
863	if (err) {
864		goto dflt;
865	}
866	buf->f_type = NCP_SUPER_MAGIC;
867	buf->f_bsize = vi.sectors_per_block * 512;
868	buf->f_blocks = vi.total_blocks;
869	buf->f_bfree = vi.free_blocks;
870	buf->f_bavail = vi.free_blocks;
871	buf->f_files = vi.total_dir_entries;
872	buf->f_ffree = vi.available_dir_entries;
873	buf->f_namelen = 12;
874	return 0;
875
876	/* We cannot say how much disk space is left on a mounted
877	   NetWare Server, because free space is distributed over
878	   volumes, and the current user might have disk quotas. So
879	   free space is not that simple to determine. Our decision
880	   here is to err conservatively. */
881
882dflt:;
883	buf->f_type = NCP_SUPER_MAGIC;
884	buf->f_bsize = NCP_BLOCK_SIZE;
885	buf->f_blocks = 0;
886	buf->f_bfree = 0;
887	buf->f_bavail = 0;
888	buf->f_namelen = 12;
889	return 0;
890}
891
892int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
893{
894	struct inode *inode = dentry->d_inode;
895	int result = 0;
896	__le32 info_mask;
897	struct nw_modify_dos_info info;
898	struct ncp_server *server;
899
900	result = -EIO;
901
902	server = NCP_SERVER(inode);
903	if (!server)	/* How this could happen? */
904		goto out;
905
906	result = -EPERM;
907	if (IS_DEADDIR(dentry->d_inode))
908		goto out;
909
910	/* ageing the dentry to force validation */
911	ncp_age_dentry(server, dentry);
912
913	result = inode_change_ok(inode, attr);
914	if (result < 0)
915		goto out;
916
917	result = -EPERM;
918	if ((attr->ia_valid & ATTR_UID) && !uid_eq(attr->ia_uid, server->m.uid))
919		goto out;
920
921	if ((attr->ia_valid & ATTR_GID) && !gid_eq(attr->ia_gid, server->m.gid))
922		goto out;
923
924	if (((attr->ia_valid & ATTR_MODE) &&
925	     (attr->ia_mode &
926	      ~(S_IFREG | S_IFDIR | S_IRWXUGO))))
927		goto out;
928
929	info_mask = 0;
930	memset(&info, 0, sizeof(info));
931
932#if 1
933        if ((attr->ia_valid & ATTR_MODE) != 0)
934        {
935		umode_t newmode = attr->ia_mode;
936
937		info_mask |= DM_ATTRIBUTES;
938
939                if (S_ISDIR(inode->i_mode)) {
940                	newmode &= server->m.dir_mode;
941		} else {
942#ifdef CONFIG_NCPFS_EXTRAS
943			if (server->m.flags & NCP_MOUNT_EXTRAS) {
944				/* any non-default execute bit set */
945				if (newmode & ~server->m.file_mode & S_IXUGO)
946					info.attributes |= aSHARED | aSYSTEM;
947				/* read for group/world and not in default file_mode */
948				else if (newmode & ~server->m.file_mode & S_IRUGO)
949					info.attributes |= aSHARED;
950			} else
951#endif
952				newmode &= server->m.file_mode;
953                }
954                if (newmode & S_IWUGO)
955                	info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
956                else
957			info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
958
959#ifdef CONFIG_NCPFS_NFS_NS
960		if (ncp_is_nfs_extras(server, NCP_FINFO(inode)->volNumber)) {
961			result = ncp_modify_nfs_info(server,
962						     NCP_FINFO(inode)->volNumber,
963						     NCP_FINFO(inode)->dirEntNum,
964						     attr->ia_mode, 0);
965			if (result != 0)
966				goto out;
967			info.attributes &= ~(aSHARED | aSYSTEM);
968			{
969				/* mark partial success */
970				struct iattr tmpattr;
971
972				tmpattr.ia_valid = ATTR_MODE;
973				tmpattr.ia_mode = attr->ia_mode;
974
975				setattr_copy(inode, &tmpattr);
976				mark_inode_dirty(inode);
977			}
978		}
979#endif
980        }
981#endif
982
983	/* Do SIZE before attributes, otherwise mtime together with size does not work...
984	 */
985	if ((attr->ia_valid & ATTR_SIZE) != 0) {
986		int written;
987
988		DPRINTK("ncpfs: trying to change size to %ld\n",
989			attr->ia_size);
990
991		if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
992			result = -EACCES;
993			goto out;
994		}
995		ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
996			  attr->ia_size, 0, "", &written);
997
998		/* According to ndir, the changes only take effect after
999		   closing the file */
1000		ncp_inode_close(inode);
1001		result = ncp_make_closed(inode);
1002		if (result)
1003			goto out;
1004
1005		if (attr->ia_size != i_size_read(inode)) {
1006			truncate_setsize(inode, attr->ia_size);
1007			mark_inode_dirty(inode);
1008		}
1009	}
1010	if ((attr->ia_valid & ATTR_CTIME) != 0) {
1011		info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
1012		ncp_date_unix2dos(attr->ia_ctime.tv_sec,
1013			     &info.creationTime, &info.creationDate);
1014	}
1015	if ((attr->ia_valid & ATTR_MTIME) != 0) {
1016		info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
1017		ncp_date_unix2dos(attr->ia_mtime.tv_sec,
1018				  &info.modifyTime, &info.modifyDate);
1019	}
1020	if ((attr->ia_valid & ATTR_ATIME) != 0) {
1021		__le16 dummy;
1022		info_mask |= (DM_LAST_ACCESS_DATE);
1023		ncp_date_unix2dos(attr->ia_atime.tv_sec,
1024				  &dummy, &info.lastAccessDate);
1025	}
1026	if (info_mask != 0) {
1027		result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
1028				      inode, info_mask, &info);
1029		if (result != 0) {
1030			if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
1031				/* NetWare seems not to allow this. I
1032				   do not know why. So, just tell the
1033				   user everything went fine. This is
1034				   a terrible hack, but I do not know
1035				   how to do this correctly. */
1036				result = 0;
1037			} else
1038				goto out;
1039		}
1040#ifdef CONFIG_NCPFS_STRONG
1041		if ((!result) && (info_mask & DM_ATTRIBUTES))
1042			NCP_FINFO(inode)->nwattr = info.attributes;
1043#endif
1044	}
1045	if (result)
1046		goto out;
1047
1048	setattr_copy(inode, attr);
1049	mark_inode_dirty(inode);
1050
1051out:
1052	if (result > 0)
1053		result = -EACCES;
1054	return result;
1055}
1056
1057static struct dentry *ncp_mount(struct file_system_type *fs_type,
1058	int flags, const char *dev_name, void *data)
1059{
1060	return mount_nodev(fs_type, flags, data, ncp_fill_super);
1061}
1062
1063static struct file_system_type ncp_fs_type = {
1064	.owner		= THIS_MODULE,
1065	.name		= "ncpfs",
1066	.mount		= ncp_mount,
1067	.kill_sb	= kill_anon_super,
1068	.fs_flags	= FS_BINARY_MOUNTDATA,
1069};
1070MODULE_ALIAS_FS("ncpfs");
1071
1072static int __init init_ncp_fs(void)
1073{
1074	int err;
1075	DPRINTK("ncpfs: init_ncp_fs called\n");
1076
1077	err = init_inodecache();
1078	if (err)
1079		goto out1;
1080	err = register_filesystem(&ncp_fs_type);
1081	if (err)
1082		goto out;
1083	return 0;
1084out:
1085	destroy_inodecache();
1086out1:
1087	return err;
1088}
1089
1090static void __exit exit_ncp_fs(void)
1091{
1092	DPRINTK("ncpfs: exit_ncp_fs called\n");
1093	unregister_filesystem(&ncp_fs_type);
1094	destroy_inodecache();
1095}
1096
1097module_init(init_ncp_fs)
1098module_exit(exit_ncp_fs)
1099MODULE_LICENSE("GPL");
1100