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