]> git.karo-electronics.de Git - mv-sheeva.git/blob - fs/ncpfs/dir.c
Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mv-sheeva.git] / fs / ncpfs / dir.c
1 /*
2  *  dir.c
3  *
4  *  Copyright (C) 1995, 1996 by Volker Lendecke
5  *  Modified for big endian by J.F. Chadima and David S. Miller
6  *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7  *  Modified 1998, 1999 Wolfram Pienkoss for NLS
8  *  Modified 1999 Wolfram Pienkoss for directory caching
9  *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
10  *
11  */
12
13
14 #include <linux/time.h>
15 #include <linux/errno.h>
16 #include <linux/stat.h>
17 #include <linux/kernel.h>
18 #include <linux/vmalloc.h>
19 #include <linux/mm.h>
20 #include <asm/uaccess.h>
21 #include <asm/byteorder.h>
22 #include <linux/smp_lock.h>
23
24 #include <linux/ncp_fs.h>
25
26 #include "ncplib_kernel.h"
27
28 static void ncp_read_volume_list(struct file *, void *, filldir_t,
29                                 struct ncp_cache_control *);
30 static void ncp_do_readdir(struct file *, void *, filldir_t,
31                                 struct ncp_cache_control *);
32
33 static int ncp_readdir(struct file *, void *, filldir_t);
34
35 static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
36 static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
37 static int ncp_unlink(struct inode *, struct dentry *);
38 static int ncp_mkdir(struct inode *, struct dentry *, int);
39 static int ncp_rmdir(struct inode *, struct dentry *);
40 static int ncp_rename(struct inode *, struct dentry *,
41                       struct inode *, struct dentry *);
42 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
43                      int mode, dev_t rdev);
44 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
45 extern int ncp_symlink(struct inode *, struct dentry *, const char *);
46 #else
47 #define ncp_symlink NULL
48 #endif
49                       
50 const struct file_operations ncp_dir_operations =
51 {
52         .read           = generic_read_dir,
53         .readdir        = ncp_readdir,
54         .ioctl          = ncp_ioctl,
55 #ifdef CONFIG_COMPAT
56         .compat_ioctl   = ncp_compat_ioctl,
57 #endif
58 };
59
60 const struct inode_operations ncp_dir_inode_operations =
61 {
62         .create         = ncp_create,
63         .lookup         = ncp_lookup,
64         .unlink         = ncp_unlink,
65         .symlink        = ncp_symlink,
66         .mkdir          = ncp_mkdir,
67         .rmdir          = ncp_rmdir,
68         .mknod          = ncp_mknod,
69         .rename         = ncp_rename,
70         .setattr        = ncp_notify_change,
71 };
72
73 /*
74  * Dentry operations routines
75  */
76 static int ncp_lookup_validate(struct dentry *, struct nameidata *);
77 static int ncp_hash_dentry(struct dentry *, struct qstr *);
78 static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
79 static int ncp_delete_dentry(struct dentry *);
80
81 static const struct dentry_operations ncp_dentry_operations =
82 {
83         .d_revalidate   = ncp_lookup_validate,
84         .d_hash         = ncp_hash_dentry,
85         .d_compare      = ncp_compare_dentry,
86         .d_delete       = ncp_delete_dentry,
87 };
88
89 const struct dentry_operations ncp_root_dentry_operations =
90 {
91         .d_hash         = ncp_hash_dentry,
92         .d_compare      = ncp_compare_dentry,
93         .d_delete       = ncp_delete_dentry,
94 };
95
96
97 /*
98  * Note: leave the hash unchanged if the directory
99  * is case-sensitive.
100  */
101 static int 
102 ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
103 {
104         struct nls_table *t;
105         unsigned long hash;
106         int i;
107
108         t = NCP_IO_TABLE(dentry);
109
110         if (!ncp_case_sensitive(dentry->d_inode)) {
111                 hash = init_name_hash();
112                 for (i=0; i<this->len ; i++)
113                         hash = partial_name_hash(ncp_tolower(t, this->name[i]),
114                                                                         hash);
115                 this->hash = end_name_hash(hash);
116         }
117         return 0;
118 }
119
120 static int
121 ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
122 {
123         if (a->len != b->len)
124                 return 1;
125
126         if (ncp_case_sensitive(dentry->d_inode))
127                 return strncmp(a->name, b->name, a->len);
128
129         return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
130 }
131
132 /*
133  * This is the callback from dput() when d_count is going to 0.
134  * We use this to unhash dentries with bad inodes.
135  * Closing files can be safely postponed until iput() - it's done there anyway.
136  */
137 static int
138 ncp_delete_dentry(struct dentry * dentry)
139 {
140         struct inode *inode = dentry->d_inode;
141
142         if (inode) {
143                 if (is_bad_inode(inode))
144                         return 1;
145         } else
146         {
147         /* N.B. Unhash negative dentries? */
148         }
149         return 0;
150 }
151
152 static inline int
153 ncp_single_volume(struct ncp_server *server)
154 {
155         return (server->m.mounted_vol[0] != '\0');
156 }
157
158 static inline int ncp_is_server_root(struct inode *inode)
159 {
160         return (!ncp_single_volume(NCP_SERVER(inode)) &&
161                 inode == inode->i_sb->s_root->d_inode);
162 }
163
164
165 /*
166  * This is the callback when the dcache has a lookup hit.
167  */
168
169
170 #ifdef CONFIG_NCPFS_STRONG
171 /* try to delete a readonly file (NW R bit set) */
172
173 static int
174 ncp_force_unlink(struct inode *dir, struct dentry* dentry)
175 {
176         int res=0x9c,res2;
177         struct nw_modify_dos_info info;
178         __le32 old_nwattr;
179         struct inode *inode;
180
181         memset(&info, 0, sizeof(info));
182         
183         /* remove the Read-Only flag on the NW server */
184         inode = dentry->d_inode;
185
186         old_nwattr = NCP_FINFO(inode)->nwattr;
187         info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
188         res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
189         if (res2)
190                 goto leave_me;
191
192         /* now try again the delete operation */
193         res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
194
195         if (res)  /* delete failed, set R bit again */
196         {
197                 info.attributes = old_nwattr;
198                 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
199                 if (res2)
200                         goto leave_me;
201         }
202 leave_me:
203         return(res);
204 }
205 #endif  /* CONFIG_NCPFS_STRONG */
206
207 #ifdef CONFIG_NCPFS_STRONG
208 static int
209 ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
210                  struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
211 {
212         struct nw_modify_dos_info info;
213         int res=0x90,res2;
214         struct inode *old_inode = old_dentry->d_inode;
215         __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
216         __le32 new_nwattr = 0; /* shut compiler warning */
217         int old_nwattr_changed = 0;
218         int new_nwattr_changed = 0;
219
220         memset(&info, 0, sizeof(info));
221         
222         /* remove the Read-Only flag on the NW server */
223
224         info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
225         res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
226         if (!res2)
227                 old_nwattr_changed = 1;
228         if (new_dentry && new_dentry->d_inode) {
229                 new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
230                 info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
231                 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
232                 if (!res2)
233                         new_nwattr_changed = 1;
234         }
235         /* now try again the rename operation */
236         /* but only if something really happened */
237         if (new_nwattr_changed || old_nwattr_changed) {
238                 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
239                                                     old_dir, _old_name,
240                                                     new_dir, _new_name);
241         } 
242         if (res)
243                 goto leave_me;
244         /* file was successfully renamed, so:
245            do not set attributes on old file - it no longer exists
246            copy attributes from old file to new */
247         new_nwattr_changed = old_nwattr_changed;
248         new_nwattr = old_nwattr;
249         old_nwattr_changed = 0;
250         
251 leave_me:;
252         if (old_nwattr_changed) {
253                 info.attributes = old_nwattr;
254                 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
255                 /* ignore errors */
256         }
257         if (new_nwattr_changed) {
258                 info.attributes = new_nwattr;
259                 res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
260                 /* ignore errors */
261         }
262         return(res);
263 }
264 #endif  /* CONFIG_NCPFS_STRONG */
265
266
267 static int
268 __ncp_lookup_validate(struct dentry *dentry)
269 {
270         struct ncp_server *server;
271         struct dentry *parent;
272         struct inode *dir;
273         struct ncp_entry_info finfo;
274         int res, val = 0, len;
275         __u8 __name[NCP_MAXPATHLEN + 1];
276
277         parent = dget_parent(dentry);
278         dir = parent->d_inode;
279
280         if (!dentry->d_inode)
281                 goto finished;
282
283         server = NCP_SERVER(dir);
284
285         if (!ncp_conn_valid(server))
286                 goto finished;
287
288         /*
289          * Inspired by smbfs:
290          * The default validation is based on dentry age:
291          * We set the max age at mount time.  (But each
292          * successful server lookup renews the timestamp.)
293          */
294         val = NCP_TEST_AGE(server, dentry);
295         if (val)
296                 goto finished;
297
298         DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
299                 dentry->d_parent->d_name.name, dentry->d_name.name,
300                 NCP_GET_AGE(dentry));
301
302         len = sizeof(__name);
303         if (ncp_is_server_root(dir)) {
304                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
305                                  dentry->d_name.len, 1);
306                 if (!res)
307                         res = ncp_lookup_volume(server, __name, &(finfo.i));
308         } else {
309                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
310                                  dentry->d_name.len, !ncp_preserve_case(dir));
311                 if (!res)
312                         res = ncp_obtain_info(server, dir, __name, &(finfo.i));
313         }
314         finfo.volume = finfo.i.volNumber;
315         DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
316                 dentry->d_parent->d_name.name, __name, res);
317         /*
318          * If we didn't find it, or if it has a different dirEntNum to
319          * what we remember, it's not valid any more.
320          */
321         if (!res) {
322                 if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
323                         ncp_new_dentry(dentry);
324                         val=1;
325                 } else
326                         DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
327
328                 ncp_update_inode2(dentry->d_inode, &finfo);
329         }
330
331 finished:
332         DDPRINTK("ncp_lookup_validate: result=%d\n", val);
333         dput(parent);
334         return val;
335 }
336
337 static int
338 ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
339 {
340         int res;
341         lock_kernel();
342         res = __ncp_lookup_validate(dentry);
343         unlock_kernel();
344         return res;
345 }
346
347 static struct dentry *
348 ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
349 {
350         struct dentry *dent = dentry;
351         struct list_head *next;
352
353         if (d_validate(dent, parent)) {
354                 if (dent->d_name.len <= NCP_MAXPATHLEN &&
355                     (unsigned long)dent->d_fsdata == fpos) {
356                         if (!dent->d_inode) {
357                                 dput(dent);
358                                 dent = NULL;
359                         }
360                         return dent;
361                 }
362                 dput(dent);
363         }
364
365         /* If a pointer is invalid, we search the dentry. */
366         spin_lock(&dcache_lock);
367         next = parent->d_subdirs.next;
368         while (next != &parent->d_subdirs) {
369                 dent = list_entry(next, struct dentry, d_u.d_child);
370                 if ((unsigned long)dent->d_fsdata == fpos) {
371                         if (dent->d_inode)
372                                 dget_locked(dent);
373                         else
374                                 dent = NULL;
375                         spin_unlock(&dcache_lock);
376                         goto out;
377                 }
378                 next = next->next;
379         }
380         spin_unlock(&dcache_lock);
381         return NULL;
382
383 out:
384         return dent;
385 }
386
387 static time_t ncp_obtain_mtime(struct dentry *dentry)
388 {
389         struct inode *inode = dentry->d_inode;
390         struct ncp_server *server = NCP_SERVER(inode);
391         struct nw_info_struct i;
392
393         if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
394                 return 0;
395
396         if (ncp_obtain_info(server, inode, NULL, &i))
397                 return 0;
398
399         return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
400 }
401
402 static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
403 {
404         struct dentry *dentry = filp->f_path.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_path.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_path.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_path.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         /* We MUST NOT use server->buffer_size handshaked with server if we are
710            using UDP, as for UDP server uses max. buffer size determined by
711            MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 
712            So we use 128KB, just to be sure, as there is no way how to know
713            this value in advance. */
714         bufsize = 131072;
715         buf = vmalloc(bufsize);
716         if (!buf)
717                 return;
718         do {
719                 int cnt;
720                 char* rpl;
721                 size_t rpls;
722
723                 err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
724                 if (err)                /* Error */
725                         break;
726                 if (!cnt)               /* prevent endless loop */
727                         break;
728                 while (cnt--) {
729                         size_t onerpl;
730                         
731                         if (rpls < offsetof(struct nw_info_struct, entryName))
732                                 break;  /* short packet */
733                         ncp_extract_file_info(rpl, &entry.i);
734                         onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
735                         if (rpls < onerpl)
736                                 break;  /* short packet */
737                         (void)ncp_obtain_nfs_info(server, &entry.i);
738                         rpl += onerpl;
739                         rpls -= onerpl;
740                         entry.volume = entry.i.volNumber;
741                         if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
742                                 break;
743                 }
744         } while (more);
745         vfree(buf);
746         return;
747 }
748
749 int ncp_conn_logged_in(struct super_block *sb)
750 {
751         struct ncp_server* server = NCP_SBP(sb);
752         int result;
753
754         if (ncp_single_volume(server)) {
755                 int len;
756                 struct dentry* dent;
757                 __u32 volNumber;
758                 __le32 dirEntNum;
759                 __le32 DosDirNum;
760                 __u8 __name[NCP_MAXPATHLEN + 1];
761
762                 len = sizeof(__name);
763                 result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
764                                     strlen(server->m.mounted_vol), 1);
765                 if (result)
766                         goto out;
767                 result = -ENOENT;
768                 if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
769                         PPRINTK("ncp_conn_logged_in: %s not found\n",
770                                 server->m.mounted_vol);
771                         goto out;
772                 }
773                 dent = sb->s_root;
774                 if (dent) {
775                         struct inode* ino = dent->d_inode;
776                         if (ino) {
777                                 NCP_FINFO(ino)->volNumber = volNumber;
778                                 NCP_FINFO(ino)->dirEntNum = dirEntNum;
779                                 NCP_FINFO(ino)->DosDirNum = DosDirNum;
780                         } else {
781                                 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
782                         }
783                 } else {
784                         DPRINTK("ncpfs: sb->s_root == NULL!\n");
785                 }
786         }
787         result = 0;
788
789 out:
790         return result;
791 }
792
793 static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
794 {
795         struct ncp_server *server = NCP_SERVER(dir);
796         struct inode *inode = NULL;
797         struct ncp_entry_info finfo;
798         int error, res, len;
799         __u8 __name[NCP_MAXPATHLEN + 1];
800
801         lock_kernel();
802         error = -EIO;
803         if (!ncp_conn_valid(server))
804                 goto finished;
805
806         PPRINTK("ncp_lookup: server lookup for %s/%s\n",
807                 dentry->d_parent->d_name.name, dentry->d_name.name);
808
809         len = sizeof(__name);
810         if (ncp_is_server_root(dir)) {
811                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
812                                  dentry->d_name.len, 1);
813                 if (!res)
814                         res = ncp_lookup_volume(server, __name, &(finfo.i));
815         } else {
816                 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
817                                  dentry->d_name.len, !ncp_preserve_case(dir));
818                 if (!res)
819                         res = ncp_obtain_info(server, dir, __name, &(finfo.i));
820         }
821         PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
822                 dentry->d_parent->d_name.name, __name, res);
823         /*
824          * If we didn't find an entry, make a negative dentry.
825          */
826         if (res)
827                 goto add_entry;
828
829         /*
830          * Create an inode for the entry.
831          */
832         finfo.opened = 0;
833         finfo.ino = iunique(dir->i_sb, 2);
834         finfo.volume = finfo.i.volNumber;
835         error = -EACCES;
836         inode = ncp_iget(dir->i_sb, &finfo);
837
838         if (inode) {
839                 ncp_new_dentry(dentry);
840 add_entry:
841                 dentry->d_op = &ncp_dentry_operations;
842                 d_add(dentry, inode);
843                 error = 0;
844         }
845
846 finished:
847         PPRINTK("ncp_lookup: result=%d\n", error);
848         unlock_kernel();
849         return ERR_PTR(error);
850 }
851
852 /*
853  * This code is common to create, mkdir, and mknod.
854  */
855 static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
856                         struct ncp_entry_info *finfo)
857 {
858         struct inode *inode;
859         int error = -EINVAL;
860
861         finfo->ino = iunique(dir->i_sb, 2);
862         inode = ncp_iget(dir->i_sb, finfo);
863         if (!inode)
864                 goto out_close;
865         d_instantiate(dentry,inode);
866         error = 0;
867 out:
868         return error;
869
870 out_close:
871         PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
872                 dentry->d_parent->d_name.name, dentry->d_name.name);
873         ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
874         goto out;
875 }
876
877 int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
878                    dev_t rdev, __le32 attributes)
879 {
880         struct ncp_server *server = NCP_SERVER(dir);
881         struct ncp_entry_info finfo;
882         int error, result, len;
883         int opmode;
884         __u8 __name[NCP_MAXPATHLEN + 1];
885         
886         PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
887                 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
888
889         error = -EIO;
890         lock_kernel();
891         if (!ncp_conn_valid(server))
892                 goto out;
893
894         ncp_age_dentry(server, dentry);
895         len = sizeof(__name);
896         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
897                            dentry->d_name.len, !ncp_preserve_case(dir));
898         if (error)
899                 goto out;
900
901         error = -EACCES;
902         
903         if (S_ISREG(mode) && 
904             (server->m.flags & NCP_MOUNT_EXTRAS) && 
905             (mode & S_IXUGO))
906                 attributes |= aSYSTEM | aSHARED;
907         
908         result = ncp_open_create_file_or_subdir(server, dir, __name,
909                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
910                                 attributes, AR_READ | AR_WRITE, &finfo);
911         opmode = O_RDWR;
912         if (result) {
913                 result = ncp_open_create_file_or_subdir(server, dir, __name,
914                                 OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
915                                 attributes, AR_WRITE, &finfo);
916                 if (result) {
917                         if (result == 0x87)
918                                 error = -ENAMETOOLONG;
919                         DPRINTK("ncp_create: %s/%s failed\n",
920                                 dentry->d_parent->d_name.name, dentry->d_name.name);
921                         goto out;
922                 }
923                 opmode = O_WRONLY;
924         }
925         finfo.access = opmode;
926         if (ncp_is_nfs_extras(server, finfo.volume)) {
927                 finfo.i.nfs.mode = mode;
928                 finfo.i.nfs.rdev = new_encode_dev(rdev);
929                 if (ncp_modify_nfs_info(server, finfo.volume,
930                                         finfo.i.dirEntNum,
931                                         mode, new_encode_dev(rdev)) != 0)
932                         goto out;
933         }
934
935         error = ncp_instantiate(dir, dentry, &finfo);
936 out:
937         unlock_kernel();
938         return error;
939 }
940
941 static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
942                 struct nameidata *nd)
943 {
944         return ncp_create_new(dir, dentry, mode, 0, 0);
945 }
946
947 static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
948 {
949         struct ncp_entry_info finfo;
950         struct ncp_server *server = NCP_SERVER(dir);
951         int error, len;
952         __u8 __name[NCP_MAXPATHLEN + 1];
953
954         DPRINTK("ncp_mkdir: making %s/%s\n",
955                 dentry->d_parent->d_name.name, dentry->d_name.name);
956
957         error = -EIO;
958         lock_kernel();
959         if (!ncp_conn_valid(server))
960                 goto out;
961
962         ncp_age_dentry(server, dentry);
963         len = sizeof(__name);
964         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
965                            dentry->d_name.len, !ncp_preserve_case(dir));
966         if (error)
967                 goto out;
968
969         error = -EACCES;
970         if (ncp_open_create_file_or_subdir(server, dir, __name,
971                                            OC_MODE_CREATE, aDIR,
972                                            cpu_to_le16(0xffff),
973                                            &finfo) == 0)
974         {
975                 if (ncp_is_nfs_extras(server, finfo.volume)) {
976                         mode |= S_IFDIR;
977                         finfo.i.nfs.mode = mode;
978                         if (ncp_modify_nfs_info(server,
979                                                 finfo.volume,
980                                                 finfo.i.dirEntNum,
981                                                 mode, 0) != 0)
982                                 goto out;
983                 }
984                 error = ncp_instantiate(dir, dentry, &finfo);
985         }
986 out:
987         unlock_kernel();
988         return error;
989 }
990
991 static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
992 {
993         struct ncp_server *server = NCP_SERVER(dir);
994         int error, result, len;
995         __u8 __name[NCP_MAXPATHLEN + 1];
996
997         DPRINTK("ncp_rmdir: removing %s/%s\n",
998                 dentry->d_parent->d_name.name, dentry->d_name.name);
999
1000         error = -EIO;
1001         lock_kernel();
1002         if (!ncp_conn_valid(server))
1003                 goto out;
1004
1005         error = -EBUSY;
1006         if (!d_unhashed(dentry))
1007                 goto out;
1008
1009         len = sizeof(__name);
1010         error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
1011                            dentry->d_name.len, !ncp_preserve_case(dir));
1012         if (error)
1013                 goto out;
1014
1015         result = ncp_del_file_or_subdir(server, dir, __name);
1016         switch (result) {
1017                 case 0x00:
1018                         error = 0;
1019                         break;
1020                 case 0x85:      /* unauthorized to delete file */
1021                 case 0x8A:      /* unauthorized to delete file */
1022                         error = -EACCES;
1023                         break;
1024                 case 0x8F:
1025                 case 0x90:      /* read only */
1026                         error = -EPERM;
1027                         break;
1028                 case 0x9F:      /* in use by another client */
1029                         error = -EBUSY;
1030                         break;
1031                 case 0xA0:      /* directory not empty */
1032                         error = -ENOTEMPTY;
1033                         break;
1034                 case 0xFF:      /* someone deleted file */
1035                         error = -ENOENT;
1036                         break;
1037                 default:
1038                         error = -EACCES;
1039                         break;
1040         }
1041 out:
1042         unlock_kernel();
1043         return error;
1044 }
1045
1046 static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1047 {
1048         struct inode *inode = dentry->d_inode;
1049         struct ncp_server *server;
1050         int error;
1051
1052         lock_kernel();
1053         server = NCP_SERVER(dir);
1054         DPRINTK("ncp_unlink: unlinking %s/%s\n",
1055                 dentry->d_parent->d_name.name, dentry->d_name.name);
1056         
1057         error = -EIO;
1058         if (!ncp_conn_valid(server))
1059                 goto out;
1060
1061         /*
1062          * Check whether to close the file ...
1063          */
1064         if (inode) {
1065                 PPRINTK("ncp_unlink: closing file\n");
1066                 ncp_make_closed(inode);
1067         }
1068
1069         error = ncp_del_file_or_subdir2(server, dentry);
1070 #ifdef CONFIG_NCPFS_STRONG
1071         /* 9C is Invalid path.. It should be 8F, 90 - read only, but
1072            it is not :-( */
1073         if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
1074                 error = ncp_force_unlink(dir, dentry);
1075         }
1076 #endif
1077         switch (error) {
1078                 case 0x00:
1079                         DPRINTK("ncp: removed %s/%s\n",
1080                                 dentry->d_parent->d_name.name, dentry->d_name.name);
1081                         break;
1082                 case 0x85:
1083                 case 0x8A:
1084                         error = -EACCES;
1085                         break;
1086                 case 0x8D:      /* some files in use */
1087                 case 0x8E:      /* all files in use */
1088                         error = -EBUSY;
1089                         break;
1090                 case 0x8F:      /* some read only */
1091                 case 0x90:      /* all read only */
1092                 case 0x9C:      /* !!! returned when in-use or read-only by NW4 */
1093                         error = -EPERM;
1094                         break;
1095                 case 0xFF:
1096                         error = -ENOENT;
1097                         break;
1098                 default:
1099                         error = -EACCES;
1100                         break;
1101         }
1102                 
1103 out:
1104         unlock_kernel();
1105         return error;
1106 }
1107
1108 static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1109                       struct inode *new_dir, struct dentry *new_dentry)
1110 {
1111         struct ncp_server *server = NCP_SERVER(old_dir);
1112         int error;
1113         int old_len, new_len;
1114         __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
1115
1116         DPRINTK("ncp_rename: %s/%s to %s/%s\n",
1117                 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1118                 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1119
1120         error = -EIO;
1121         lock_kernel();
1122         if (!ncp_conn_valid(server))
1123                 goto out;
1124
1125         ncp_age_dentry(server, old_dentry);
1126         ncp_age_dentry(server, new_dentry);
1127
1128         old_len = sizeof(__old_name);
1129         error = ncp_io2vol(server, __old_name, &old_len,
1130                            old_dentry->d_name.name, old_dentry->d_name.len,
1131                            !ncp_preserve_case(old_dir));
1132         if (error)
1133                 goto out;
1134
1135         new_len = sizeof(__new_name);
1136         error = ncp_io2vol(server, __new_name, &new_len,
1137                            new_dentry->d_name.name, new_dentry->d_name.len,
1138                            !ncp_preserve_case(new_dir));
1139         if (error)
1140                 goto out;
1141
1142         error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
1143                                                       new_dir, __new_name);
1144 #ifdef CONFIG_NCPFS_STRONG
1145         if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
1146                         server->m.flags & NCP_MOUNT_STRONG) {   /* RO */
1147                 error = ncp_force_rename(old_dir, old_dentry, __old_name,
1148                                          new_dir, new_dentry, __new_name);
1149         }
1150 #endif
1151         switch (error) {
1152                 case 0x00:
1153                         DPRINTK("ncp renamed %s -> %s.\n",
1154                                 old_dentry->d_name.name,new_dentry->d_name.name);
1155                         break;
1156                 case 0x9E:
1157                         error = -ENAMETOOLONG;
1158                         break;
1159                 case 0xFF:
1160                         error = -ENOENT;
1161                         break;
1162                 default:
1163                         error = -EACCES;
1164                         break;
1165         }
1166 out:
1167         unlock_kernel();
1168         return error;
1169 }
1170
1171 static int ncp_mknod(struct inode * dir, struct dentry *dentry,
1172                      int mode, dev_t rdev)
1173 {
1174         if (!new_valid_dev(rdev))
1175                 return -EINVAL;
1176         if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
1177                 DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
1178                 return ncp_create_new(dir, dentry, mode, rdev, 0);
1179         }
1180         return -EPERM; /* Strange, but true */
1181 }
1182
1183 /* The following routines are taken directly from msdos-fs */
1184
1185 /* Linear day numbers of the respective 1sts in non-leap years. */
1186
1187 static int day_n[] =
1188 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
1189 /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
1190
1191
1192 extern struct timezone sys_tz;
1193
1194 static int utc2local(int time)
1195 {
1196         return time - sys_tz.tz_minuteswest * 60;
1197 }
1198
1199 static int local2utc(int time)
1200 {
1201         return time + sys_tz.tz_minuteswest * 60;
1202 }
1203
1204 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
1205 int
1206 ncp_date_dos2unix(__le16 t, __le16 d)
1207 {
1208         unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
1209         int month, year, secs;
1210
1211         /* first subtract and mask after that... Otherwise, if
1212            date == 0, bad things happen */
1213         month = ((date >> 5) - 1) & 15;
1214         year = date >> 9;
1215         secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
1216                 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + 
1217                 year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
1218         /* days since 1.1.70 plus 80's leap day */
1219         return local2utc(secs);
1220 }
1221
1222
1223 /* Convert linear UNIX date to a MS-DOS time/date pair. */
1224 void
1225 ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
1226 {
1227         int day, year, nl_day, month;
1228
1229         unix_date = utc2local(unix_date);
1230         *time = cpu_to_le16(
1231                 (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
1232                 (((unix_date / 3600) % 24) << 11));
1233         day = unix_date / 86400 - 3652;
1234         year = day / 365;
1235         if ((year + 3) / 4 + 365 * year > day)
1236                 year--;
1237         day -= (year + 3) / 4 + 365 * year;
1238         if (day == 59 && !(year & 3)) {
1239                 nl_day = day;
1240                 month = 2;
1241         } else {
1242                 nl_day = (year & 3) || day <= 59 ? day : day - 1;
1243                 for (month = 1; month < 12; month++)
1244                         if (day_n[month] > nl_day)
1245                                 break;
1246         }
1247         *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
1248 }