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