d_hash_and_lookup(): export, switch open-coded instances
[sfrench/cifs-2.6.git] / 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  *  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
26 static void ncp_read_volume_list(struct file *, void *, filldir_t,
27                                 struct ncp_cache_control *);
28 static void ncp_do_readdir(struct file *, void *, filldir_t,
29                                 struct ncp_cache_control *);
30
31 static int ncp_readdir(struct file *, void *, filldir_t);
32
33 static int ncp_create(struct inode *, struct dentry *, umode_t, bool);
34 static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int);
35 static int ncp_unlink(struct inode *, struct dentry *);
36 static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
37 static int ncp_rmdir(struct inode *, struct dentry *);
38 static int ncp_rename(struct inode *, struct dentry *,
39                       struct inode *, struct dentry *);
40 static 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)
43 extern int ncp_symlink(struct inode *, struct dentry *, const char *);
44 #else
45 #define ncp_symlink NULL
46 #endif
47                       
48 const 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
59 const 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  */
75 static int ncp_lookup_validate(struct dentry *, unsigned int);
76 static int ncp_hash_dentry(const struct dentry *, const struct inode *,
77                 struct qstr *);
78 static 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 *);
81 static int ncp_delete_dentry(const struct dentry *);
82
83 const 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
93 static 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
110 static 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  */
123 static int 
124 ncp_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
143 static int
144 ncp_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  */
162 static int
163 ncp_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
177 static inline int
178 ncp_single_volume(struct ncp_server *server)
179 {
180         return (server->m.mounted_vol[0] != '\0');
181 }
182
183 static 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
198 static int
199 ncp_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         }
227 leave_me:
228         return(res);
229 }
230 #endif  /* CONFIG_NCPFS_STRONG */
231
232 #ifdef CONFIG_NCPFS_STRONG
233 static int
234 ncp_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         
276 leave_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
292 static int
293 ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
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 (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
366 finished:
367         DDPRINTK("ncp_lookup_validate: result=%d\n", val);
368         dput(parent);
369         return val;
370 }
371
372 static struct dentry *
373 ncp_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
408 out:
409         return dent;
410 }
411
412 static 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
427 static 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         }
527 invalid_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;
535 init_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;
549 read_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;
557 finished:
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         }
571 out:
572         return result;
573 }
574
575 static int
576 ncp_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
597         newdent = d_hash_and_lookup(dentry, &qname);
598         if (unlikely(IS_ERR(newdent)))
599                 goto end_advance;
600         if (!newdent) {
601                 newdent = d_alloc(dentry, &qname);
602                 if (!newdent)
603                         goto end_advance;
604         } else {
605                 hashed = 1;
606
607                 /* If case sensitivity changed for this volume, all entries below this one
608                    should be thrown away.  This entry itself is not affected, as its case
609                    sensitivity is controlled by its own parent. */
610                 if (inval_childs)
611                         shrink_dcache_parent(newdent);
612
613                 /*
614                  * NetWare's OS2 namespace is case preserving yet case
615                  * insensitive.  So we update dentry's name as received from
616                  * server. Parent dir's i_mutex is locked because we're in
617                  * readdir.
618                  */
619                 dentry_update_name_case(newdent, &qname);
620         }
621
622         if (!newdent->d_inode) {
623                 struct inode *inode;
624
625                 entry->opened = 0;
626                 entry->ino = iunique(dir->i_sb, 2);
627                 inode = ncp_iget(dir->i_sb, entry);
628                 if (inode) {
629                         d_instantiate(newdent, inode);
630                         if (!hashed)
631                                 d_rehash(newdent);
632                 }
633         } else {
634                 struct inode *inode = newdent->d_inode;
635
636                 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
637                 ncp_update_inode2(inode, entry);
638                 mutex_unlock(&inode->i_mutex);
639         }
640
641         if (newdent->d_inode) {
642                 ino = newdent->d_inode->i_ino;
643                 newdent->d_fsdata = (void *) ctl.fpos;
644                 ncp_new_dentry(newdent);
645         }
646
647         if (ctl.idx >= NCP_DIRCACHE_SIZE) {
648                 if (ctl.page) {
649                         kunmap(ctl.page);
650                         SetPageUptodate(ctl.page);
651                         unlock_page(ctl.page);
652                         page_cache_release(ctl.page);
653                 }
654                 ctl.cache = NULL;
655                 ctl.idx  -= NCP_DIRCACHE_SIZE;
656                 ctl.ofs  += 1;
657                 ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
658                 if (ctl.page)
659                         ctl.cache = kmap(ctl.page);
660         }
661         if (ctl.cache) {
662                 ctl.cache->dentry[ctl.idx] = newdent;
663                 valid = 1;
664         }
665         dput(newdent);
666 end_advance:
667         if (!valid)
668                 ctl.valid = 0;
669         if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
670                 if (!ino)
671                         ino = find_inode_number(dentry, &qname);
672                 if (!ino)
673                         ino = iunique(dir->i_sb, 2);
674                 ctl.filled = filldir(dirent, qname.name, qname.len,
675                                      filp->f_pos, ino, DT_UNKNOWN);
676                 if (!ctl.filled)
677                         filp->f_pos += 1;
678         }
679         ctl.fpos += 1;
680         ctl.idx  += 1;
681         *ctrl = ctl;
682         return (ctl.valid || !ctl.filled);
683 }
684
685 static void
686 ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
687                         struct ncp_cache_control *ctl)
688 {
689         struct dentry *dentry = filp->f_path.dentry;
690         struct inode *inode = dentry->d_inode;
691         struct ncp_server *server = NCP_SERVER(inode);
692         struct ncp_volume_info info;
693         struct ncp_entry_info entry;
694         int i;
695
696         DPRINTK("ncp_read_volume_list: pos=%ld\n",
697                         (unsigned long) filp->f_pos);
698
699         for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
700                 int inval_dentry;
701
702                 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
703                         return;
704                 if (!strlen(info.volume_name))
705                         continue;
706
707                 DPRINTK("ncp_read_volume_list: found vol: %s\n",
708                         info.volume_name);
709
710                 if (ncp_lookup_volume(server, info.volume_name,
711                                         &entry.i)) {
712                         DPRINTK("ncpfs: could not lookup vol %s\n",
713                                 info.volume_name);
714                         continue;
715                 }
716                 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
717                 entry.volume = entry.i.volNumber;
718                 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
719                         return;
720         }
721 }
722
723 static void
724 ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
725                                                 struct ncp_cache_control *ctl)
726 {
727         struct dentry *dentry = filp->f_path.dentry;
728         struct inode *dir = dentry->d_inode;
729         struct ncp_server *server = NCP_SERVER(dir);
730         struct nw_search_sequence seq;
731         struct ncp_entry_info entry;
732         int err;
733         void* buf;
734         int more;
735         size_t bufsize;
736
737         DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
738                 dentry->d_parent->d_name.name, dentry->d_name.name,
739                 (unsigned long) filp->f_pos);
740         PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
741                 dentry->d_name.name, NCP_FINFO(dir)->volNumber,
742                 NCP_FINFO(dir)->dirEntNum);
743
744         err = ncp_initialize_search(server, dir, &seq);
745         if (err) {
746                 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
747                 return;
748         }
749         /* We MUST NOT use server->buffer_size handshaked with server if we are
750            using UDP, as for UDP server uses max. buffer size determined by
751            MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 
752            So we use 128KB, just to be sure, as there is no way how to know
753            this value in advance. */
754         bufsize = 131072;
755         buf = vmalloc(bufsize);
756         if (!buf)
757                 return;
758         do {
759                 int cnt;
760                 char* rpl;
761                 size_t rpls;
762
763                 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
764                 if (err)                /* Error */
765                         break;
766                 if (!cnt)               /* prevent endless loop */
767                         break;
768                 while (cnt--) {
769                         size_t onerpl;
770                         
771                         if (rpls < offsetof(struct nw_info_struct, entryName))
772                                 break;  /* short packet */
773                         ncp_extract_file_info(rpl, &entry.i);
774                         onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
775                         if (rpls < onerpl)
776                                 break;  /* short packet */
777                         (void)ncp_obtain_nfs_info(server, &entry.i);
778                         rpl += onerpl;
779                         rpls -= onerpl;
780                         entry.volume = entry.i.volNumber;
781                         if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
782                                 break;
783                 }
784         } while (more);
785         vfree(buf);
786         return;
787 }
788
789 int ncp_conn_logged_in(struct super_block *sb)
790 {
791         struct ncp_server* server = NCP_SBP(sb);
792         int result;
793
794         if (ncp_single_volume(server)) {
795                 int len;
796                 struct dentry* dent;
797                 __u32 volNumber;
798                 __le32 dirEntNum;
799                 __le32 DosDirNum;
800                 __u8 __name[NCP_MAXPATHLEN + 1];
801
802                 len = sizeof(__name);
803                 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
804                                     strlen(server->m.mounted_vol), 1);
805                 if (result)
806                         goto out;
807                 result = -ENOENT;
808                 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
809                         PPRINTK("ncp_conn_logged_in: %s not found\n",
810                                 server->m.mounted_vol);
811                         goto out;
812                 }
813                 dent = sb->s_root;
814                 if (dent) {
815                         struct inode* ino = dent->d_inode;
816                         if (ino) {
817                                 ncp_update_known_namespace(server, volNumber, NULL);
818                                 NCP_FINFO(ino)->volNumber = volNumber;
819                                 NCP_FINFO(ino)->dirEntNum = dirEntNum;
820                                 NCP_FINFO(ino)->DosDirNum = DosDirNum;
821                                 result = 0;
822                         } else {
823                                 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
824                         }
825                 } else {
826                         DPRINTK("ncpfs: sb->s_root == NULL!\n");
827                 }
828         } else
829                 result = 0;
830
831 out:
832         return result;
833 }
834
835 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
836 {
837         struct ncp_server *server = NCP_SERVER(dir);
838         struct inode *inode = NULL;
839         struct ncp_entry_info finfo;
840         int error, res, len;
841         __u8 __name[NCP_MAXPATHLEN + 1];
842
843         error = -EIO;
844         if (!ncp_conn_valid(server))
845                 goto finished;
846
847         PPRINTK("ncp_lookup: server lookup for %s/%s\n",
848                 dentry->d_parent->d_name.name, dentry->d_name.name);
849
850         len = sizeof(__name);
851         if (ncp_is_server_root(dir)) {
852                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
853                                  dentry->d_name.len, 1);
854                 if (!res)
855                         res = ncp_lookup_volume(server, __name, &(finfo.i));
856                         if (!res)
857                                 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
858         } else {
859                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
860                                  dentry->d_name.len, !ncp_preserve_case(dir));
861                 if (!res)
862                         res = ncp_obtain_info(server, dir, __name, &(finfo.i));
863         }
864         PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
865                 dentry->d_parent->d_name.name, __name, res);
866         /*
867          * If we didn't find an entry, make a negative dentry.
868          */
869         if (res)
870                 goto add_entry;
871
872         /*
873          * Create an inode for the entry.
874          */
875         finfo.opened = 0;
876         finfo.ino = iunique(dir->i_sb, 2);
877         finfo.volume = finfo.i.volNumber;
878         error = -EACCES;
879         inode = ncp_iget(dir->i_sb, &finfo);
880
881         if (inode) {
882                 ncp_new_dentry(dentry);
883 add_entry:
884                 d_add(dentry, inode);
885                 error = 0;
886         }
887
888 finished:
889         PPRINTK("ncp_lookup: result=%d\n", error);
890         return ERR_PTR(error);
891 }
892
893 /*
894  * This code is common to create, mkdir, and mknod.
895  */
896 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
897                         struct ncp_entry_info *finfo)
898 {
899         struct inode *inode;
900         int error = -EINVAL;
901
902         finfo->ino = iunique(dir->i_sb, 2);
903         inode = ncp_iget(dir->i_sb, finfo);
904         if (!inode)
905                 goto out_close;
906         d_instantiate(dentry,inode);
907         error = 0;
908 out:
909         return error;
910
911 out_close:
912         PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
913                 dentry->d_parent->d_name.name, dentry->d_name.name);
914         ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
915         goto out;
916 }
917
918 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
919                    dev_t rdev, __le32 attributes)
920 {
921         struct ncp_server *server = NCP_SERVER(dir);
922         struct ncp_entry_info finfo;
923         int error, result, len;
924         int opmode;
925         __u8 __name[NCP_MAXPATHLEN + 1];
926         
927         PPRINTK("ncp_create_new: creating %s/%s, mode=%hx\n",
928                 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
929
930         ncp_age_dentry(server, dentry);
931         len = sizeof(__name);
932         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
933                            dentry->d_name.len, !ncp_preserve_case(dir));
934         if (error)
935                 goto out;
936
937         error = -EACCES;
938         
939         if (S_ISREG(mode) && 
940             (server->m.flags & NCP_MOUNT_EXTRAS) && 
941             (mode & S_IXUGO))
942                 attributes |= aSYSTEM | aSHARED;
943         
944         result = ncp_open_create_file_or_subdir(server, dir, __name,
945                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
946                                 attributes, AR_READ | AR_WRITE, &finfo);
947         opmode = O_RDWR;
948         if (result) {
949                 result = ncp_open_create_file_or_subdir(server, dir, __name,
950                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
951                                 attributes, AR_WRITE, &finfo);
952                 if (result) {
953                         if (result == 0x87)
954                                 error = -ENAMETOOLONG;
955                         else if (result < 0)
956                                 error = result;
957                         DPRINTK("ncp_create: %s/%s failed\n",
958                                 dentry->d_parent->d_name.name, dentry->d_name.name);
959                         goto out;
960                 }
961                 opmode = O_WRONLY;
962         }
963         finfo.access = opmode;
964         if (ncp_is_nfs_extras(server, finfo.volume)) {
965                 finfo.i.nfs.mode = mode;
966                 finfo.i.nfs.rdev = new_encode_dev(rdev);
967                 if (ncp_modify_nfs_info(server, finfo.volume,
968                                         finfo.i.dirEntNum,
969                                         mode, new_encode_dev(rdev)) != 0)
970                         goto out;
971         }
972
973         error = ncp_instantiate(dir, dentry, &finfo);
974 out:
975         return error;
976 }
977
978 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
979                 bool excl)
980 {
981         return ncp_create_new(dir, dentry, mode, 0, 0);
982 }
983
984 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
985 {
986         struct ncp_entry_info finfo;
987         struct ncp_server *server = NCP_SERVER(dir);
988         int error, len;
989         __u8 __name[NCP_MAXPATHLEN + 1];
990
991         DPRINTK("ncp_mkdir: making %s/%s\n",
992                 dentry->d_parent->d_name.name, dentry->d_name.name);
993
994         ncp_age_dentry(server, dentry);
995         len = sizeof(__name);
996         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
997                            dentry->d_name.len, !ncp_preserve_case(dir));
998         if (error)
999                 goto out;
1000
1001         error = ncp_open_create_file_or_subdir(server, dir, __name,
1002                                            OC_MODE_CREATE, aDIR,
1003                                            cpu_to_le16(0xffff),
1004                                            &finfo);
1005         if (error == 0) {
1006                 if (ncp_is_nfs_extras(server, finfo.volume)) {
1007                         mode |= S_IFDIR;
1008                         finfo.i.nfs.mode = mode;
1009                         if (ncp_modify_nfs_info(server,
1010                                                 finfo.volume,
1011                                                 finfo.i.dirEntNum,
1012                                                 mode, 0) != 0)
1013                                 goto out;
1014                 }
1015                 error = ncp_instantiate(dir, dentry, &finfo);
1016         } else if (error > 0) {
1017                 error = -EACCES;
1018         }
1019 out:
1020         return error;
1021 }
1022
1023 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1024 {
1025         struct ncp_server *server = NCP_SERVER(dir);
1026         int error, result, len;
1027         __u8 __name[NCP_MAXPATHLEN + 1];
1028
1029         DPRINTK("ncp_rmdir: removing %s/%s\n",
1030                 dentry->d_parent->d_name.name, dentry->d_name.name);
1031
1032         /*
1033          * fail with EBUSY if there are still references to this
1034          * directory.
1035          */
1036         dentry_unhash(dentry);
1037         error = -EBUSY;
1038         if (!d_unhashed(dentry))
1039                 goto out;
1040
1041         len = sizeof(__name);
1042         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1043                            dentry->d_name.len, !ncp_preserve_case(dir));
1044         if (error)
1045                 goto out;
1046
1047         result = ncp_del_file_or_subdir(server, dir, __name);
1048         switch (result) {
1049                 case 0x00:
1050                         error = 0;
1051                         break;
1052                 case 0x85:      /* unauthorized to delete file */
1053                 case 0x8A:      /* unauthorized to delete file */
1054                         error = -EACCES;
1055                         break;
1056                 case 0x8F:
1057                 case 0x90:      /* read only */
1058                         error = -EPERM;
1059                         break;
1060                 case 0x9F:      /* in use by another client */
1061                         error = -EBUSY;
1062                         break;
1063                 case 0xA0:      /* directory not empty */
1064                         error = -ENOTEMPTY;
1065                         break;
1066                 case 0xFF:      /* someone deleted file */
1067                         error = -ENOENT;
1068                         break;
1069                 default:
1070                         error = result < 0 ? result : -EACCES;
1071                         break;
1072         }
1073 out:
1074         return error;
1075 }
1076
1077 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1078 {
1079         struct inode *inode = dentry->d_inode;
1080         struct ncp_server *server;
1081         int error;
1082
1083         server = NCP_SERVER(dir);
1084         DPRINTK("ncp_unlink: unlinking %s/%s\n",
1085                 dentry->d_parent->d_name.name, dentry->d_name.name);
1086         
1087         /*
1088          * Check whether to close the file ...
1089          */
1090         if (inode) {
1091                 PPRINTK("ncp_unlink: closing file\n");
1092                 ncp_make_closed(inode);
1093         }
1094
1095         error = ncp_del_file_or_subdir2(server, dentry);
1096 #ifdef CONFIG_NCPFS_STRONG
1097         /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1098            it is not :-( */
1099         if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1100                 error = ncp_force_unlink(dir, dentry);
1101         }
1102 #endif
1103         switch (error) {
1104                 case 0x00:
1105                         DPRINTK("ncp: removed %s/%s\n",
1106                                 dentry->d_parent->d_name.name, dentry->d_name.name);
1107                         break;
1108                 case 0x85:
1109                 case 0x8A:
1110                         error = -EACCES;
1111                         break;
1112                 case 0x8D:      /* some files in use */
1113                 case 0x8E:      /* all files in use */
1114                         error = -EBUSY;
1115                         break;
1116                 case 0x8F:      /* some read only */
1117                 case 0x90:      /* all read only */
1118                 case 0x9C:      /* !!! returned when in-use or read-only by NW4 */
1119                         error = -EPERM;
1120                         break;
1121                 case 0xFF:
1122                         error = -ENOENT;
1123                         break;
1124                 default:
1125                         error = error < 0 ? error : -EACCES;
1126                         break;
1127         }
1128         return error;
1129 }
1130
1131 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1132                       struct inode *new_dir, struct dentry *new_dentry)
1133 {
1134         struct ncp_server *server = NCP_SERVER(old_dir);
1135         int error;
1136         int old_len, new_len;
1137         __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1138
1139         DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1140                 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1141                 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1142
1143         if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) {
1144                 /*
1145                  * fail with EBUSY if there are still references to this
1146                  * directory.
1147                  */
1148                 dentry_unhash(new_dentry);
1149                 error = -EBUSY;
1150                 if (!d_unhashed(new_dentry))
1151                         goto out;
1152         }
1153
1154         ncp_age_dentry(server, old_dentry);
1155         ncp_age_dentry(server, new_dentry);
1156
1157         old_len = sizeof(__old_name);
1158         error = ncp_io2vol(server, __old_name, &old_len,
1159                            old_dentry->d_name.name, old_dentry->d_name.len,
1160                            !ncp_preserve_case(old_dir));
1161         if (error)
1162                 goto out;
1163
1164         new_len = sizeof(__new_name);
1165         error = ncp_io2vol(server, __new_name, &new_len,
1166                            new_dentry->d_name.name, new_dentry->d_name.len,
1167                            !ncp_preserve_case(new_dir));
1168         if (error)
1169                 goto out;
1170
1171         error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1172                                                       new_dir, __new_name);
1173 #ifdef CONFIG_NCPFS_STRONG
1174         if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1175                         server->m.flags & NCP_MOUNT_STRONG) {   /* RO */
1176                 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1177                                          new_dir, new_dentry, __new_name);
1178         }
1179 #endif
1180         switch (error) {
1181                 case 0x00:
1182                         DPRINTK("ncp renamed %s -> %s.\n",
1183                                 old_dentry->d_name.name,new_dentry->d_name.name);
1184                         break;
1185                 case 0x9E:
1186                         error = -ENAMETOOLONG;
1187                         break;
1188                 case 0xFF:
1189                         error = -ENOENT;
1190                         break;
1191                 default:
1192                         error = error < 0 ? error : -EACCES;
1193                         break;
1194         }
1195 out:
1196         return error;
1197 }
1198
1199 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1200                      umode_t mode, dev_t rdev)
1201 {
1202         if (!new_valid_dev(rdev))
1203                 return -EINVAL;
1204         if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1205                 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%ho\n", mode);
1206                 return ncp_create_new(dir, dentry, mode, rdev, 0);
1207         }
1208         return -EPERM; /* Strange, but true */
1209 }
1210
1211 /* The following routines are taken directly from msdos-fs */
1212
1213 /* Linear day numbers of the respective 1sts in non-leap years. */
1214
1215 static int day_n[] =
1216 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1217 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1218
1219
1220 extern struct timezone sys_tz;
1221
1222 static int utc2local(int time)
1223 {
1224         return time - sys_tz.tz_minuteswest * 60;
1225 }
1226
1227 static int local2utc(int time)
1228 {
1229         return time + sys_tz.tz_minuteswest * 60;
1230 }
1231
1232 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1233 int
1234 ncp_date_dos2unix(__le16 t, __le16 d)
1235 {
1236         unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1237         int month, year, secs;
1238
1239         /* first subtract and mask after that... Otherwise, if
1240            date == 0, bad things happen */
1241         month = ((date >> 5) - 1) & 15;
1242         year = date >> 9;
1243         secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1244                 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
1245                 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1246         /* days since 1.1.70 plus 80's leap day */
1247         return local2utc(secs);
1248 }
1249
1250
1251 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1252 void
1253 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1254 {
1255         int day, year, nl_day, month;
1256
1257         unix_date = utc2local(unix_date);
1258         *time = cpu_to_le16(
1259                 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1260                 (((unix_date / 3600) % 24) << 11));
1261         day = unix_date / 86400 - 3652;
1262         year = day / 365;
1263         if ((year + 3) / 4 + 365 * year > day)
1264                 year--;
1265         day -= (year + 3) / 4 + 365 * year;
1266         if (day == 59 && !(year & 3)) {
1267                 nl_day = day;
1268                 month = 2;
1269         } else {
1270                 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1271                 for (month = 1; month < 12; month++)
1272                         if (day_n[month] > nl_day)
1273                                 break;
1274         }
1275         *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1276 }