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