Linux Audio

Check our new training course

Buildroot integration, development and maintenance

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