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