Linux Audio

Check our new training course

In-person Linux kernel drivers training

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