File: /usr/src/linux/fs/ncpfs/dir.c

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