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