Merge git://git.kernel.org/pub/scm/linux/kernel/git/pkl/squashfs-linus
[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         /*
1037          * fail with EBUSY if there are still references to this
1038          * directory.
1039          */
1040         dentry_unhash(dentry);
1041         error = -EBUSY;
1042         if (!d_unhashed(dentry))
1043                 goto out;
1044
1045         len = sizeof(__name);
1046         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1047                            dentry->d_name.len, !ncp_preserve_case(dir));
1048         if (error)
1049                 goto out;
1050
1051         result = ncp_del_file_or_subdir(server, dir, __name);
1052         switch (result) {
1053                 case 0x00:
1054                         error = 0;
1055                         break;
1056                 case 0x85:      /* unauthorized to delete file */
1057                 case 0x8A:      /* unauthorized to delete file */
1058                         error = -EACCES;
1059                         break;
1060                 case 0x8F:
1061                 case 0x90:      /* read only */
1062                         error = -EPERM;
1063                         break;
1064                 case 0x9F:      /* in use by another client */
1065                         error = -EBUSY;
1066                         break;
1067                 case 0xA0:      /* directory not empty */
1068                         error = -ENOTEMPTY;
1069                         break;
1070                 case 0xFF:      /* someone deleted file */
1071                         error = -ENOENT;
1072                         break;
1073                 default:
1074                         error = result < 0 ? result : -EACCES;
1075                         break;
1076         }
1077 out:
1078         return error;
1079 }
1080
1081 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1082 {
1083         struct inode *inode = dentry->d_inode;
1084         struct ncp_server *server;
1085         int error;
1086
1087         server = NCP_SERVER(dir);
1088         DPRINTK("ncp_unlink: unlinking %s/%s\n",
1089                 dentry->d_parent->d_name.name, dentry->d_name.name);
1090         
1091         /*
1092          * Check whether to close the file ...
1093          */
1094         if (inode) {
1095                 PPRINTK("ncp_unlink: closing file\n");
1096                 ncp_make_closed(inode);
1097         }
1098
1099         error = ncp_del_file_or_subdir2(server, dentry);
1100 #ifdef CONFIG_NCPFS_STRONG
1101         /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1102            it is not :-( */
1103         if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1104                 error = ncp_force_unlink(dir, dentry);
1105         }
1106 #endif
1107         switch (error) {
1108                 case 0x00:
1109                         DPRINTK("ncp: removed %s/%s\n",
1110                                 dentry->d_parent->d_name.name, dentry->d_name.name);
1111                         break;
1112                 case 0x85:
1113                 case 0x8A:
1114                         error = -EACCES;
1115                         break;
1116                 case 0x8D:      /* some files in use */
1117                 case 0x8E:      /* all files in use */
1118                         error = -EBUSY;
1119                         break;
1120                 case 0x8F:      /* some read only */
1121                 case 0x90:      /* all read only */
1122                 case 0x9C:      /* !!! returned when in-use or read-only by NW4 */
1123                         error = -EPERM;
1124                         break;
1125                 case 0xFF:
1126                         error = -ENOENT;
1127                         break;
1128                 default:
1129                         error = error < 0 ? error : -EACCES;
1130                         break;
1131         }
1132         return error;
1133 }
1134
1135 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1136                       struct inode *new_dir, struct dentry *new_dentry)
1137 {
1138         struct ncp_server *server = NCP_SERVER(old_dir);
1139         int error;
1140         int old_len, new_len;
1141         __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1142
1143         DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1144                 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1145                 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1146
1147         if (new_dentry->d_inode && S_ISDIR(new_dentry->d_inode->i_mode)) {
1148                 /*
1149                  * fail with EBUSY if there are still references to this
1150                  * directory.
1151                  */
1152                 dentry_unhash(new_dentry);
1153                 error = -EBUSY;
1154                 if (!d_unhashed(new_dentry))
1155                         goto out;
1156         }
1157
1158         ncp_age_dentry(server, old_dentry);
1159         ncp_age_dentry(server, new_dentry);
1160
1161         old_len = sizeof(__old_name);
1162         error = ncp_io2vol(server, __old_name, &old_len,
1163                            old_dentry->d_name.name, old_dentry->d_name.len,
1164                            !ncp_preserve_case(old_dir));
1165         if (error)
1166                 goto out;
1167
1168         new_len = sizeof(__new_name);
1169         error = ncp_io2vol(server, __new_name, &new_len,
1170                            new_dentry->d_name.name, new_dentry->d_name.len,
1171                            !ncp_preserve_case(new_dir));
1172         if (error)
1173                 goto out;
1174
1175         error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1176                                                       new_dir, __new_name);
1177 #ifdef CONFIG_NCPFS_STRONG
1178         if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1179                         server->m.flags & NCP_MOUNT_STRONG) {   /* RO */
1180                 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1181                                          new_dir, new_dentry, __new_name);
1182         }
1183 #endif
1184         switch (error) {
1185                 case 0x00:
1186                         DPRINTK("ncp renamed %s -> %s.\n",
1187                                 old_dentry->d_name.name,new_dentry->d_name.name);
1188                         break;
1189                 case 0x9E:
1190                         error = -ENAMETOOLONG;
1191                         break;
1192                 case 0xFF:
1193                         error = -ENOENT;
1194                         break;
1195                 default:
1196                         error = error < 0 ? error : -EACCES;
1197                         break;
1198         }
1199 out:
1200         return error;
1201 }
1202
1203 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1204                      int mode, dev_t rdev)
1205 {
1206         if (!new_valid_dev(rdev))
1207                 return -EINVAL;
1208         if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1209                 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
1210                 return ncp_create_new(dir, dentry, mode, rdev, 0);
1211         }
1212         return -EPERM; /* Strange, but true */
1213 }
1214
1215 /* The following routines are taken directly from msdos-fs */
1216
1217 /* Linear day numbers of the respective 1sts in non-leap years. */
1218
1219 static int day_n[] =
1220 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1221 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1222
1223
1224 extern struct timezone sys_tz;
1225
1226 static int utc2local(int time)
1227 {
1228         return time - sys_tz.tz_minuteswest * 60;
1229 }
1230
1231 static int local2utc(int time)
1232 {
1233         return time + sys_tz.tz_minuteswest * 60;
1234 }
1235
1236 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1237 int
1238 ncp_date_dos2unix(__le16 t, __le16 d)
1239 {
1240         unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1241         int month, year, secs;
1242
1243         /* first subtract and mask after that... Otherwise, if
1244            date == 0, bad things happen */
1245         month = ((date >> 5) - 1) & 15;
1246         year = date >> 9;
1247         secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1248                 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
1249                 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1250         /* days since 1.1.70 plus 80's leap day */
1251         return local2utc(secs);
1252 }
1253
1254
1255 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1256 void
1257 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1258 {
1259         int day, year, nl_day, month;
1260
1261         unix_date = utc2local(unix_date);
1262         *time = cpu_to_le16(
1263                 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1264                 (((unix_date / 3600) % 24) << 11));
1265         day = unix_date / 86400 - 3652;
1266         year = day / 365;
1267         if ((year + 3) / 4 + 365 * year > day)
1268                 year--;
1269         day -= (year + 3) / 4 + 365 * year;
1270         if (day == 59 && !(year & 3)) {
1271                 nl_day = day;
1272                 month = 2;
1273         } else {
1274                 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1275                 for (month = 1; month < 12; month++)
1276                         if (day_n[month] > nl_day)
1277                                 break;
1278         }
1279         *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1280 }