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