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