]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/ncpfs/dir.c
arm: imx6: defconfig: update tx6 defconfigs
[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         DDPRINTK("ncp_lookup_validate: %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         DDPRINTK("ncp_lookup_validate: 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                         DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
376
377                 ncp_update_inode2(inode, &finfo);
378                 mutex_unlock(&inode->i_mutex);
379         }
380
381 finished:
382         DDPRINTK("ncp_lookup_validate: 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         DDPRINTK("ncp_readdir: reading %pD2, pos=%d\n", file,
457                 (int) ctx->pos);
458
459         result = -EIO;
460         /* Do not generate '.' and '..' when server is dead. */
461         if (!ncp_conn_valid(server))
462                 goto out;
463
464         result = 0;
465         if (!dir_emit_dots(file, ctx))
466                 goto out;
467
468         page = grab_cache_page(&inode->i_data, 0);
469         if (!page)
470                 goto read_really;
471
472         ctl.cache = cache = kmap(page);
473         ctl.head  = cache->head;
474
475         if (!PageUptodate(page) || !ctl.head.eof)
476                 goto init_cache;
477
478         if (ctx->pos == 2) {
479                 if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
480                         goto init_cache;
481
482                 mtime = ncp_obtain_mtime(dentry);
483                 mtime_valid = 1;
484                 if ((!mtime) || (mtime != ctl.head.mtime))
485                         goto init_cache;
486         }
487
488         if (ctx->pos > ctl.head.end)
489                 goto finished;
490
491         ctl.fpos = ctx->pos + (NCP_DIRCACHE_START - 2);
492         ctl.ofs  = ctl.fpos / NCP_DIRCACHE_SIZE;
493         ctl.idx  = ctl.fpos % NCP_DIRCACHE_SIZE;
494
495         for (;;) {
496                 if (ctl.ofs != 0) {
497                         ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
498                         if (!ctl.page)
499                                 goto invalid_cache;
500                         ctl.cache = kmap(ctl.page);
501                         if (!PageUptodate(ctl.page))
502                                 goto invalid_cache;
503                 }
504                 while (ctl.idx < NCP_DIRCACHE_SIZE) {
505                         struct dentry *dent;
506                         bool over;
507
508                         dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
509                                                 dentry, ctx->pos);
510                         if (!dent)
511                                 goto invalid_cache;
512                         over = !dir_emit(ctx, dent->d_name.name,
513                                         dent->d_name.len,
514                                         dent->d_inode->i_ino, DT_UNKNOWN);
515                         dput(dent);
516                         if (over)
517                                 goto finished;
518                         ctx->pos += 1;
519                         ctl.idx += 1;
520                         if (ctx->pos > ctl.head.end)
521                                 goto finished;
522                 }
523                 if (ctl.page) {
524                         kunmap(ctl.page);
525                         SetPageUptodate(ctl.page);
526                         unlock_page(ctl.page);
527                         page_cache_release(ctl.page);
528                         ctl.page = NULL;
529                 }
530                 ctl.idx  = 0;
531                 ctl.ofs += 1;
532         }
533 invalid_cache:
534         if (ctl.page) {
535                 kunmap(ctl.page);
536                 unlock_page(ctl.page);
537                 page_cache_release(ctl.page);
538                 ctl.page = NULL;
539         }
540         ctl.cache = cache;
541 init_cache:
542         ncp_invalidate_dircache_entries(dentry);
543         if (!mtime_valid) {
544                 mtime = ncp_obtain_mtime(dentry);
545                 mtime_valid = 1;
546         }
547         ctl.head.mtime = mtime;
548         ctl.head.time = jiffies;
549         ctl.head.eof = 0;
550         ctl.fpos = 2;
551         ctl.ofs = 0;
552         ctl.idx = NCP_DIRCACHE_START;
553         ctl.filled = 0;
554         ctl.valid  = 1;
555 read_really:
556         if (ncp_is_server_root(inode)) {
557                 ncp_read_volume_list(file, ctx, &ctl);
558         } else {
559                 ncp_do_readdir(file, ctx, &ctl);
560         }
561         ctl.head.end = ctl.fpos - 1;
562         ctl.head.eof = ctl.valid;
563 finished:
564         if (ctl.page) {
565                 kunmap(ctl.page);
566                 SetPageUptodate(ctl.page);
567                 unlock_page(ctl.page);
568                 page_cache_release(ctl.page);
569         }
570         if (page) {
571                 cache->head = ctl.head;
572                 kunmap(page);
573                 SetPageUptodate(page);
574                 unlock_page(page);
575                 page_cache_release(page);
576         }
577 out:
578         return result;
579 }
580
581 static int
582 ncp_fill_cache(struct file *file, struct dir_context *ctx,
583                 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
584                 int inval_childs)
585 {
586         struct dentry *newdent, *dentry = file->f_path.dentry;
587         struct inode *dir = dentry->d_inode;
588         struct ncp_cache_control ctl = *ctrl;
589         struct qstr qname;
590         int valid = 0;
591         int hashed = 0;
592         ino_t ino = 0;
593         __u8 __name[NCP_MAXPATHLEN + 1];
594
595         qname.len = sizeof(__name);
596         if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
597                         entry->i.entryName, entry->i.nameLen,
598                         !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
599                 return 1; /* I'm not sure */
600
601         qname.name = __name;
602
603         newdent = d_hash_and_lookup(dentry, &qname);
604         if (unlikely(IS_ERR(newdent)))
605                 goto end_advance;
606         if (!newdent) {
607                 newdent = d_alloc(dentry, &qname);
608                 if (!newdent)
609                         goto end_advance;
610         } else {
611                 hashed = 1;
612
613                 /* If case sensitivity changed for this volume, all entries below this one
614                    should be thrown away.  This entry itself is not affected, as its case
615                    sensitivity is controlled by its own parent. */
616                 if (inval_childs)
617                         shrink_dcache_parent(newdent);
618
619                 /*
620                  * NetWare's OS2 namespace is case preserving yet case
621                  * insensitive.  So we update dentry's name as received from
622                  * server. Parent dir's i_mutex is locked because we're in
623                  * readdir.
624                  */
625                 dentry_update_name_case(newdent, &qname);
626         }
627
628         if (!newdent->d_inode) {
629                 struct inode *inode;
630
631                 entry->opened = 0;
632                 entry->ino = iunique(dir->i_sb, 2);
633                 inode = ncp_iget(dir->i_sb, entry);
634                 if (inode) {
635                         d_instantiate(newdent, inode);
636                         if (!hashed)
637                                 d_rehash(newdent);
638                 }
639         } else {
640                 struct inode *inode = newdent->d_inode;
641
642                 mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
643                 ncp_update_inode2(inode, entry);
644                 mutex_unlock(&inode->i_mutex);
645         }
646
647         if (newdent->d_inode) {
648                 ino = newdent->d_inode->i_ino;
649                 newdent->d_fsdata = (void *) ctl.fpos;
650                 ncp_new_dentry(newdent);
651         }
652
653         if (ctl.idx >= NCP_DIRCACHE_SIZE) {
654                 if (ctl.page) {
655                         kunmap(ctl.page);
656                         SetPageUptodate(ctl.page);
657                         unlock_page(ctl.page);
658                         page_cache_release(ctl.page);
659                 }
660                 ctl.cache = NULL;
661                 ctl.idx  -= NCP_DIRCACHE_SIZE;
662                 ctl.ofs  += 1;
663                 ctl.page  = grab_cache_page(&dir->i_data, ctl.ofs);
664                 if (ctl.page)
665                         ctl.cache = kmap(ctl.page);
666         }
667         if (ctl.cache) {
668                 ctl.cache->dentry[ctl.idx] = newdent;
669                 valid = 1;
670         }
671         dput(newdent);
672 end_advance:
673         if (!valid)
674                 ctl.valid = 0;
675         if (!ctl.filled && (ctl.fpos == ctx->pos)) {
676                 if (!ino)
677                         ino = iunique(dir->i_sb, 2);
678                 ctl.filled = !dir_emit(ctx, qname.name, qname.len,
679                                      ino, DT_UNKNOWN);
680                 if (!ctl.filled)
681                         ctx->pos += 1;
682         }
683         ctl.fpos += 1;
684         ctl.idx  += 1;
685         *ctrl = ctl;
686         return (ctl.valid || !ctl.filled);
687 }
688
689 static void
690 ncp_read_volume_list(struct file *file, struct dir_context *ctx,
691                         struct ncp_cache_control *ctl)
692 {
693         struct dentry *dentry = file->f_path.dentry;
694         struct inode *inode = dentry->d_inode;
695         struct ncp_server *server = NCP_SERVER(inode);
696         struct ncp_volume_info info;
697         struct ncp_entry_info entry;
698         int i;
699
700         DPRINTK("ncp_read_volume_list: pos=%ld\n",
701                         (unsigned long) ctx->pos);
702
703         for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
704                 int inval_dentry;
705
706                 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
707                         return;
708                 if (!strlen(info.volume_name))
709                         continue;
710
711                 DPRINTK("ncp_read_volume_list: found vol: %s\n",
712                         info.volume_name);
713
714                 if (ncp_lookup_volume(server, info.volume_name,
715                                         &entry.i)) {
716                         DPRINTK("ncpfs: could not lookup vol %s\n",
717                                 info.volume_name);
718                         continue;
719                 }
720                 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
721                 entry.volume = entry.i.volNumber;
722                 if (!ncp_fill_cache(file, ctx, ctl, &entry, inval_dentry))
723                         return;
724         }
725 }
726
727 static void
728 ncp_do_readdir(struct file *file, struct dir_context *ctx,
729                                                 struct ncp_cache_control *ctl)
730 {
731         struct dentry *dentry = file->f_path.dentry;
732         struct inode *dir = dentry->d_inode;
733         struct ncp_server *server = NCP_SERVER(dir);
734         struct nw_search_sequence seq;
735         struct ncp_entry_info entry;
736         int err;
737         void* buf;
738         int more;
739         size_t bufsize;
740
741         DPRINTK("ncp_do_readdir: %pD2, fpos=%ld\n", file,
742                 (unsigned long) ctx->pos);
743         PPRINTK("ncp_do_readdir: init %pD, volnum=%d, dirent=%u\n",
744                 file, NCP_FINFO(dir)->volNumber, NCP_FINFO(dir)->dirEntNum);
745
746         err = ncp_initialize_search(server, dir, &seq);
747         if (err) {
748                 DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
749                 return;
750         }
751         /* We MUST NOT use server->buffer_size handshaked with server if we are
752            using UDP, as for UDP server uses max. buffer size determined by
753            MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 
754            So we use 128KB, just to be sure, as there is no way how to know
755            this value in advance. */
756         bufsize = 131072;
757         buf = vmalloc(bufsize);
758         if (!buf)
759                 return;
760         do {
761                 int cnt;
762                 char* rpl;
763                 size_t rpls;
764
765                 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
766                 if (err)                /* Error */
767                         break;
768                 if (!cnt)               /* prevent endless loop */
769                         break;
770                 while (cnt--) {
771                         size_t onerpl;
772                         
773                         if (rpls < offsetof(struct nw_info_struct, entryName))
774                                 break;  /* short packet */
775                         ncp_extract_file_info(rpl, &entry.i);
776                         onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
777                         if (rpls < onerpl)
778                                 break;  /* short packet */
779                         (void)ncp_obtain_nfs_info(server, &entry.i);
780                         rpl += onerpl;
781                         rpls -= onerpl;
782                         entry.volume = entry.i.volNumber;
783                         if (!ncp_fill_cache(file, ctx, ctl, &entry, 0))
784                                 break;
785                 }
786         } while (more);
787         vfree(buf);
788         return;
789 }
790
791 int ncp_conn_logged_in(struct super_block *sb)
792 {
793         struct ncp_server* server = NCP_SBP(sb);
794         int result;
795
796         if (ncp_single_volume(server)) {
797                 int len;
798                 struct dentry* dent;
799                 __u32 volNumber;
800                 __le32 dirEntNum;
801                 __le32 DosDirNum;
802                 __u8 __name[NCP_MAXPATHLEN + 1];
803
804                 len = sizeof(__name);
805                 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
806                                     strlen(server->m.mounted_vol), 1);
807                 if (result)
808                         goto out;
809                 result = -ENOENT;
810                 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
811                         PPRINTK("ncp_conn_logged_in: %s not found\n",
812                                 server->m.mounted_vol);
813                         goto out;
814                 }
815                 dent = sb->s_root;
816                 if (dent) {
817                         struct inode* ino = dent->d_inode;
818                         if (ino) {
819                                 ncp_update_known_namespace(server, volNumber, NULL);
820                                 NCP_FINFO(ino)->volNumber = volNumber;
821                                 NCP_FINFO(ino)->dirEntNum = dirEntNum;
822                                 NCP_FINFO(ino)->DosDirNum = DosDirNum;
823                                 result = 0;
824                         } else {
825                                 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
826                         }
827                 } else {
828                         DPRINTK("ncpfs: sb->s_root == NULL!\n");
829                 }
830         } else
831                 result = 0;
832
833 out:
834         return result;
835 }
836
837 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
838 {
839         struct ncp_server *server = NCP_SERVER(dir);
840         struct inode *inode = NULL;
841         struct ncp_entry_info finfo;
842         int error, res, len;
843         __u8 __name[NCP_MAXPATHLEN + 1];
844
845         error = -EIO;
846         if (!ncp_conn_valid(server))
847                 goto finished;
848
849         PPRINTK("ncp_lookup: server lookup for %pd2\n", dentry);
850
851         len = sizeof(__name);
852         if (ncp_is_server_root(dir)) {
853                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
854                                  dentry->d_name.len, 1);
855                 if (!res)
856                         res = ncp_lookup_volume(server, __name, &(finfo.i));
857                         if (!res)
858                                 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
859         } else {
860                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
861                                  dentry->d_name.len, !ncp_preserve_case(dir));
862                 if (!res)
863                         res = ncp_obtain_info(server, dir, __name, &(finfo.i));
864         }
865         PPRINTK("ncp_lookup: looked for %pd2, res=%d\n", dentry, res);
866         /*
867          * If we didn't find an entry, make a negative dentry.
868          */
869         if (res)
870                 goto add_entry;
871
872         /*
873          * Create an inode for the entry.
874          */
875         finfo.opened = 0;
876         finfo.ino = iunique(dir->i_sb, 2);
877         finfo.volume = finfo.i.volNumber;
878         error = -EACCES;
879         inode = ncp_iget(dir->i_sb, &finfo);
880
881         if (inode) {
882                 ncp_new_dentry(dentry);
883 add_entry:
884                 d_add(dentry, inode);
885                 error = 0;
886         }
887
888 finished:
889         PPRINTK("ncp_lookup: result=%d\n", error);
890         return ERR_PTR(error);
891 }
892
893 /*
894  * This code is common to create, mkdir, and mknod.
895  */
896 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
897                         struct ncp_entry_info *finfo)
898 {
899         struct inode *inode;
900         int error = -EINVAL;
901
902         finfo->ino = iunique(dir->i_sb, 2);
903         inode = ncp_iget(dir->i_sb, finfo);
904         if (!inode)
905                 goto out_close;
906         d_instantiate(dentry,inode);
907         error = 0;
908 out:
909         return error;
910
911 out_close:
912         PPRINTK("ncp_instantiate: %pd2 failed, closing file\n", dentry);
913         ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
914         goto out;
915 }
916
917 int ncp_create_new(struct inode *dir, struct dentry *dentry, umode_t mode,
918                    dev_t rdev, __le32 attributes)
919 {
920         struct ncp_server *server = NCP_SERVER(dir);
921         struct ncp_entry_info finfo;
922         int error, result, len;
923         int opmode;
924         __u8 __name[NCP_MAXPATHLEN + 1];
925         
926         PPRINTK("ncp_create_new: creating %pd2, mode=%hx\n", dentry, mode);
927
928         ncp_age_dentry(server, dentry);
929         len = sizeof(__name);
930         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
931                            dentry->d_name.len, !ncp_preserve_case(dir));
932         if (error)
933                 goto out;
934
935         error = -EACCES;
936         
937         if (S_ISREG(mode) && 
938             (server->m.flags & NCP_MOUNT_EXTRAS) && 
939             (mode & S_IXUGO))
940                 attributes |= aSYSTEM | aSHARED;
941         
942         result = ncp_open_create_file_or_subdir(server, dir, __name,
943                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
944                                 attributes, AR_READ | AR_WRITE, &finfo);
945         opmode = O_RDWR;
946         if (result) {
947                 result = ncp_open_create_file_or_subdir(server, dir, __name,
948                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
949                                 attributes, AR_WRITE, &finfo);
950                 if (result) {
951                         if (result == 0x87)
952                                 error = -ENAMETOOLONG;
953                         else if (result < 0)
954                                 error = result;
955                         DPRINTK("ncp_create: %pd2 failed\n", dentry);
956                         goto out;
957                 }
958                 opmode = O_WRONLY;
959         }
960         finfo.access = opmode;
961         if (ncp_is_nfs_extras(server, finfo.volume)) {
962                 finfo.i.nfs.mode = mode;
963                 finfo.i.nfs.rdev = new_encode_dev(rdev);
964                 if (ncp_modify_nfs_info(server, finfo.volume,
965                                         finfo.i.dirEntNum,
966                                         mode, new_encode_dev(rdev)) != 0)
967                         goto out;
968         }
969
970         error = ncp_instantiate(dir, dentry, &finfo);
971 out:
972         return error;
973 }
974
975 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
976                 bool excl)
977 {
978         return ncp_create_new(dir, dentry, mode, 0, 0);
979 }
980
981 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
982 {
983         struct ncp_entry_info finfo;
984         struct ncp_server *server = NCP_SERVER(dir);
985         int error, len;
986         __u8 __name[NCP_MAXPATHLEN + 1];
987
988         DPRINTK("ncp_mkdir: making %pd2\n", dentry);
989
990         ncp_age_dentry(server, dentry);
991         len = sizeof(__name);
992         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
993                            dentry->d_name.len, !ncp_preserve_case(dir));
994         if (error)
995                 goto out;
996
997         error = ncp_open_create_file_or_subdir(server, dir, __name,
998                                            OC_MODE_CREATE, aDIR,
999                                            cpu_to_le16(0xffff),
1000                                            &finfo);
1001         if (error == 0) {
1002                 if (ncp_is_nfs_extras(server, finfo.volume)) {
1003                         mode |= S_IFDIR;
1004                         finfo.i.nfs.mode = mode;
1005                         if (ncp_modify_nfs_info(server,
1006                                                 finfo.volume,
1007                                                 finfo.i.dirEntNum,
1008                                                 mode, 0) != 0)
1009                                 goto out;
1010                 }
1011                 error = ncp_instantiate(dir, dentry, &finfo);
1012         } else if (error > 0) {
1013                 error = -EACCES;
1014         }
1015 out:
1016         return error;
1017 }
1018
1019 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1020 {
1021         struct ncp_server *server = NCP_SERVER(dir);
1022         int error, result, len;
1023         __u8 __name[NCP_MAXPATHLEN + 1];
1024
1025         DPRINTK("ncp_rmdir: removing %pd2\n", dentry);
1026
1027         len = sizeof(__name);
1028         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1029                            dentry->d_name.len, !ncp_preserve_case(dir));
1030         if (error)
1031                 goto out;
1032
1033         result = ncp_del_file_or_subdir(server, dir, __name);
1034         switch (result) {
1035                 case 0x00:
1036                         error = 0;
1037                         break;
1038                 case 0x85:      /* unauthorized to delete file */
1039                 case 0x8A:      /* unauthorized to delete file */
1040                         error = -EACCES;
1041                         break;
1042                 case 0x8F:
1043                 case 0x90:      /* read only */
1044                         error = -EPERM;
1045                         break;
1046                 case 0x9F:      /* in use by another client */
1047                         error = -EBUSY;
1048                         break;
1049                 case 0xA0:      /* directory not empty */
1050                         error = -ENOTEMPTY;
1051                         break;
1052                 case 0xFF:      /* someone deleted file */
1053                         error = -ENOENT;
1054                         break;
1055                 default:
1056                         error = result < 0 ? result : -EACCES;
1057                         break;
1058         }
1059 out:
1060         return error;
1061 }
1062
1063 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1064 {
1065         struct inode *inode = dentry->d_inode;
1066         struct ncp_server *server;
1067         int error;
1068
1069         server = NCP_SERVER(dir);
1070         DPRINTK("ncp_unlink: unlinking %pd2\n", dentry);
1071         
1072         /*
1073          * Check whether to close the file ...
1074          */
1075         if (inode) {
1076                 PPRINTK("ncp_unlink: closing file\n");
1077                 ncp_make_closed(inode);
1078         }
1079
1080         error = ncp_del_file_or_subdir2(server, dentry);
1081 #ifdef CONFIG_NCPFS_STRONG
1082         /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1083            it is not :-( */
1084         if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1085                 error = ncp_force_unlink(dir, dentry);
1086         }
1087 #endif
1088         switch (error) {
1089                 case 0x00:
1090                         DPRINTK("ncp: removed %pd2\n", dentry);
1091                         break;
1092                 case 0x85:
1093                 case 0x8A:
1094                         error = -EACCES;
1095                         break;
1096                 case 0x8D:      /* some files in use */
1097                 case 0x8E:      /* all files in use */
1098                         error = -EBUSY;
1099                         break;
1100                 case 0x8F:      /* some read only */
1101                 case 0x90:      /* all read only */
1102                 case 0x9C:      /* !!! returned when in-use or read-only by NW4 */
1103                         error = -EPERM;
1104                         break;
1105                 case 0xFF:
1106                         error = -ENOENT;
1107                         break;
1108                 default:
1109                         error = error < 0 ? error : -EACCES;
1110                         break;
1111         }
1112         return error;
1113 }
1114
1115 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1116                       struct inode *new_dir, struct dentry *new_dentry)
1117 {
1118         struct ncp_server *server = NCP_SERVER(old_dir);
1119         int error;
1120         int old_len, new_len;
1121         __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1122
1123         DPRINTK("ncp_rename: %pd2 to %pd2\n", old_dentry, new_dentry);
1124
1125         ncp_age_dentry(server, old_dentry);
1126         ncp_age_dentry(server, new_dentry);
1127
1128         old_len = sizeof(__old_name);
1129         error = ncp_io2vol(server, __old_name, &old_len,
1130                            old_dentry->d_name.name, old_dentry->d_name.len,
1131                            !ncp_preserve_case(old_dir));
1132         if (error)
1133                 goto out;
1134
1135         new_len = sizeof(__new_name);
1136         error = ncp_io2vol(server, __new_name, &new_len,
1137                            new_dentry->d_name.name, new_dentry->d_name.len,
1138                            !ncp_preserve_case(new_dir));
1139         if (error)
1140                 goto out;
1141
1142         error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1143                                                       new_dir, __new_name);
1144 #ifdef CONFIG_NCPFS_STRONG
1145         if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1146                         server->m.flags & NCP_MOUNT_STRONG) {   /* RO */
1147                 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1148                                          new_dir, new_dentry, __new_name);
1149         }
1150 #endif
1151         switch (error) {
1152                 case 0x00:
1153                         DPRINTK("ncp renamed %pd -> %pd.\n",
1154                                 old_dentry, new_dentry);
1155                         break;
1156                 case 0x9E:
1157                         error = -ENAMETOOLONG;
1158                         break;
1159                 case 0xFF:
1160                         error = -ENOENT;
1161                         break;
1162                 default:
1163                         error = error < 0 ? error : -EACCES;
1164                         break;
1165         }
1166 out:
1167         return error;
1168 }
1169
1170 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1171                      umode_t mode, dev_t rdev)
1172 {
1173         if (!new_valid_dev(rdev))
1174                 return -EINVAL;
1175         if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1176                 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%ho\n", mode);
1177                 return ncp_create_new(dir, dentry, mode, rdev, 0);
1178         }
1179         return -EPERM; /* Strange, but true */
1180 }
1181
1182 /* The following routines are taken directly from msdos-fs */
1183
1184 /* Linear day numbers of the respective 1sts in non-leap years. */
1185
1186 static int day_n[] =
1187 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1188 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1189
1190
1191 extern struct timezone sys_tz;
1192
1193 static int utc2local(int time)
1194 {
1195         return time - sys_tz.tz_minuteswest * 60;
1196 }
1197
1198 static int local2utc(int time)
1199 {
1200         return time + sys_tz.tz_minuteswest * 60;
1201 }
1202
1203 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1204 int
1205 ncp_date_dos2unix(__le16 t, __le16 d)
1206 {
1207         unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1208         int month, year, secs;
1209
1210         /* first subtract and mask after that... Otherwise, if
1211            date == 0, bad things happen */
1212         month = ((date >> 5) - 1) & 15;
1213         year = date >> 9;
1214         secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1215                 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
1216                 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1217         /* days since 1.1.70 plus 80's leap day */
1218         return local2utc(secs);
1219 }
1220
1221
1222 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1223 void
1224 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1225 {
1226         int day, year, nl_day, month;
1227
1228         unix_date = utc2local(unix_date);
1229         *time = cpu_to_le16(
1230                 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1231                 (((unix_date / 3600) % 24) << 11));
1232         day = unix_date / 86400 - 3652;
1233         year = day / 365;
1234         if ((year + 3) / 4 + 365 * year > day)
1235                 year--;
1236         day -= (year + 3) / 4 + 365 * year;
1237         if (day == 59 && !(year & 3)) {
1238                 nl_day = day;
1239                 month = 2;
1240         } else {
1241                 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1242                 for (month = 1; month < 12; month++)
1243                         if (day_n[month] > nl_day)
1244                                 break;
1245         }
1246         *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1247 }