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