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