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