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