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