]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/ncpfs/dir.c
8bfd2c44c2d2bfaddda9411e4f71eca4a15cc02b
[karo-tx-linux.git] / fs / ncpfs / dir.c
1 /*
2  *  dir.c
3  *
4  *  Copyright (C) 1995, 1996 by Volker Lendecke
5  *  Modified for big endian by J.F. Chadima and David S. Miller
6  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7  *  Modified 1998, 1999 Wolfram Pienkoss for NLS
8  *  Modified 1999 Wolfram Pienkoss for directory caching
9  *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
10  *
11  */
12
13
14 #include <linux/time.h>
15 #include <linux/errno.h>
16 #include <linux/stat.h>
17 #include <linux/kernel.h>
18 #include <linux/vmalloc.h>
19 #include <linux/mm.h>
20 #include <linux/namei.h>
21 #include <asm/uaccess.h>
22 #include <asm/byteorder.h>
23
24 #include "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         PPRINTK("ncp_do_readdir: 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                         PPRINTK("ncp_conn_logged_in: %s not found\n",
808                                 server->m.mounted_vol);
809                         goto out;
810                 }
811                 dent = sb->s_root;
812                 if (dent) {
813                         struct inode* ino = dent->d_inode;
814                         if (ino) {
815                                 ncp_update_known_namespace(server, volNumber, NULL);
816                                 NCP_FINFO(ino)->volNumber = volNumber;
817                                 NCP_FINFO(ino)->dirEntNum = dirEntNum;
818                                 NCP_FINFO(ino)->DosDirNum = DosDirNum;
819                                 result = 0;
820                         } else {
821                                 ncp_dbg(1, "sb->s_root->d_inode == NULL!\n");
822                         }
823                 } else {
824                         ncp_dbg(1, "sb->s_root == NULL!\n");
825                 }
826         } else
827                 result = 0;
828
829 out:
830         return result;
831 }
832
833 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
834 {
835         struct ncp_server *server = NCP_SERVER(dir);
836         struct inode *inode = NULL;
837         struct ncp_entry_info finfo;
838         int error, res, len;
839         __u8 __name[NCP_MAXPATHLEN + 1];
840
841         error = -EIO;
842         if (!ncp_conn_valid(server))
843                 goto finished;
844
845         PPRINTK("ncp_lookup: server lookup for %pd2\n", dentry);
846
847         len = sizeof(__name);
848         if (ncp_is_server_root(dir)) {
849                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
850                                  dentry->d_name.len, 1);
851                 if (!res)
852                         res = ncp_lookup_volume(server, __name, &(finfo.i));
853                         if (!res)
854                                 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
855         } else {
856                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
857                                  dentry->d_name.len, !ncp_preserve_case(dir));
858                 if (!res)
859                         res = ncp_obtain_info(server, dir, __name, &(finfo.i));
860         }
861         PPRINTK("ncp_lookup: looked for %pd2, res=%d\n", dentry, res);
862         /*
863          * If we didn't find an entry, make a negative dentry.
864          */
865         if (res)
866                 goto add_entry;
867
868         /*
869          * Create an inode for the entry.
870          */
871         finfo.opened = 0;
872         finfo.ino = iunique(dir->i_sb, 2);
873         finfo.volume = finfo.i.volNumber;
874         error = -EACCES;
875         inode = ncp_iget(dir->i_sb, &finfo);
876
877         if (inode) {
878                 ncp_new_dentry(dentry);
879 add_entry:
880                 d_add(dentry, inode);
881                 error = 0;
882         }
883
884 finished:
885         PPRINTK("ncp_lookup: result=%d\n", error);
886         return ERR_PTR(error);
887 }
888
889 /*
890  * This code is common to create, mkdir, and mknod.
891  */
892 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
893                         struct ncp_entry_info *finfo)
894 {
895         struct inode *inode;
896         int error = -EINVAL;
897
898         finfo->ino = iunique(dir->i_sb, 2);
899         inode = ncp_iget(dir->i_sb, finfo);
900         if (!inode)
901                 goto out_close;
902         d_instantiate(dentry,inode);
903         error = 0;
904 out:
905         return error;
906
907 out_close:
908         PPRINTK("ncp_instantiate: %pd2 failed, closing file\n", dentry);
909         ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
910         goto out;
911 }
912
913 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
914                    dev_t rdev, __le32 attributes)
915 {
916         struct ncp_server *server = NCP_SERVER(dir);
917         struct ncp_entry_info finfo;
918         int error, result, len;
919         int opmode;
920         __u8 __name[NCP_MAXPATHLEN + 1];
921         
922         PPRINTK("ncp_create_new: creating %pd2, mode=%hx\n", dentry, mode);
923
924         ncp_age_dentry(server, dentry);
925         len = sizeof(__name);
926         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
927                            dentry->d_name.len, !ncp_preserve_case(dir));
928         if (error)
929                 goto out;
930
931         error = -EACCES;
932         
933         if (S_ISREG(mode) && 
934             (server->m.flags & NCP_MOUNT_EXTRAS) && 
935             (mode & S_IXUGO))
936                 attributes |= aSYSTEM | aSHARED;
937         
938         result = ncp_open_create_file_or_subdir(server, dir, __name,
939                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
940                                 attributes, AR_READ | AR_WRITE, &finfo);
941         opmode = O_RDWR;
942         if (result) {
943                 result = ncp_open_create_file_or_subdir(server, dir, __name,
944                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
945                                 attributes, AR_WRITE, &finfo);
946                 if (result) {
947                         if (result == 0x87)
948                                 error = -ENAMETOOLONG;
949                         else if (result < 0)
950                                 error = result;
951                         ncp_dbg(1, "%pd2 failed\n", dentry);
952                         goto out;
953                 }
954                 opmode = O_WRONLY;
955         }
956         finfo.access = opmode;
957         if (ncp_is_nfs_extras(server, finfo.volume)) {
958                 finfo.i.nfs.mode = mode;
959                 finfo.i.nfs.rdev = new_encode_dev(rdev);
960                 if (ncp_modify_nfs_info(server, finfo.volume,
961                                         finfo.i.dirEntNum,
962                                         mode, new_encode_dev(rdev)) != 0)
963                         goto out;
964         }
965
966         error = ncp_instantiate(dir, dentry, &finfo);
967 out:
968         return error;
969 }
970
971 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
972                 bool excl)
973 {
974         return ncp_create_new(dir, dentry, mode, 0, 0);
975 }
976
977 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
978 {
979         struct ncp_entry_info finfo;
980         struct ncp_server *server = NCP_SERVER(dir);
981         int error, len;
982         __u8 __name[NCP_MAXPATHLEN + 1];
983
984         ncp_dbg(1, "making %pd2\n", dentry);
985
986         ncp_age_dentry(server, dentry);
987         len = sizeof(__name);
988         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
989                            dentry->d_name.len, !ncp_preserve_case(dir));
990         if (error)
991                 goto out;
992
993         error = ncp_open_create_file_or_subdir(server, dir, __name,
994                                            OC_MODE_CREATE, aDIR,
995                                            cpu_to_le16(0xffff),
996                                            &finfo);
997         if (error == 0) {
998                 if (ncp_is_nfs_extras(server, finfo.volume)) {
999                         mode |= S_IFDIR;
1000                         finfo.i.nfs.mode = mode;
1001                         if (ncp_modify_nfs_info(server,
1002                                                 finfo.volume,
1003                                                 finfo.i.dirEntNum,
1004                                                 mode, 0) != 0)
1005                                 goto out;
1006                 }
1007                 error = ncp_instantiate(dir, dentry, &finfo);
1008         } else if (error > 0) {
1009                 error = -EACCES;
1010         }
1011 out:
1012         return error;
1013 }
1014
1015 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1016 {
1017         struct ncp_server *server = NCP_SERVER(dir);
1018         int error, result, len;
1019         __u8 __name[NCP_MAXPATHLEN + 1];
1020
1021         ncp_dbg(1, "removing %pd2\n", dentry);
1022
1023         len = sizeof(__name);
1024         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1025                            dentry->d_name.len, !ncp_preserve_case(dir));
1026         if (error)
1027                 goto out;
1028
1029         result = ncp_del_file_or_subdir(server, dir, __name);
1030         switch (result) {
1031                 case 0x00:
1032                         error = 0;
1033                         break;
1034                 case 0x85:      /* unauthorized to delete file */
1035                 case 0x8A:      /* unauthorized to delete file */
1036                         error = -EACCES;
1037                         break;
1038                 case 0x8F:
1039                 case 0x90:      /* read only */
1040                         error = -EPERM;
1041                         break;
1042                 case 0x9F:      /* in use by another client */
1043                         error = -EBUSY;
1044                         break;
1045                 case 0xA0:      /* directory not empty */
1046                         error = -ENOTEMPTY;
1047                         break;
1048                 case 0xFF:      /* someone deleted file */
1049                         error = -ENOENT;
1050                         break;
1051                 default:
1052                         error = result < 0 ? result : -EACCES;
1053                         break;
1054         }
1055 out:
1056         return error;
1057 }
1058
1059 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1060 {
1061         struct inode *inode = dentry->d_inode;
1062         struct ncp_server *server;
1063         int error;
1064
1065         server = NCP_SERVER(dir);
1066         ncp_dbg(1, "unlinking %pd2\n", dentry);
1067         
1068         /*
1069          * Check whether to close the file ...
1070          */
1071         if (inode) {
1072                 PPRINTK("ncp_unlink: closing file\n");
1073                 ncp_make_closed(inode);
1074         }
1075
1076         error = ncp_del_file_or_subdir2(server, dentry);
1077 #ifdef CONFIG_NCPFS_STRONG
1078         /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1079            it is not :-( */
1080         if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1081                 error = ncp_force_unlink(dir, dentry);
1082         }
1083 #endif
1084         switch (error) {
1085                 case 0x00:
1086                         ncp_dbg(1, "removed %pd2\n", dentry);
1087                         break;
1088                 case 0x85:
1089                 case 0x8A:
1090                         error = -EACCES;
1091                         break;
1092                 case 0x8D:      /* some files in use */
1093                 case 0x8E:      /* all files in use */
1094                         error = -EBUSY;
1095                         break;
1096                 case 0x8F:      /* some read only */
1097                 case 0x90:      /* all read only */
1098                 case 0x9C:      /* !!! returned when in-use or read-only by NW4 */
1099                         error = -EPERM;
1100                         break;
1101                 case 0xFF:
1102                         error = -ENOENT;
1103                         break;
1104                 default:
1105                         error = error < 0 ? error : -EACCES;
1106                         break;
1107         }
1108         return error;
1109 }
1110
1111 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1112                       struct inode *new_dir, struct dentry *new_dentry)
1113 {
1114         struct ncp_server *server = NCP_SERVER(old_dir);
1115         int error;
1116         int old_len, new_len;
1117         __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1118
1119         ncp_dbg(1, "%pd2 to %pd2\n", old_dentry, new_dentry);
1120
1121         ncp_age_dentry(server, old_dentry);
1122         ncp_age_dentry(server, new_dentry);
1123
1124         old_len = sizeof(__old_name);
1125         error = ncp_io2vol(server, __old_name, &old_len,
1126                            old_dentry->d_name.name, old_dentry->d_name.len,
1127                            !ncp_preserve_case(old_dir));
1128         if (error)
1129                 goto out;
1130
1131         new_len = sizeof(__new_name);
1132         error = ncp_io2vol(server, __new_name, &new_len,
1133                            new_dentry->d_name.name, new_dentry->d_name.len,
1134                            !ncp_preserve_case(new_dir));
1135         if (error)
1136                 goto out;
1137
1138         error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1139                                                       new_dir, __new_name);
1140 #ifdef CONFIG_NCPFS_STRONG
1141         if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1142                         server->m.flags & NCP_MOUNT_STRONG) {   /* RO */
1143                 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1144                                          new_dir, new_dentry, __new_name);
1145         }
1146 #endif
1147         switch (error) {
1148                 case 0x00:
1149                         ncp_dbg(1, "renamed %pd -> %pd\n",
1150                                 old_dentry, new_dentry);
1151                         break;
1152                 case 0x9E:
1153                         error = -ENAMETOOLONG;
1154                         break;
1155                 case 0xFF:
1156                         error = -ENOENT;
1157                         break;
1158                 default:
1159                         error = error < 0 ? error : -EACCES;
1160                         break;
1161         }
1162 out:
1163         return error;
1164 }
1165
1166 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1167                      umode_t mode, dev_t rdev)
1168 {
1169         if (!new_valid_dev(rdev))
1170                 return -EINVAL;
1171         if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1172                 ncp_dbg(1, "mode = 0%ho\n", mode);
1173                 return ncp_create_new(dir, dentry, mode, rdev, 0);
1174         }
1175         return -EPERM; /* Strange, but true */
1176 }
1177
1178 /* The following routines are taken directly from msdos-fs */
1179
1180 /* Linear day numbers of the respective 1sts in non-leap years. */
1181
1182 static int day_n[] =
1183 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1184 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1185
1186
1187 extern struct timezone sys_tz;
1188
1189 static int utc2local(int time)
1190 {
1191         return time - sys_tz.tz_minuteswest * 60;
1192 }
1193
1194 static int local2utc(int time)
1195 {
1196         return time + sys_tz.tz_minuteswest * 60;
1197 }
1198
1199 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1200 int
1201 ncp_date_dos2unix(__le16 t, __le16 d)
1202 {
1203         unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1204         int month, year, secs;
1205
1206         /* first subtract and mask after that... Otherwise, if
1207            date == 0, bad things happen */
1208         month = ((date >> 5) - 1) & 15;
1209         year = date >> 9;
1210         secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1211                 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
1212                 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1213         /* days since 1.1.70 plus 80's leap day */
1214         return local2utc(secs);
1215 }
1216
1217
1218 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1219 void
1220 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1221 {
1222         int day, year, nl_day, month;
1223
1224         unix_date = utc2local(unix_date);
1225         *time = cpu_to_le16(
1226                 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1227                 (((unix_date / 3600) % 24) << 11));
1228         day = unix_date / 86400 - 3652;
1229         year = day / 365;
1230         if ((year + 3) / 4 + 365 * year > day)
1231                 year--;
1232         day -= (year + 3) / 4 + 365 * year;
1233         if (day == 59 && !(year & 3)) {
1234                 nl_day = day;
1235                 month = 2;
1236         } else {
1237                 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1238                 for (month = 1; month < 12; month++)
1239                         if (day_n[month] > nl_day)
1240                                 break;
1241         }
1242         *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1243 }