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