Linux Audio

Check our new training course

Loading...
   1/*
   2 *  dir.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, 1999 Wolfram Pienkoss for NLS
   8 *  Modified 1999 Wolfram Pienkoss for directory caching
   9 *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
  10 *
  11 */
  12
  13
  14#include <linux/time.h>
  15#include <linux/errno.h>
  16#include <linux/stat.h>
  17#include <linux/kernel.h>
  18#include <linux/vmalloc.h>
  19#include <linux/mm.h>
  20#include <linux/namei.h>
  21#include <asm/uaccess.h>
  22#include <asm/byteorder.h>
  23
  24#include "ncp_fs.h"
  25
  26static void ncp_read_volume_list(struct file *, void *, filldir_t,
  27				struct ncp_cache_control *);
  28static void ncp_do_readdir(struct file *, void *, filldir_t,
  29				struct ncp_cache_control *);
  30
  31static int ncp_readdir(struct file *, void *, filldir_t);
  32
  33static int ncp_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
  34static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
  35static int ncp_unlink(struct inode *, struct dentry *);
  36static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
  37static int ncp_rmdir(struct inode *, struct dentry *);
  38static int ncp_rename(struct inode *, struct dentry *,
  39	  	      struct inode *, struct dentry *);
  40static int ncp_mknod(struct inode * dir, struct dentry *dentry,
  41		     umode_t mode, dev_t rdev);
  42#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
  43extern int ncp_symlink(struct inode *, struct dentry *, const char *);
  44#else
  45#define ncp_symlink NULL
  46#endif
  47		      
  48const struct file_operations ncp_dir_operations =
  49{
  50	.llseek		= generic_file_llseek,
  51	.read		= generic_read_dir,
  52	.readdir	= ncp_readdir,
  53	.unlocked_ioctl	= ncp_ioctl,
  54#ifdef CONFIG_COMPAT
  55	.compat_ioctl	= ncp_compat_ioctl,
  56#endif
  57};
  58
  59const struct inode_operations ncp_dir_inode_operations =
  60{
  61	.create		= ncp_create,
  62	.lookup		= ncp_lookup,
  63	.unlink		= ncp_unlink,
  64	.symlink	= ncp_symlink,
  65	.mkdir		= ncp_mkdir,
  66	.rmdir		= ncp_rmdir,
  67	.mknod		= ncp_mknod,
  68	.rename		= ncp_rename,
  69	.setattr	= ncp_notify_change,
  70};
  71
  72/*
  73 * Dentry operations routines
  74 */
  75static int ncp_lookup_validate(struct dentry *, struct nameidata *);
  76static int ncp_hash_dentry(const struct dentry *, const struct inode *,
  77		struct qstr *);
  78static int ncp_compare_dentry(const struct dentry *, const struct inode *,
  79		const struct dentry *, const struct inode *,
  80		unsigned int, const char *, const struct qstr *);
  81static int ncp_delete_dentry(const struct dentry *);
  82
  83const struct dentry_operations ncp_dentry_operations =
  84{
  85	.d_revalidate	= ncp_lookup_validate,
  86	.d_hash		= ncp_hash_dentry,
  87	.d_compare	= ncp_compare_dentry,
  88	.d_delete	= ncp_delete_dentry,
  89};
  90
  91#define ncp_namespace(i)	(NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
  92
  93static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
  94{
  95#ifdef CONFIG_NCPFS_SMALLDOS
  96	int ns = ncp_namespace(i);
  97
  98	if ((ns == NW_NS_DOS)
  99#ifdef CONFIG_NCPFS_OS2_NS
 100		|| ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
 101#endif /* CONFIG_NCPFS_OS2_NS */
 102	   )
 103		return 0;
 104#endif /* CONFIG_NCPFS_SMALLDOS */
 105	return 1;
 106}
 107
 108#define ncp_preserve_case(i)	(ncp_namespace(i) != NW_NS_DOS)
 109
 110static inline int ncp_case_sensitive(const struct inode *i)
 111{
 112#ifdef CONFIG_NCPFS_NFS_NS
 113	return ncp_namespace(i) == NW_NS_NFS;
 114#else
 115	return 0;
 116#endif /* CONFIG_NCPFS_NFS_NS */
 117}
 118
 119/*
 120 * Note: leave the hash unchanged if the directory
 121 * is case-sensitive.
 122 */
 123static int 
 124ncp_hash_dentry(const struct dentry *dentry, const struct inode *inode,
 125		struct qstr *this)
 126{
 127	if (!ncp_case_sensitive(inode)) {
 128		struct super_block *sb = dentry->d_sb;
 129		struct nls_table *t;
 130		unsigned long hash;
 131		int i;
 132
 133		t = NCP_IO_TABLE(sb);
 134		hash = init_name_hash();
 135		for (i=0; i<this->len ; i++)
 136			hash = partial_name_hash(ncp_tolower(t, this->name[i]),
 137									hash);
 138		this->hash = end_name_hash(hash);
 139	}
 140	return 0;
 141}
 142
 143static int
 144ncp_compare_dentry(const struct dentry *parent, const struct inode *pinode,
 145		const struct dentry *dentry, const struct inode *inode,
 146		unsigned int len, const char *str, const struct qstr *name)
 147{
 148	if (len != name->len)
 149		return 1;
 150
 151	if (ncp_case_sensitive(pinode))
 152		return strncmp(str, name->name, len);
 153
 154	return ncp_strnicmp(NCP_IO_TABLE(pinode->i_sb), str, name->name, len);
 155}
 156
 157/*
 158 * This is the callback from dput() when d_count is going to 0.
 159 * We use this to unhash dentries with bad inodes.
 160 * Closing files can be safely postponed until iput() - it's done there anyway.
 161 */
 162static int
 163ncp_delete_dentry(const struct dentry * dentry)
 164{
 165	struct inode *inode = dentry->d_inode;
 166
 167	if (inode) {
 168		if (is_bad_inode(inode))
 169			return 1;
 170	} else
 171	{
 172	/* N.B. Unhash negative dentries? */
 173	}
 174	return 0;
 175}
 176
 177static inline int
 178ncp_single_volume(struct ncp_server *server)
 179{
 180	return (server->m.mounted_vol[0] != '\0');
 181}
 182
 183static inline int ncp_is_server_root(struct inode *inode)
 184{
 185	return (!ncp_single_volume(NCP_SERVER(inode)) &&
 186		inode == inode->i_sb->s_root->d_inode);
 187}
 188
 189
 190/*
 191 * This is the callback when the dcache has a lookup hit.
 192 */
 193
 194
 195#ifdef CONFIG_NCPFS_STRONG
 196/* try to delete a readonly file (NW R bit set) */
 197
 198static int
 199ncp_force_unlink(struct inode *dir, struct dentry* dentry)
 200{
 201        int res=0x9c,res2;
 202	struct nw_modify_dos_info info;
 203	__le32 old_nwattr;
 204	struct inode *inode;
 205
 206	memset(&info, 0, sizeof(info));
 207	
 208        /* remove the Read-Only flag on the NW server */
 209	inode = dentry->d_inode;
 210
 211	old_nwattr = NCP_FINFO(inode)->nwattr;
 212	info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
 213	res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
 214	if (res2)
 215		goto leave_me;
 216
 217        /* now try again the delete operation */
 218        res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
 219
 220        if (res)  /* delete failed, set R bit again */
 221        {
 222		info.attributes = old_nwattr;
 223		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
 224		if (res2)
 225                        goto leave_me;
 226        }
 227leave_me:
 228        return(res);
 229}
 230#endif	/* CONFIG_NCPFS_STRONG */
 231
 232#ifdef CONFIG_NCPFS_STRONG
 233static int
 234ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
 235                 struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
 236{
 237	struct nw_modify_dos_info info;
 238        int res=0x90,res2;
 239	struct inode *old_inode = old_dentry->d_inode;
 240	__le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
 241	__le32 new_nwattr = 0; /* shut compiler warning */
 242	int old_nwattr_changed = 0;
 243	int new_nwattr_changed = 0;
 244
 245	memset(&info, 0, sizeof(info));
 246	
 247        /* remove the Read-Only flag on the NW server */
 248
 249	info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 250	res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
 251	if (!res2)
 252		old_nwattr_changed = 1;
 253	if (new_dentry && new_dentry->d_inode) {
 254		new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
 255		info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
 256		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
 257		if (!res2)
 258			new_nwattr_changed = 1;
 259	}
 260        /* now try again the rename operation */
 261	/* but only if something really happened */
 262	if (new_nwattr_changed || old_nwattr_changed) {
 263	        res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
 264        	                                    old_dir, _old_name,
 265                	                            new_dir, _new_name);
 266	} 
 267	if (res)
 268		goto leave_me;
 269	/* file was successfully renamed, so:
 270	   do not set attributes on old file - it no longer exists
 271	   copy attributes from old file to new */
 272	new_nwattr_changed = old_nwattr_changed;
 273	new_nwattr = old_nwattr;
 274	old_nwattr_changed = 0;
 275	
 276leave_me:;
 277	if (old_nwattr_changed) {
 278		info.attributes = old_nwattr;
 279		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
 280		/* ignore errors */
 281	}
 282	if (new_nwattr_changed)	{
 283		info.attributes = new_nwattr;
 284		res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
 285		/* ignore errors */
 286	}
 287        return(res);
 288}
 289#endif	/* CONFIG_NCPFS_STRONG */
 290
 291
 292static int
 293ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
 294{
 295	struct ncp_server *server;
 296	struct dentry *parent;
 297	struct inode *dir;
 298	struct ncp_entry_info finfo;
 299	int res, val = 0, len;
 300	__u8 __name[NCP_MAXPATHLEN + 1];
 301
 302	if (dentry == dentry->d_sb->s_root)
 303		return 1;
 304
 305	if (nd->flags & LOOKUP_RCU)
 306		return -ECHILD;
 307
 308	parent = dget_parent(dentry);
 309	dir = parent->d_inode;
 310
 311	if (!dentry->d_inode)
 312		goto finished;
 313
 314	server = NCP_SERVER(dir);
 315
 316	/*
 317	 * Inspired by smbfs:
 318	 * The default validation is based on dentry age:
 319	 * We set the max age at mount time.  (But each
 320	 * successful server lookup renews the timestamp.)
 321	 */
 322	val = NCP_TEST_AGE(server, dentry);
 323	if (val)
 324		goto finished;
 325
 326	DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
 327		dentry->d_parent->d_name.name, dentry->d_name.name,
 328		NCP_GET_AGE(dentry));
 329
 330	len = sizeof(__name);
 331	if (ncp_is_server_root(dir)) {
 332		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 333				 dentry->d_name.len, 1);
 334		if (!res) {
 335			res = ncp_lookup_volume(server, __name, &(finfo.i));
 336			if (!res)
 337				ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
 338		}
 339	} else {
 340		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 341				 dentry->d_name.len, !ncp_preserve_case(dir));
 342		if (!res)
 343			res = ncp_obtain_info(server, dir, __name, &(finfo.i));
 344	}
 345	finfo.volume = finfo.i.volNumber;
 346	DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
 347		dentry->d_parent->d_name.name, __name, res);
 348	/*
 349	 * If we didn't find it, or if it has a different dirEntNum to
 350	 * what we remember, it's not valid any more.
 351	 */
 352	if (!res) {
 353		struct inode *inode = dentry->d_inode;
 354
 355		mutex_lock(&inode->i_mutex);
 356		if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
 357			ncp_new_dentry(dentry);
 358			val=1;
 359		} else
 360			DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
 361
 362		ncp_update_inode2(inode, &finfo);
 363		mutex_unlock(&inode->i_mutex);
 364	}
 365
 366finished:
 367	DDPRINTK("ncp_lookup_validate: result=%d\n", val);
 368	dput(parent);
 369	return val;
 370}
 371
 372static struct dentry *
 373ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
 374{
 375	struct dentry *dent = dentry;
 376	struct list_head *next;
 377
 378	if (d_validate(dent, parent)) {
 379		if (dent->d_name.len <= NCP_MAXPATHLEN &&
 380		    (unsigned long)dent->d_fsdata == fpos) {
 381			if (!dent->d_inode) {
 382				dput(dent);
 383				dent = NULL;
 384			}
 385			return dent;
 386		}
 387		dput(dent);
 388	}
 389
 390	/* If a pointer is invalid, we search the dentry. */
 391	spin_lock(&parent->d_lock);
 392	next = parent->d_subdirs.next;
 393	while (next != &parent->d_subdirs) {
 394		dent = list_entry(next, struct dentry, d_u.d_child);
 395		if ((unsigned long)dent->d_fsdata == fpos) {
 396			if (dent->d_inode)
 397				dget(dent);
 398			else
 399				dent = NULL;
 400			spin_unlock(&parent->d_lock);
 401			goto out;
 402		}
 403		next = next->next;
 404	}
 405	spin_unlock(&parent->d_lock);
 406	return NULL;
 407
 408out:
 409	return dent;
 410}
 411
 412static time_t ncp_obtain_mtime(struct dentry *dentry)
 413{
 414	struct inode *inode = dentry->d_inode;
 415	struct ncp_server *server = NCP_SERVER(inode);
 416	struct nw_info_struct i;
 417
 418	if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
 419		return 0;
 420
 421	if (ncp_obtain_info(server, inode, NULL, &i))
 422		return 0;
 423
 424	return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
 425}
 426
 427static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
 428{
 429	struct dentry *dentry = filp->f_path.dentry;
 430	struct inode *inode = dentry->d_inode;
 431	struct page *page = NULL;
 432	struct ncp_server *server = NCP_SERVER(inode);
 433	union  ncp_dir_cache *cache = NULL;
 434	struct ncp_cache_control ctl;
 435	int result, mtime_valid = 0;
 436	time_t mtime = 0;
 437
 438	ctl.page  = NULL;
 439	ctl.cache = NULL;
 440
 441	DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
 442		dentry->d_parent->d_name.name, dentry->d_name.name,
 443		(int) filp->f_pos);
 444
 445	result = -EIO;
 446	/* Do not generate '.' and '..' when server is dead. */
 447	if (!ncp_conn_valid(server))
 448		goto out;
 449
 450	result = 0;
 451	if (filp->f_pos == 0) {
 452		if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
 453			goto out;
 454		filp->f_pos = 1;
 455	}
 456	if (filp->f_pos == 1) {
 457		if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))
 458			goto out;
 459		filp->f_pos = 2;
 460	}
 461
 462	page = grab_cache_page(&inode->i_data, 0);
 463	if (!page)
 464		goto read_really;
 465
 466	ctl.cache = cache = kmap(page);
 467	ctl.head  = cache->head;
 468
 469	if (!PageUptodate(page) || !ctl.head.eof)
 470		goto init_cache;
 471
 472	if (filp->f_pos == 2) {
 473		if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
 474			goto init_cache;
 475
 476		mtime = ncp_obtain_mtime(dentry);
 477		mtime_valid = 1;
 478		if ((!mtime) || (mtime != ctl.head.mtime))
 479			goto init_cache;
 480	}
 481
 482	if (filp->f_pos > ctl.head.end)
 483		goto finished;
 484
 485	ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
 486	ctl.ofs  = ctl.fpos / NCP_DIRCACHE_SIZE;
 487	ctl.idx  = ctl.fpos % NCP_DIRCACHE_SIZE;
 488
 489	for (;;) {
 490		if (ctl.ofs != 0) {
 491			ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
 492			if (!ctl.page)
 493				goto invalid_cache;
 494			ctl.cache = kmap(ctl.page);
 495			if (!PageUptodate(ctl.page))
 496				goto invalid_cache;
 497		}
 498		while (ctl.idx < NCP_DIRCACHE_SIZE) {
 499			struct dentry *dent;
 500			int res;
 501
 502			dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
 503						dentry, filp->f_pos);
 504			if (!dent)
 505				goto invalid_cache;
 506			res = filldir(dirent, dent->d_name.name,
 507					dent->d_name.len, filp->f_pos,
 508					dent->d_inode->i_ino, DT_UNKNOWN);
 509			dput(dent);
 510			if (res)
 511				goto finished;
 512			filp->f_pos += 1;
 513			ctl.idx += 1;
 514			if (filp->f_pos > ctl.head.end)
 515				goto finished;
 516		}
 517		if (ctl.page) {
 518			kunmap(ctl.page);
 519			SetPageUptodate(ctl.page);
 520			unlock_page(ctl.page);
 521			page_cache_release(ctl.page);
 522			ctl.page = NULL;
 523		}
 524		ctl.idx  = 0;
 525		ctl.ofs += 1;
 526	}
 527invalid_cache:
 528	if (ctl.page) {
 529		kunmap(ctl.page);
 530		unlock_page(ctl.page);
 531		page_cache_release(ctl.page);
 532		ctl.page = NULL;
 533	}
 534	ctl.cache = cache;
 535init_cache:
 536	ncp_invalidate_dircache_entries(dentry);
 537	if (!mtime_valid) {
 538		mtime = ncp_obtain_mtime(dentry);
 539		mtime_valid = 1;
 540	}
 541	ctl.head.mtime = mtime;
 542	ctl.head.time = jiffies;
 543	ctl.head.eof = 0;
 544	ctl.fpos = 2;
 545	ctl.ofs = 0;
 546	ctl.idx = NCP_DIRCACHE_START;
 547	ctl.filled = 0;
 548	ctl.valid  = 1;
 549read_really:
 550	if (ncp_is_server_root(inode)) {
 551		ncp_read_volume_list(filp, dirent, filldir, &ctl);
 552	} else {
 553		ncp_do_readdir(filp, dirent, filldir, &ctl);
 554	}
 555	ctl.head.end = ctl.fpos - 1;
 556	ctl.head.eof = ctl.valid;
 557finished:
 558	if (ctl.page) {
 559		kunmap(ctl.page);
 560		SetPageUptodate(ctl.page);
 561		unlock_page(ctl.page);
 562		page_cache_release(ctl.page);
 563	}
 564	if (page) {
 565		cache->head = ctl.head;
 566		kunmap(page);
 567		SetPageUptodate(page);
 568		unlock_page(page);
 569		page_cache_release(page);
 570	}
 571out:
 572	return result;
 573}
 574
 575static int
 576ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
 577		struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
 578		int inval_childs)
 579{
 580	struct dentry *newdent, *dentry = filp->f_path.dentry;
 581	struct inode *dir = dentry->d_inode;
 582	struct ncp_cache_control ctl = *ctrl;
 583	struct qstr qname;
 584	int valid = 0;
 585	int hashed = 0;
 586	ino_t ino = 0;
 587	__u8 __name[NCP_MAXPATHLEN + 1];
 588
 589	qname.len = sizeof(__name);
 590	if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
 591			entry->i.entryName, entry->i.nameLen,
 592			!ncp_preserve_entry_case(dir, entry->i.NSCreator)))
 593		return 1; /* I'm not sure */
 594
 595	qname.name = __name;
 596	qname.hash = full_name_hash(qname.name, qname.len);
 597
 598	if (dentry->d_op && dentry->d_op->d_hash)
 599		if (dentry->d_op->d_hash(dentry, dentry->d_inode, &qname) != 0)
 600			goto end_advance;
 601
 602	newdent = d_lookup(dentry, &qname);
 603
 604	if (!newdent) {
 605		newdent = d_alloc(dentry, &qname);
 606		if (!newdent)
 607			goto end_advance;
 608	} else {
 609		hashed = 1;
 610
 611		/* If case sensitivity changed for this volume, all entries below this one
 612		   should be thrown away.  This entry itself is not affected, as its case
 613		   sensitivity is controlled by its own parent. */
 614		if (inval_childs)
 615			shrink_dcache_parent(newdent);
 616
 617		/*
 618		 * NetWare's OS2 namespace is case preserving yet case
 619		 * insensitive.  So we update dentry's name as received from
 620		 * server. Parent dir's i_mutex is locked because we're in
 621		 * readdir.
 622		 */
 623		dentry_update_name_case(newdent, &qname);
 624	}
 625
 626	if (!newdent->d_inode) {
 627		struct inode *inode;
 628
 629		entry->opened = 0;
 630		entry->ino = iunique(dir->i_sb, 2);
 631		inode = ncp_iget(dir->i_sb, entry);
 632		if (inode) {
 633			d_instantiate(newdent, inode);
 634			if (!hashed)
 635				d_rehash(newdent);
 636		}
 637	} else {
 638		struct inode *inode = newdent->d_inode;
 639
 640		mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
 641		ncp_update_inode2(inode, entry);
 642		mutex_unlock(&inode->i_mutex);
 643	}
 644
 645	if (newdent->d_inode) {
 646		ino = newdent->d_inode->i_ino;
 647		newdent->d_fsdata = (void *) ctl.fpos;
 648		ncp_new_dentry(newdent);
 649	}
 650
 651	if (ctl.idx >= NCP_DIRCACHE_SIZE) {
 652		if (ctl.page) {
 653			kunmap(ctl.page);
 654			SetPageUptodate(ctl.page);
 655			unlock_page(ctl.page);
 656			page_cache_release(ctl.page);
 657		}
 658		ctl.cache = NULL;
 659		ctl.idx  -= NCP_DIRCACHE_SIZE;
 660		ctl.ofs  += 1;
 661		ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
 662		if (ctl.page)
 663			ctl.cache = kmap(ctl.page);
 664	}
 665	if (ctl.cache) {
 666		ctl.cache->dentry[ctl.idx] = newdent;
 667		valid = 1;
 668	}
 669	dput(newdent);
 670end_advance:
 671	if (!valid)
 672		ctl.valid = 0;
 673	if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
 674		if (!ino)
 675			ino = find_inode_number(dentry, &qname);
 676		if (!ino)
 677			ino = iunique(dir->i_sb, 2);
 678		ctl.filled = filldir(dirent, qname.name, qname.len,
 679				     filp->f_pos, ino, DT_UNKNOWN);
 680		if (!ctl.filled)
 681			filp->f_pos += 1;
 682	}
 683	ctl.fpos += 1;
 684	ctl.idx  += 1;
 685	*ctrl = ctl;
 686	return (ctl.valid || !ctl.filled);
 687}
 688
 689static void
 690ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
 691			struct ncp_cache_control *ctl)
 692{
 693	struct dentry *dentry = filp->f_path.dentry;
 694	struct inode *inode = dentry->d_inode;
 695	struct ncp_server *server = NCP_SERVER(inode);
 696	struct ncp_volume_info info;
 697	struct ncp_entry_info entry;
 698	int i;
 699
 700	DPRINTK("ncp_read_volume_list: pos=%ld\n",
 701			(unsigned long) filp->f_pos);
 702
 703	for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
 704		int inval_dentry;
 705
 706		if (ncp_get_volume_info_with_number(server, i, &info) != 0)
 707			return;
 708		if (!strlen(info.volume_name))
 709			continue;
 710
 711		DPRINTK("ncp_read_volume_list: found vol: %s\n",
 712			info.volume_name);
 713
 714		if (ncp_lookup_volume(server, info.volume_name,
 715					&entry.i)) {
 716			DPRINTK("ncpfs: could not lookup vol %s\n",
 717				info.volume_name);
 718			continue;
 719		}
 720		inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
 721		entry.volume = entry.i.volNumber;
 722		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
 723			return;
 724	}
 725}
 726
 727static void
 728ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
 729						struct ncp_cache_control *ctl)
 730{
 731	struct dentry *dentry = filp->f_path.dentry;
 732	struct inode *dir = dentry->d_inode;
 733	struct ncp_server *server = NCP_SERVER(dir);
 734	struct nw_search_sequence seq;
 735	struct ncp_entry_info entry;
 736	int err;
 737	void* buf;
 738	int more;
 739	size_t bufsize;
 740
 741	DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
 742		dentry->d_parent->d_name.name, dentry->d_name.name,
 743		(unsigned long) filp->f_pos);
 744	PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
 745		dentry->d_name.name, NCP_FINFO(dir)->volNumber,
 746		NCP_FINFO(dir)->dirEntNum);
 747
 748	err = ncp_initialize_search(server, dir, &seq);
 749	if (err) {
 750		DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
 751		return;
 752	}
 753	/* We MUST NOT use server->buffer_size handshaked with server if we are
 754	   using UDP, as for UDP server uses max. buffer size determined by
 755	   MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 
 756	   So we use 128KB, just to be sure, as there is no way how to know
 757	   this value in advance. */
 758	bufsize = 131072;
 759	buf = vmalloc(bufsize);
 760	if (!buf)
 761		return;
 762	do {
 763		int cnt;
 764		char* rpl;
 765		size_t rpls;
 766
 767		err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
 768		if (err)		/* Error */
 769			break;
 770		if (!cnt)		/* prevent endless loop */
 771			break;
 772		while (cnt--) {
 773			size_t onerpl;
 774			
 775			if (rpls < offsetof(struct nw_info_struct, entryName))
 776				break;	/* short packet */
 777			ncp_extract_file_info(rpl, &entry.i);
 778			onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
 779			if (rpls < onerpl)
 780				break;	/* short packet */
 781			(void)ncp_obtain_nfs_info(server, &entry.i);
 782			rpl += onerpl;
 783			rpls -= onerpl;
 784			entry.volume = entry.i.volNumber;
 785			if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
 786				break;
 787		}
 788	} while (more);
 789	vfree(buf);
 790	return;
 791}
 792
 793int ncp_conn_logged_in(struct super_block *sb)
 794{
 795	struct ncp_server* server = NCP_SBP(sb);
 796	int result;
 797
 798	if (ncp_single_volume(server)) {
 799		int len;
 800		struct dentry* dent;
 801		__u32 volNumber;
 802		__le32 dirEntNum;
 803		__le32 DosDirNum;
 804		__u8 __name[NCP_MAXPATHLEN + 1];
 805
 806		len = sizeof(__name);
 807		result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
 808				    strlen(server->m.mounted_vol), 1);
 809		if (result)
 810			goto out;
 811		result = -ENOENT;
 812		if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
 813			PPRINTK("ncp_conn_logged_in: %s not found\n",
 814				server->m.mounted_vol);
 815			goto out;
 816		}
 817		dent = sb->s_root;
 818		if (dent) {
 819			struct inode* ino = dent->d_inode;
 820			if (ino) {
 821				ncp_update_known_namespace(server, volNumber, NULL);
 822				NCP_FINFO(ino)->volNumber = volNumber;
 823				NCP_FINFO(ino)->dirEntNum = dirEntNum;
 824				NCP_FINFO(ino)->DosDirNum = DosDirNum;
 825				result = 0;
 826			} else {
 827				DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
 828			}
 829		} else {
 830			DPRINTK("ncpfs: sb->s_root == NULL!\n");
 831		}
 832	} else
 833		result = 0;
 834
 835out:
 836	return result;
 837}
 838
 839static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 840{
 841	struct ncp_server *server = NCP_SERVER(dir);
 842	struct inode *inode = NULL;
 843	struct ncp_entry_info finfo;
 844	int error, res, len;
 845	__u8 __name[NCP_MAXPATHLEN + 1];
 846
 847	error = -EIO;
 848	if (!ncp_conn_valid(server))
 849		goto finished;
 850
 851	PPRINTK("ncp_lookup: server lookup for %s/%s\n",
 852		dentry->d_parent->d_name.name, dentry->d_name.name);
 853
 854	len = sizeof(__name);
 855	if (ncp_is_server_root(dir)) {
 856		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 857				 dentry->d_name.len, 1);
 858		if (!res)
 859			res = ncp_lookup_volume(server, __name, &(finfo.i));
 860			if (!res)
 861				ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
 862	} else {
 863		res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 864				 dentry->d_name.len, !ncp_preserve_case(dir));
 865		if (!res)
 866			res = ncp_obtain_info(server, dir, __name, &(finfo.i));
 867	}
 868	PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
 869		dentry->d_parent->d_name.name, __name, res);
 870	/*
 871	 * If we didn't find an entry, make a negative dentry.
 872	 */
 873	if (res)
 874		goto add_entry;
 875
 876	/*
 877	 * Create an inode for the entry.
 878	 */
 879	finfo.opened = 0;
 880	finfo.ino = iunique(dir->i_sb, 2);
 881	finfo.volume = finfo.i.volNumber;
 882	error = -EACCES;
 883	inode = ncp_iget(dir->i_sb, &finfo);
 884
 885	if (inode) {
 886		ncp_new_dentry(dentry);
 887add_entry:
 888		d_add(dentry, inode);
 889		error = 0;
 890	}
 891
 892finished:
 893	PPRINTK("ncp_lookup: result=%d\n", error);
 894	return ERR_PTR(error);
 895}
 896
 897/*
 898 * This code is common to create, mkdir, and mknod.
 899 */
 900static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
 901			struct ncp_entry_info *finfo)
 902{
 903	struct inode *inode;
 904	int error = -EINVAL;
 905
 906	finfo->ino = iunique(dir->i_sb, 2);
 907	inode = ncp_iget(dir->i_sb, finfo);
 908	if (!inode)
 909		goto out_close;
 910	d_instantiate(dentry,inode);
 911	error = 0;
 912out:
 913	return error;
 914
 915out_close:
 916	PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
 917		dentry->d_parent->d_name.name, dentry->d_name.name);
 918	ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
 919	goto out;
 920}
 921
 922int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
 923		   dev_t rdev, __le32 attributes)
 924{
 925	struct ncp_server *server = NCP_SERVER(dir);
 926	struct ncp_entry_info finfo;
 927	int error, result, len;
 928	int opmode;
 929	__u8 __name[NCP_MAXPATHLEN + 1];
 930	
 931	PPRINTK("ncp_create_new: creating %s/%s, mode=%hx\n",
 932		dentry->d_parent->d_name.name, dentry->d_name.name, mode);
 933
 934	ncp_age_dentry(server, dentry);
 935	len = sizeof(__name);
 936	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
 937			   dentry->d_name.len, !ncp_preserve_case(dir));
 938	if (error)
 939		goto out;
 940
 941	error = -EACCES;
 942	
 943	if (S_ISREG(mode) && 
 944	    (server->m.flags & NCP_MOUNT_EXTRAS) && 
 945	    (mode & S_IXUGO))
 946		attributes |= aSYSTEM | aSHARED;
 947	
 948	result = ncp_open_create_file_or_subdir(server, dir, __name,
 949				OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
 950				attributes, AR_READ | AR_WRITE, &finfo);
 951	opmode = O_RDWR;
 952	if (result) {
 953		result = ncp_open_create_file_or_subdir(server, dir, __name,
 954				OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
 955				attributes, AR_WRITE, &finfo);
 956		if (result) {
 957			if (result == 0x87)
 958				error = -ENAMETOOLONG;
 959			else if (result < 0)
 960				error = result;
 961			DPRINTK("ncp_create: %s/%s failed\n",
 962				dentry->d_parent->d_name.name, dentry->d_name.name);
 963			goto out;
 964		}
 965		opmode = O_WRONLY;
 966	}
 967	finfo.access = opmode;
 968	if (ncp_is_nfs_extras(server, finfo.volume)) {
 969		finfo.i.nfs.mode = mode;
 970		finfo.i.nfs.rdev = new_encode_dev(rdev);
 971		if (ncp_modify_nfs_info(server, finfo.volume,
 972					finfo.i.dirEntNum,
 973					mode, new_encode_dev(rdev)) != 0)
 974			goto out;
 975	}
 976
 977	error = ncp_instantiate(dir, dentry, &finfo);
 978out:
 979	return error;
 980}
 981
 982static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 983		struct nameidata *nd)
 984{
 985	return ncp_create_new(dir, dentry, mode, 0, 0);
 986}
 987
 988static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 989{
 990	struct ncp_entry_info finfo;
 991	struct ncp_server *server = NCP_SERVER(dir);
 992	int error, len;
 993	__u8 __name[NCP_MAXPATHLEN + 1];
 994
 995	DPRINTK("ncp_mkdir: making %s/%s\n",
 996		dentry->d_parent->d_name.name, dentry->d_name.name);
 997
 998	ncp_age_dentry(server, dentry);
 999	len = sizeof(__name);
1000	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1001			   dentry->d_name.len, !ncp_preserve_case(dir));
1002	if (error)
1003		goto out;
1004
1005	error = ncp_open_create_file_or_subdir(server, dir, __name,
1006					   OC_MODE_CREATE, aDIR,
1007					   cpu_to_le16(0xffff),
1008					   &finfo);
1009	if (error == 0) {
1010		if (ncp_is_nfs_extras(server, finfo.volume)) {
1011			mode |= S_IFDIR;
1012			finfo.i.nfs.mode = mode;
1013			if (ncp_modify_nfs_info(server,
1014						finfo.volume,
1015						finfo.i.dirEntNum,
1016						mode, 0) != 0)
1017				goto out;
1018		}
1019		error = ncp_instantiate(dir, dentry, &finfo);
1020	} else if (error > 0) {
1021		error = -EACCES;
1022	}
1023out:
1024	return error;
1025}
1026
1027static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1028{
1029	struct ncp_server *server = NCP_SERVER(dir);
1030	int error, result, len;
1031	__u8 __name[NCP_MAXPATHLEN + 1];
1032
1033	DPRINTK("ncp_rmdir: removing %s/%s\n",
1034		dentry->d_parent->d_name.name, dentry->d_name.name);
1035
1036	/*
1037	 * fail with EBUSY if there are still references to this
1038	 * directory.
1039	 */
1040	dentry_unhash(dentry);
1041	error = -EBUSY;
1042	if (!d_unhashed(dentry))
1043		goto out;
1044
1045	len = sizeof(__name);
1046	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1047			   dentry->d_name.len, !ncp_preserve_case(dir));
1048	if (error)
1049		goto out;
1050
1051	result = ncp_del_file_or_subdir(server, dir, __name);
1052	switch (result) {
1053		case 0x00:
1054			error = 0;
1055			break;
1056		case 0x85:	/* unauthorized to delete file */
1057		case 0x8A:	/* unauthorized to delete file */
1058			error = -EACCES;
1059			break;
1060		case 0x8F:
1061		case 0x90:	/* read only */
1062			error = -EPERM;
1063			break;
1064		case 0x9F:	/* in use by another client */
1065			error = -EBUSY;
1066			break;
1067		case 0xA0:	/* directory not empty */
1068			error = -ENOTEMPTY;
1069			break;
1070		case 0xFF:	/* someone deleted file */
1071			error = -ENOENT;
1072			break;
1073		default:
1074			error = result < 0 ? result : -EACCES;
1075			break;
1076       	}
1077out:
1078	return error;
1079}
1080
1081static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1082{
1083	struct inode *inode = dentry->d_inode;
1084	struct ncp_server *server;
1085	int error;
1086
1087	server = NCP_SERVER(dir);
1088	DPRINTK("ncp_unlink: unlinking %s/%s\n",
1089		dentry->d_parent->d_name.name, dentry->d_name.name);
1090	
1091	/*
1092	 * Check whether to close the file ...
1093	 */
1094	if (inode) {
1095		PPRINTK("ncp_unlink: closing file\n");
1096		ncp_make_closed(inode);
1097	}
1098
1099	error = ncp_del_file_or_subdir2(server, dentry);
1100#ifdef CONFIG_NCPFS_STRONG
1101	/* 9C is Invalid path.. It should be 8F, 90 - read only, but
1102	   it is not :-( */
1103	if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1104		error = ncp_force_unlink(dir, dentry);
1105	}
1106#endif
1107	switch (error) {
1108		case 0x00:
1109			DPRINTK("ncp: removed %s/%s\n",
1110				dentry->d_parent->d_name.name, dentry->d_name.name);
1111			break;
1112		case 0x85:
1113		case 0x8A:
1114			error = -EACCES;
1115			break;
1116		case 0x8D:	/* some files in use */
1117		case 0x8E:	/* all files in use */
1118			error = -EBUSY;
1119			break;
1120		case 0x8F:	/* some read only */
1121		case 0x90:	/* all read only */
1122		case 0x9C:	/* !!! returned when in-use or read-only by NW4 */
1123			error = -EPERM;
1124			break;
1125		case 0xFF:
1126			error = -ENOENT;
1127			break;
1128		default:
1129			error = error < 0 ? error : -EACCES;
1130			break;
1131	}
1132	return error;
1133}
1134
1135static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1136		      struct inode *new_dir, struct dentry *new_dentry)
1137{
1138	struct ncp_server *server = NCP_SERVER(old_dir);
1139	int error;
1140	int old_len, new_len;
1141	__u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1142
1143	DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1144		old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1145		new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1146
1147	if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) {
1148		/*
1149		 * fail with EBUSY if there are still references to this
1150		 * directory.
1151		 */
1152		dentry_unhash(new_dentry);
1153		error = -EBUSY;
1154		if (!d_unhashed(new_dentry))
1155			goto out;
1156	}
1157
1158	ncp_age_dentry(server, old_dentry);
1159	ncp_age_dentry(server, new_dentry);
1160
1161	old_len = sizeof(__old_name);
1162	error = ncp_io2vol(server, __old_name, &old_len,
1163			   old_dentry->d_name.name, old_dentry->d_name.len,
1164			   !ncp_preserve_case(old_dir));
1165	if (error)
1166		goto out;
1167
1168	new_len = sizeof(__new_name);
1169	error = ncp_io2vol(server, __new_name, &new_len,
1170			   new_dentry->d_name.name, new_dentry->d_name.len,
1171			   !ncp_preserve_case(new_dir));
1172	if (error)
1173		goto out;
1174
1175	error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1176						      new_dir, __new_name);
1177#ifdef CONFIG_NCPFS_STRONG
1178	if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1179			server->m.flags & NCP_MOUNT_STRONG) {	/* RO */
1180		error = ncp_force_rename(old_dir, old_dentry, __old_name,
1181					 new_dir, new_dentry, __new_name);
1182	}
1183#endif
1184	switch (error) {
1185		case 0x00:
1186               	        DPRINTK("ncp renamed %s -> %s.\n",
1187                                old_dentry->d_name.name,new_dentry->d_name.name);
1188			break;
1189		case 0x9E:
1190			error = -ENAMETOOLONG;
1191			break;
1192		case 0xFF:
1193			error = -ENOENT;
1194			break;
1195		default:
1196			error = error < 0 ? error : -EACCES;
1197			break;
1198	}
1199out:
1200	return error;
1201}
1202
1203static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1204		     umode_t mode, dev_t rdev)
1205{
1206	if (!new_valid_dev(rdev))
1207		return -EINVAL;
1208	if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1209		DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%ho\n", mode);
1210		return ncp_create_new(dir, dentry, mode, rdev, 0);
1211	}
1212	return -EPERM; /* Strange, but true */
1213}
1214
1215/* The following routines are taken directly from msdos-fs */
1216
1217/* Linear day numbers of the respective 1sts in non-leap years. */
1218
1219static int day_n[] =
1220{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1221/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1222
1223
1224extern struct timezone sys_tz;
1225
1226static int utc2local(int time)
1227{
1228	return time - sys_tz.tz_minuteswest * 60;
1229}
1230
1231static int local2utc(int time)
1232{
1233	return time + sys_tz.tz_minuteswest * 60;
1234}
1235
1236/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1237int
1238ncp_date_dos2unix(__le16 t, __le16 d)
1239{
1240	unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1241	int month, year, secs;
1242
1243	/* first subtract and mask after that... Otherwise, if
1244	   date == 0, bad things happen */
1245	month = ((date >> 5) - 1) & 15;
1246	year = date >> 9;
1247	secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1248		86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
1249		year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1250	/* days since 1.1.70 plus 80's leap day */
1251	return local2utc(secs);
1252}
1253
1254
1255/* Convert linear UNIX date to a MS-DOS time/date pair. */
1256void
1257ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1258{
1259	int day, year, nl_day, month;
1260
1261	unix_date = utc2local(unix_date);
1262	*time = cpu_to_le16(
1263		(unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1264		(((unix_date / 3600) % 24) << 11));
1265	day = unix_date / 86400 - 3652;
1266	year = day / 365;
1267	if ((year + 3) / 4 + 365 * year > day)
1268		year--;
1269	day -= (year + 3) / 4 + 365 * year;
1270	if (day == 59 && !(year & 3)) {
1271		nl_day = day;
1272		month = 2;
1273	} else {
1274		nl_day = (year & 3) || day <= 59 ? day : day - 1;
1275		for (month = 1; month < 12; month++)
1276			if (day_n[month] > nl_day)
1277				break;
1278	}
1279	*date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1280}