Linux Audio

Check our new training course

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#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");