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