Linux Audio

Check our new training course

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