aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Vandrovec <petr@vandrovec.name>2010-09-26 19:47:33 -0400
committerArnd Bergmann <arnd@arndb.de>2010-10-04 15:10:52 -0400
commit2e54eb96e2c801f33d95b5dade15212ac4d6c4a5 (patch)
treec2996f29aa49881e93c7a37fad41e4961f6b8578
parent60056794127a25d641465b706e8828186f7a2e1f (diff)
BKL: Remove BKL from ncpfs
Dozen of changes in ncpfs to provide some locking other than BKL. In readdir cache unlock and mark complete first page as last operation, so it can be used for synchronization, as code intended. When updating dentry name on case insensitive filesystems do at least some basic locking... Hold i_mutex when updating inode fields. Push some ncp_conn_is_valid down to ncp_request. Connection can become invalid at any moment, and fewer error code paths to test the better. Use i_size_{read,write} to modify file size. Set inode's backing_dev_info as ncpfs has its own special bdi. In ioctl unbreak ioctls invoked on filesystem mounted 'ro' - tests are for inode writeable or owner match, but were turned to filesystem writeable and inode writeable or owner match. Also collect all permission checks in single place. Add some locking, and remove comments saying that it would be cool to add some locks to the code. Constify some pointers. Signed-off-by: Petr Vandrovec <petr@vandrovec.name> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--fs/ncpfs/dir.c221
-rw-r--r--fs/ncpfs/file.c25
-rw-r--r--fs/ncpfs/inode.c41
-rw-r--r--fs/ncpfs/ioctl.c470
-rw-r--r--fs/ncpfs/ncplib_kernel.c101
-rw-r--r--fs/ncpfs/ncplib_kernel.h15
-rw-r--r--fs/ncpfs/ncpsign_kernel.c10
-rw-r--r--fs/ncpfs/sock.c1
-rw-r--r--include/linux/ncp_fs.h28
-rw-r--r--include/linux/ncp_fs_sb.h4
10 files changed, 487 insertions, 429 deletions
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 9578cbe0cd58..aac8832e919e 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -95,6 +95,34 @@ const struct dentry_operations ncp_root_dentry_operations =
95}; 95};
96 96
97 97
98#define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
99
100static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
101{
102#ifdef CONFIG_NCPFS_SMALLDOS
103 int ns = ncp_namespace(i);
104
105 if ((ns == NW_NS_DOS)
106#ifdef CONFIG_NCPFS_OS2_NS
107 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
108#endif /* CONFIG_NCPFS_OS2_NS */
109 )
110 return 0;
111#endif /* CONFIG_NCPFS_SMALLDOS */
112 return 1;
113}
114
115#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
116
117static inline int ncp_case_sensitive(struct dentry *dentry)
118{
119#ifdef CONFIG_NCPFS_NFS_NS
120 return ncp_namespace(dentry->d_inode) == NW_NS_NFS;
121#else
122 return 0;
123#endif /* CONFIG_NCPFS_NFS_NS */
124}
125
98/* 126/*
99 * Note: leave the hash unchanged if the directory 127 * Note: leave the hash unchanged if the directory
100 * is case-sensitive. 128 * is case-sensitive.
@@ -102,13 +130,12 @@ const struct dentry_operations ncp_root_dentry_operations =
102static int 130static int
103ncp_hash_dentry(struct dentry *dentry, struct qstr *this) 131ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
104{ 132{
105 struct nls_table *t; 133 if (!ncp_case_sensitive(dentry)) {
106 unsigned long hash; 134 struct nls_table *t;
107 int i; 135 unsigned long hash;
108 136 int i;
109 t = NCP_IO_TABLE(dentry);
110 137
111 if (!ncp_case_sensitive(dentry->d_inode)) { 138 t = NCP_IO_TABLE(dentry);
112 hash = init_name_hash(); 139 hash = init_name_hash();
113 for (i=0; i<this->len ; i++) 140 for (i=0; i<this->len ; i++)
114 hash = partial_name_hash(ncp_tolower(t, this->name[i]), 141 hash = partial_name_hash(ncp_tolower(t, this->name[i]),
@@ -124,7 +151,7 @@ ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
124 if (a->len != b->len) 151 if (a->len != b->len)
125 return 1; 152 return 1;
126 153
127 if (ncp_case_sensitive(dentry->d_inode)) 154 if (ncp_case_sensitive(dentry))
128 return strncmp(a->name, b->name, a->len); 155 return strncmp(a->name, b->name, a->len);
129 156
130 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len); 157 return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
@@ -266,7 +293,7 @@ leave_me:;
266 293
267 294
268static int 295static int
269__ncp_lookup_validate(struct dentry *dentry) 296ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
270{ 297{
271 struct ncp_server *server; 298 struct ncp_server *server;
272 struct dentry *parent; 299 struct dentry *parent;
@@ -283,9 +310,6 @@ __ncp_lookup_validate(struct dentry *dentry)
283 310
284 server = NCP_SERVER(dir); 311 server = NCP_SERVER(dir);
285 312
286 if (!ncp_conn_valid(server))
287 goto finished;
288
289 /* 313 /*
290 * Inspired by smbfs: 314 * Inspired by smbfs:
291 * The default validation is based on dentry age: 315 * The default validation is based on dentry age:
@@ -304,8 +328,11 @@ __ncp_lookup_validate(struct dentry *dentry)
304 if (ncp_is_server_root(dir)) { 328 if (ncp_is_server_root(dir)) {
305 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 329 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
306 dentry->d_name.len, 1); 330 dentry->d_name.len, 1);
307 if (!res) 331 if (!res) {
308 res = ncp_lookup_volume(server, __name, &(finfo.i)); 332 res = ncp_lookup_volume(server, __name, &(finfo.i));
333 if (!res)
334 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
335 }
309 } else { 336 } else {
310 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 337 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
311 dentry->d_name.len, !ncp_preserve_case(dir)); 338 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -320,13 +347,17 @@ __ncp_lookup_validate(struct dentry *dentry)
320 * what we remember, it's not valid any more. 347 * what we remember, it's not valid any more.
321 */ 348 */
322 if (!res) { 349 if (!res) {
323 if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) { 350 struct inode *inode = dentry->d_inode;
351
352 mutex_lock(&inode->i_mutex);
353 if (finfo.i.dirEntNum == NCP_FINFO(inode)->dirEntNum) {
324 ncp_new_dentry(dentry); 354 ncp_new_dentry(dentry);
325 val=1; 355 val=1;
326 } else 356 } else
327 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n"); 357 DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
328 358
329 ncp_update_inode2(dentry->d_inode, &finfo); 359 ncp_update_inode2(inode, &finfo);
360 mutex_unlock(&inode->i_mutex);
330 } 361 }
331 362
332finished: 363finished:
@@ -335,16 +366,6 @@ finished:
335 return val; 366 return val;
336} 367}
337 368
338static int
339ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
340{
341 int res;
342 lock_kernel();
343 res = __ncp_lookup_validate(dentry);
344 unlock_kernel();
345 return res;
346}
347
348static struct dentry * 369static struct dentry *
349ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos) 370ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
350{ 371{
@@ -411,8 +432,6 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
411 int result, mtime_valid = 0; 432 int result, mtime_valid = 0;
412 time_t mtime = 0; 433 time_t mtime = 0;
413 434
414 lock_kernel();
415
416 ctl.page = NULL; 435 ctl.page = NULL;
417 ctl.cache = NULL; 436 ctl.cache = NULL;
418 437
@@ -421,6 +440,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
421 (int) filp->f_pos); 440 (int) filp->f_pos);
422 441
423 result = -EIO; 442 result = -EIO;
443 /* Do not generate '.' and '..' when server is dead. */
424 if (!ncp_conn_valid(server)) 444 if (!ncp_conn_valid(server))
425 goto out; 445 goto out;
426 446
@@ -532,6 +552,12 @@ read_really:
532 ctl.head.end = ctl.fpos - 1; 552 ctl.head.end = ctl.fpos - 1;
533 ctl.head.eof = ctl.valid; 553 ctl.head.eof = ctl.valid;
534finished: 554finished:
555 if (ctl.page) {
556 kunmap(ctl.page);
557 SetPageUptodate(ctl.page);
558 unlock_page(ctl.page);
559 page_cache_release(ctl.page);
560 }
535 if (page) { 561 if (page) {
536 cache->head = ctl.head; 562 cache->head = ctl.head;
537 kunmap(page); 563 kunmap(page);
@@ -539,23 +565,17 @@ finished:
539 unlock_page(page); 565 unlock_page(page);
540 page_cache_release(page); 566 page_cache_release(page);
541 } 567 }
542 if (ctl.page) {
543 kunmap(ctl.page);
544 SetPageUptodate(ctl.page);
545 unlock_page(ctl.page);
546 page_cache_release(ctl.page);
547 }
548out: 568out:
549 unlock_kernel();
550 return result; 569 return result;
551} 570}
552 571
553static int 572static int
554ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir, 573ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
555 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry) 574 struct ncp_cache_control *ctrl, struct ncp_entry_info *entry,
575 int inval_childs)
556{ 576{
557 struct dentry *newdent, *dentry = filp->f_path.dentry; 577 struct dentry *newdent, *dentry = filp->f_path.dentry;
558 struct inode *newino, *inode = dentry->d_inode; 578 struct inode *dir = dentry->d_inode;
559 struct ncp_cache_control ctl = *ctrl; 579 struct ncp_cache_control ctl = *ctrl;
560 struct qstr qname; 580 struct qstr qname;
561 int valid = 0; 581 int valid = 0;
@@ -564,9 +584,9 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
564 __u8 __name[NCP_MAXPATHLEN + 1]; 584 __u8 __name[NCP_MAXPATHLEN + 1];
565 585
566 qname.len = sizeof(__name); 586 qname.len = sizeof(__name);
567 if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len, 587 if (ncp_vol2io(NCP_SERVER(dir), __name, &qname.len,
568 entry->i.entryName, entry->i.nameLen, 588 entry->i.entryName, entry->i.nameLen,
569 !ncp_preserve_entry_case(inode, entry->i.NSCreator))) 589 !ncp_preserve_entry_case(dir, entry->i.NSCreator)))
570 return 1; /* I'm not sure */ 590 return 1; /* I'm not sure */
571 591
572 qname.name = __name; 592 qname.name = __name;
@@ -584,22 +604,64 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
584 goto end_advance; 604 goto end_advance;
585 } else { 605 } else {
586 hashed = 1; 606 hashed = 1;
587 memcpy((char *) newdent->d_name.name, qname.name, 607
588 newdent->d_name.len); 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 * It is not as dangerous as it looks. NetWare's OS2 namespace is
616 * case preserving yet case insensitive. So we update dentry's name
617 * as received from server. We found dentry via d_lookup with our
618 * hash, so we know that hash does not change, and so replacing name
619 * should be reasonably safe.
620 */
621 if (qname.len == newdent->d_name.len &&
622 memcmp(newdent->d_name.name, qname.name, newdent->d_name.len)) {
623 struct inode *inode = newdent->d_inode;
624
625 /*
626 * Inside ncpfs all uses of d_name are either for debugging,
627 * or on functions which acquire inode mutex (mknod, creat,
628 * lookup). So grab i_mutex here, to be sure. d_path
629 * uses dcache_lock when generating path, so we should too.
630 * And finally d_compare is protected by dentry's d_lock, so
631 * here we go.
632 */
633 if (inode)
634 mutex_lock(&inode->i_mutex);
635 spin_lock(&dcache_lock);
636 spin_lock(&newdent->d_lock);
637 memcpy((char *) newdent->d_name.name, qname.name,
638 newdent->d_name.len);
639 spin_unlock(&newdent->d_lock);
640 spin_unlock(&dcache_lock);
641 if (inode)
642 mutex_unlock(&inode->i_mutex);
643 }
589 } 644 }
590 645
591 if (!newdent->d_inode) { 646 if (!newdent->d_inode) {
647 struct inode *inode;
648
592 entry->opened = 0; 649 entry->opened = 0;
593 entry->ino = iunique(inode->i_sb, 2); 650 entry->ino = iunique(dir->i_sb, 2);
594 newino = ncp_iget(inode->i_sb, entry); 651 inode = ncp_iget(dir->i_sb, entry);
595 if (newino) { 652 if (inode) {
596 newdent->d_op = &ncp_dentry_operations; 653 newdent->d_op = &ncp_dentry_operations;
597 d_instantiate(newdent, newino); 654 d_instantiate(newdent, inode);
598 if (!hashed) 655 if (!hashed)
599 d_rehash(newdent); 656 d_rehash(newdent);
600 } 657 }
601 } else 658 } else {
602 ncp_update_inode2(newdent->d_inode, entry); 659 struct inode *inode = newdent->d_inode;
660
661 mutex_lock(&inode->i_mutex);
662 ncp_update_inode2(inode, entry);
663 mutex_unlock(&inode->i_mutex);
664 }
603 665
604 if (newdent->d_inode) { 666 if (newdent->d_inode) {
605 ino = newdent->d_inode->i_ino; 667 ino = newdent->d_inode->i_ino;
@@ -617,7 +679,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
617 ctl.cache = NULL; 679 ctl.cache = NULL;
618 ctl.idx -= NCP_DIRCACHE_SIZE; 680 ctl.idx -= NCP_DIRCACHE_SIZE;
619 ctl.ofs += 1; 681 ctl.ofs += 1;
620 ctl.page = grab_cache_page(&inode->i_data, ctl.ofs); 682 ctl.page = grab_cache_page(&dir->i_data, ctl.ofs);
621 if (ctl.page) 683 if (ctl.page)
622 ctl.cache = kmap(ctl.page); 684 ctl.cache = kmap(ctl.page);
623 } 685 }
@@ -633,7 +695,7 @@ end_advance:
633 if (!ino) 695 if (!ino)
634 ino = find_inode_number(dentry, &qname); 696 ino = find_inode_number(dentry, &qname);
635 if (!ino) 697 if (!ino)
636 ino = iunique(inode->i_sb, 2); 698 ino = iunique(dir->i_sb, 2);
637 ctl.filled = filldir(dirent, qname.name, qname.len, 699 ctl.filled = filldir(dirent, qname.name, qname.len,
638 filp->f_pos, ino, DT_UNKNOWN); 700 filp->f_pos, ino, DT_UNKNOWN);
639 if (!ctl.filled) 701 if (!ctl.filled)
@@ -660,6 +722,7 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
660 (unsigned long) filp->f_pos); 722 (unsigned long) filp->f_pos);
661 723
662 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) { 724 for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
725 int inval_dentry;
663 726
664 if (ncp_get_volume_info_with_number(server, i, &info) != 0) 727 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
665 return; 728 return;
@@ -675,8 +738,9 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
675 info.volume_name); 738 info.volume_name);
676 continue; 739 continue;
677 } 740 }
741 inval_dentry = ncp_update_known_namespace(server, entry.i.volNumber, NULL);
678 entry.volume = entry.i.volNumber; 742 entry.volume = entry.i.volNumber;
679 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) 743 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, inval_dentry))
680 return; 744 return;
681 } 745 }
682} 746}
@@ -739,7 +803,7 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
739 rpl += onerpl; 803 rpl += onerpl;
740 rpls -= onerpl; 804 rpls -= onerpl;
741 entry.volume = entry.i.volNumber; 805 entry.volume = entry.i.volNumber;
742 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry)) 806 if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry, 0))
743 break; 807 break;
744 } 808 }
745 } while (more); 809 } while (more);
@@ -775,17 +839,19 @@ int ncp_conn_logged_in(struct super_block *sb)
775 if (dent) { 839 if (dent) {
776 struct inode* ino = dent->d_inode; 840 struct inode* ino = dent->d_inode;
777 if (ino) { 841 if (ino) {
842 ncp_update_known_namespace(server, volNumber, NULL);
778 NCP_FINFO(ino)->volNumber = volNumber; 843 NCP_FINFO(ino)->volNumber = volNumber;
779 NCP_FINFO(ino)->dirEntNum = dirEntNum; 844 NCP_FINFO(ino)->dirEntNum = dirEntNum;
780 NCP_FINFO(ino)->DosDirNum = DosDirNum; 845 NCP_FINFO(ino)->DosDirNum = DosDirNum;
846 result = 0;
781 } else { 847 } else {
782 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n"); 848 DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
783 } 849 }
784 } else { 850 } else {
785 DPRINTK("ncpfs: sb->s_root == NULL!\n"); 851 DPRINTK("ncpfs: sb->s_root == NULL!\n");
786 } 852 }
787 } 853 } else
788 result = 0; 854 result = 0;
789 855
790out: 856out:
791 return result; 857 return result;
@@ -799,7 +865,6 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc
799 int error, res, len; 865 int error, res, len;
800 __u8 __name[NCP_MAXPATHLEN + 1]; 866 __u8 __name[NCP_MAXPATHLEN + 1];
801 867
802 lock_kernel();
803 error = -EIO; 868 error = -EIO;
804 if (!ncp_conn_valid(server)) 869 if (!ncp_conn_valid(server))
805 goto finished; 870 goto finished;
@@ -813,6 +878,8 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struc
813 dentry->d_name.len, 1); 878 dentry->d_name.len, 1);
814 if (!res) 879 if (!res)
815 res = ncp_lookup_volume(server, __name, &(finfo.i)); 880 res = ncp_lookup_volume(server, __name, &(finfo.i));
881 if (!res)
882 ncp_update_known_namespace(server, finfo.i.volNumber, NULL);
816 } else { 883 } else {
817 res = ncp_io2vol(server, __name, &len, dentry->d_name.name, 884 res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
818 dentry->d_name.len, !ncp_preserve_case(dir)); 885 dentry->d_name.len, !ncp_preserve_case(dir));
@@ -846,7 +913,6 @@ add_entry:
846 913
847finished: 914finished:
848 PPRINTK("ncp_lookup: result=%d\n", error); 915 PPRINTK("ncp_lookup: result=%d\n", error);
849 unlock_kernel();
850 return ERR_PTR(error); 916 return ERR_PTR(error);
851} 917}
852 918
@@ -887,11 +953,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
887 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n", 953 PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
888 dentry->d_parent->d_name.name, dentry->d_name.name, mode); 954 dentry->d_parent->d_name.name, dentry->d_name.name, mode);
889 955
890 error = -EIO;
891 lock_kernel();
892 if (!ncp_conn_valid(server))
893 goto out;
894
895 ncp_age_dentry(server, dentry); 956 ncp_age_dentry(server, dentry);
896 len = sizeof(__name); 957 len = sizeof(__name);
897 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 958 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -917,6 +978,8 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
917 if (result) { 978 if (result) {
918 if (result == 0x87) 979 if (result == 0x87)
919 error = -ENAMETOOLONG; 980 error = -ENAMETOOLONG;
981 else if (result < 0)
982 error = result;
920 DPRINTK("ncp_create: %s/%s failed\n", 983 DPRINTK("ncp_create: %s/%s failed\n",
921 dentry->d_parent->d_name.name, dentry->d_name.name); 984 dentry->d_parent->d_name.name, dentry->d_name.name);
922 goto out; 985 goto out;
@@ -935,7 +998,6 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
935 998
936 error = ncp_instantiate(dir, dentry, &finfo); 999 error = ncp_instantiate(dir, dentry, &finfo);
937out: 1000out:
938 unlock_kernel();
939 return error; 1001 return error;
940} 1002}
941 1003
@@ -955,11 +1017,6 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
955 DPRINTK("ncp_mkdir: making %s/%s\n", 1017 DPRINTK("ncp_mkdir: making %s/%s\n",
956 dentry->d_parent->d_name.name, dentry->d_name.name); 1018 dentry->d_parent->d_name.name, dentry->d_name.name);
957 1019
958 error = -EIO;
959 lock_kernel();
960 if (!ncp_conn_valid(server))
961 goto out;
962
963 ncp_age_dentry(server, dentry); 1020 ncp_age_dentry(server, dentry);
964 len = sizeof(__name); 1021 len = sizeof(__name);
965 error = ncp_io2vol(server, __name, &len, dentry->d_name.name, 1022 error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -967,12 +1024,11 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
967 if (error) 1024 if (error)
968 goto out; 1025 goto out;
969 1026
970 error = -EACCES; 1027 error = ncp_open_create_file_or_subdir(server, dir, __name,
971 if (ncp_open_create_file_or_subdir(server, dir, __name,
972 OC_MODE_CREATE, aDIR, 1028 OC_MODE_CREATE, aDIR,
973 cpu_to_le16(0xffff), 1029 cpu_to_le16(0xffff),
974 &finfo) == 0) 1030 &finfo);
975 { 1031 if (error == 0) {
976 if (ncp_is_nfs_extras(server, finfo.volume)) { 1032 if (ncp_is_nfs_extras(server, finfo.volume)) {
977 mode |= S_IFDIR; 1033 mode |= S_IFDIR;
978 finfo.i.nfs.mode = mode; 1034 finfo.i.nfs.mode = mode;
@@ -983,9 +1039,10 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
983 goto out; 1039 goto out;
984 } 1040 }
985 error = ncp_instantiate(dir, dentry, &finfo); 1041 error = ncp_instantiate(dir, dentry, &finfo);
1042 } else if (error > 0) {
1043 error = -EACCES;
986 } 1044 }
987out: 1045out:
988 unlock_kernel();
989 return error; 1046 return error;
990} 1047}
991 1048
@@ -998,11 +1055,6 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
998 DPRINTK("ncp_rmdir: removing %s/%s\n", 1055 DPRINTK("ncp_rmdir: removing %s/%s\n",
999 dentry->d_parent->d_name.name, dentry->d_name.name); 1056 dentry->d_parent->d_name.name, dentry->d_name.name);
1000 1057
1001 error = -EIO;
1002 lock_kernel();
1003 if (!ncp_conn_valid(server))
1004 goto out;
1005
1006 error = -EBUSY; 1058 error = -EBUSY;
1007 if (!d_unhashed(dentry)) 1059 if (!d_unhashed(dentry))
1008 goto out; 1060 goto out;
@@ -1036,11 +1088,10 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
1036 error = -ENOENT; 1088 error = -ENOENT;
1037 break; 1089 break;
1038 default: 1090 default:
1039 error = -EACCES; 1091 error = result < 0 ? result : -EACCES;
1040 break; 1092 break;
1041 } 1093 }
1042out: 1094out:
1043 unlock_kernel();
1044 return error; 1095 return error;
1045} 1096}
1046 1097
@@ -1050,15 +1101,10 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1050 struct ncp_server *server; 1101 struct ncp_server *server;
1051 int error; 1102 int error;
1052 1103
1053 lock_kernel();
1054 server = NCP_SERVER(dir); 1104 server = NCP_SERVER(dir);
1055 DPRINTK("ncp_unlink: unlinking %s/%s\n", 1105 DPRINTK("ncp_unlink: unlinking %s/%s\n",
1056 dentry->d_parent->d_name.name, dentry->d_name.name); 1106 dentry->d_parent->d_name.name, dentry->d_name.name);
1057 1107
1058 error = -EIO;
1059 if (!ncp_conn_valid(server))
1060 goto out;
1061
1062 /* 1108 /*
1063 * Check whether to close the file ... 1109 * Check whether to close the file ...
1064 */ 1110 */
@@ -1097,12 +1143,9 @@ static int ncp_unlink(struct inode *dir, struct dentry *dentry)
1097 error = -ENOENT; 1143 error = -ENOENT;
1098 break; 1144 break;
1099 default: 1145 default:
1100 error = -EACCES; 1146 error = error < 0 ? error : -EACCES;
1101 break; 1147 break;
1102 } 1148 }
1103
1104out:
1105 unlock_kernel();
1106 return error; 1149 return error;
1107} 1150}
1108 1151
@@ -1118,11 +1161,6 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1118 old_dentry->d_parent->d_name.name, old_dentry->d_name.name, 1161 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
1119 new_dentry->d_parent->d_name.name, new_dentry->d_name.name); 1162 new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
1120 1163
1121 error = -EIO;
1122 lock_kernel();
1123 if (!ncp_conn_valid(server))
1124 goto out;
1125
1126 ncp_age_dentry(server, old_dentry); 1164 ncp_age_dentry(server, old_dentry);
1127 ncp_age_dentry(server, new_dentry); 1165 ncp_age_dentry(server, new_dentry);
1128 1166
@@ -1161,11 +1199,10 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
1161 error = -ENOENT; 1199 error = -ENOENT;
1162 break; 1200 break;
1163 default: 1201 default:
1164 error = -EACCES; 1202 error = error < 0 ? error : -EACCES;
1165 break; 1203 break;
1166 } 1204 }
1167out: 1205out:
1168 unlock_kernel();
1169 return error; 1206 return error;
1170} 1207}
1171 1208
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 3639cc5cbdae..6c754f70c529 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -113,9 +113,6 @@ ncp_file_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
113 DPRINTK("ncp_file_read: enter %s/%s\n", 113 DPRINTK("ncp_file_read: enter %s/%s\n",
114 dentry->d_parent->d_name.name, dentry->d_name.name); 114 dentry->d_parent->d_name.name, dentry->d_name.name);
115 115
116 if (!ncp_conn_valid(NCP_SERVER(inode)))
117 return -EIO;
118
119 pos = *ppos; 116 pos = *ppos;
120 117
121 if ((ssize_t) count < 0) { 118 if ((ssize_t) count < 0) {
@@ -192,13 +189,11 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
192 189
193 DPRINTK("ncp_file_write: enter %s/%s\n", 190 DPRINTK("ncp_file_write: enter %s/%s\n",
194 dentry->d_parent->d_name.name, dentry->d_name.name); 191 dentry->d_parent->d_name.name, dentry->d_name.name);
195 if (!ncp_conn_valid(NCP_SERVER(inode)))
196 return -EIO;
197 if ((ssize_t) count < 0) 192 if ((ssize_t) count < 0)
198 return -EINVAL; 193 return -EINVAL;
199 pos = *ppos; 194 pos = *ppos;
200 if (file->f_flags & O_APPEND) { 195 if (file->f_flags & O_APPEND) {
201 pos = inode->i_size; 196 pos = i_size_read(inode);
202 } 197 }
203 198
204 if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) { 199 if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
@@ -264,8 +259,11 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
264 259
265 *ppos = pos; 260 *ppos = pos;
266 261
267 if (pos > inode->i_size) { 262 if (pos > i_size_read(inode)) {
268 inode->i_size = pos; 263 mutex_lock(&inode->i_mutex);
264 if (pos > i_size_read(inode))
265 i_size_write(inode, pos);
266 mutex_unlock(&inode->i_mutex);
269 } 267 }
270 DPRINTK("ncp_file_write: exit %s/%s\n", 268 DPRINTK("ncp_file_write: exit %s/%s\n",
271 dentry->d_parent->d_name.name, dentry->d_name.name); 269 dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -281,18 +279,9 @@ static int ncp_release(struct inode *inode, struct file *file) {
281 return 0; 279 return 0;
282} 280}
283 281
284static loff_t ncp_remote_llseek(struct file *file, loff_t offset, int origin)
285{
286 loff_t ret;
287 lock_kernel();
288 ret = generic_file_llseek_unlocked(file, offset, origin);
289 unlock_kernel();
290 return ret;
291}
292
293const struct file_operations ncp_file_operations = 282const struct file_operations ncp_file_operations =
294{ 283{
295 .llseek = ncp_remote_llseek, 284 .llseek = generic_file_llseek,
296 .read = ncp_file_read, 285 .read = ncp_file_read,
297 .write = ncp_file_write, 286 .write = ncp_file_write,
298 .unlocked_ioctl = ncp_ioctl, 287 .unlocked_ioctl = ncp_ioctl,
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index b4de38cf49f5..5f4e58d93fdd 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -139,7 +139,7 @@ static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi)
139 inode->i_mode = nwi->nfs.mode; 139 inode->i_mode = nwi->nfs.mode;
140 } 140 }
141 141
142 inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; 142 inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
143 143
144 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); 144 inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate);
145 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); 145 inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate);
@@ -158,18 +158,21 @@ static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo)
158 inode->i_mode = server->m.dir_mode; 158 inode->i_mode = server->m.dir_mode;
159 /* for directories dataStreamSize seems to be some 159 /* for directories dataStreamSize seems to be some
160 Object ID ??? */ 160 Object ID ??? */
161 inode->i_size = NCP_BLOCK_SIZE; 161 i_size_write(inode, NCP_BLOCK_SIZE);
162 } else { 162 } else {
163 u32 size;
164
163 inode->i_mode = server->m.file_mode; 165 inode->i_mode = server->m.file_mode;
164 inode->i_size = le32_to_cpu(nwi->dataStreamSize); 166 size = le32_to_cpu(nwi->dataStreamSize);
167 i_size_write(inode, size);
165#ifdef CONFIG_NCPFS_EXTRAS 168#ifdef CONFIG_NCPFS_EXTRAS
166 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) 169 if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
167 && (nwi->attributes & aSHARED)) { 170 && (nwi->attributes & aSHARED)) {
168 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { 171 switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
169 case aHIDDEN: 172 case aHIDDEN:
170 if (server->m.flags & NCP_MOUNT_SYMLINKS) { 173 if (server->m.flags & NCP_MOUNT_SYMLINKS) {
171 if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE) 174 if (/* (size >= NCP_MIN_SYMLINK_SIZE)
172 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) { 175 && */ (size <= NCP_MAX_SYMLINK_SIZE)) {
173 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; 176 inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
174 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; 177 NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK;
175 break; 178 break;
@@ -208,7 +211,7 @@ void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
208} 211}
209 212
210/* 213/*
211 * Fill in the inode based on the ncp_entry_info structure. 214 * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes.
212 */ 215 */
213static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) 216static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
214{ 217{
@@ -254,6 +257,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
254 if (inode) { 257 if (inode) {
255 atomic_set(&NCP_FINFO(inode)->opened, info->opened); 258 atomic_set(&NCP_FINFO(inode)->opened, info->opened);
256 259
260 inode->i_mapping->backing_dev_info = sb->s_bdi;
257 inode->i_ino = info->ino; 261 inode->i_ino = info->ino;
258 ncp_set_attr(inode, info); 262 ncp_set_attr(inode, info);
259 if (S_ISREG(inode->i_mode)) { 263 if (S_ISREG(inode->i_mode)) {
@@ -565,10 +569,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
565/* server->conn_status = 0; */ 569/* server->conn_status = 0; */
566/* server->root_dentry = NULL; */ 570/* server->root_dentry = NULL; */
567/* server->root_setuped = 0; */ 571/* server->root_setuped = 0; */
572 mutex_init(&server->root_setup_lock);
568#ifdef CONFIG_NCPFS_PACKET_SIGNING 573#ifdef CONFIG_NCPFS_PACKET_SIGNING
569/* server->sign_wanted = 0; */ 574/* server->sign_wanted = 0; */
570/* server->sign_active = 0; */ 575/* server->sign_active = 0; */
571#endif 576#endif
577 init_rwsem(&server->auth_rwsem);
572 server->auth.auth_type = NCP_AUTH_NONE; 578 server->auth.auth_type = NCP_AUTH_NONE;
573/* server->auth.object_name_len = 0; */ 579/* server->auth.object_name_len = 0; */
574/* server->auth.object_name = NULL; */ 580/* server->auth.object_name = NULL; */
@@ -593,7 +599,7 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
593 server->nls_io = load_nls_default(); 599 server->nls_io = load_nls_default();
594#endif /* CONFIG_NCPFS_NLS */ 600#endif /* CONFIG_NCPFS_NLS */
595 601
596 server->dentry_ttl = 0; /* no caching */ 602 atomic_set(&server->dentry_ttl, 0); /* no caching */
597 603
598 INIT_LIST_HEAD(&server->tx.requests); 604 INIT_LIST_HEAD(&server->tx.requests);
599 mutex_init(&server->rcv.creq_mutex); 605 mutex_init(&server->rcv.creq_mutex);
@@ -658,8 +664,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
658 goto out_disconnect; 664 goto out_disconnect;
659 } 665 }
660 } 666 }
667 ncp_lock_server(server);
661 if (options & 2) 668 if (options & 2)
662 server->sign_wanted = 1; 669 server->sign_wanted = 1;
670 ncp_unlock_server(server);
663 } 671 }
664 else 672 else
665#endif /* CONFIG_NCPFS_PACKET_SIGNING */ 673#endif /* CONFIG_NCPFS_PACKET_SIGNING */
@@ -720,6 +728,9 @@ out_nls:
720 unload_nls(server->nls_io); 728 unload_nls(server->nls_io);
721 unload_nls(server->nls_vol); 729 unload_nls(server->nls_vol);
722#endif 730#endif
731 mutex_destroy(&server->rcv.creq_mutex);
732 mutex_destroy(&server->root_setup_lock);
733 mutex_destroy(&server->mutex);
723out_fput2: 734out_fput2:
724 if (server->info_filp) 735 if (server->info_filp)
725 fput(server->info_filp); 736 fput(server->info_filp);
@@ -743,8 +754,6 @@ static void ncp_put_super(struct super_block *sb)
743{ 754{
744 struct ncp_server *server = NCP_SBP(sb); 755 struct ncp_server *server = NCP_SBP(sb);
745 756
746 lock_kernel();
747
748 ncp_lock_server(server); 757 ncp_lock_server(server);
749 ncp_disconnect(server); 758 ncp_disconnect(server);
750 ncp_unlock_server(server); 759 ncp_unlock_server(server);
@@ -756,6 +765,9 @@ static void ncp_put_super(struct super_block *sb)
756 unload_nls(server->nls_vol); 765 unload_nls(server->nls_vol);
757 unload_nls(server->nls_io); 766 unload_nls(server->nls_io);
758#endif /* CONFIG_NCPFS_NLS */ 767#endif /* CONFIG_NCPFS_NLS */
768 mutex_destroy(&server->rcv.creq_mutex);
769 mutex_destroy(&server->root_setup_lock);
770 mutex_destroy(&server->mutex);
759 771
760 if (server->info_filp) 772 if (server->info_filp)
761 fput(server->info_filp); 773 fput(server->info_filp);
@@ -771,8 +783,6 @@ static void ncp_put_super(struct super_block *sb)
771 vfree(server->packet); 783 vfree(server->packet);
772 sb->s_fs_info = NULL; 784 sb->s_fs_info = NULL;
773 kfree(server); 785 kfree(server);
774
775 unlock_kernel();
776} 786}
777 787
778static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) 788static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
@@ -851,10 +861,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
851 861
852 result = -EIO; 862 result = -EIO;
853 863
854 lock_kernel();
855
856 server = NCP_SERVER(inode); 864 server = NCP_SERVER(inode);
857 if ((!server) || !ncp_conn_valid(server)) 865 if (!server) /* How this could happen? */
858 goto out; 866 goto out;
859 867
860 /* ageing the dentry to force validation */ 868 /* ageing the dentry to force validation */
@@ -981,8 +989,6 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
981 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode), 989 result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
982 inode, info_mask, &info); 990 inode, info_mask, &info);
983 if (result != 0) { 991 if (result != 0) {
984 result = -EACCES;
985
986 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) { 992 if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
987 /* NetWare seems not to allow this. I 993 /* NetWare seems not to allow this. I
988 do not know why. So, just tell the 994 do not know why. So, just tell the
@@ -1005,7 +1011,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
1005 mark_inode_dirty(inode); 1011 mark_inode_dirty(inode);
1006 1012
1007out: 1013out:
1008 unlock_kernel(); 1014 if (result > 0)
1015 result = -EACCES;
1009 return result; 1016 return result;
1010} 1017}
1011 1018
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 84a8cfc4e38e..c2a1f9a155c3 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -35,16 +35,11 @@
35#define NCP_PACKET_SIZE_INTERNAL 65536 35#define NCP_PACKET_SIZE_INTERNAL 65536
36 36
37static int 37static int
38ncp_get_fs_info(struct ncp_server * server, struct file *file, 38ncp_get_fs_info(struct ncp_server * server, struct inode *inode,
39 struct ncp_fs_info __user *arg) 39 struct ncp_fs_info __user *arg)
40{ 40{
41 struct inode *inode = file->f_path.dentry->d_inode;
42 struct ncp_fs_info info; 41 struct ncp_fs_info info;
43 42
44 if (file_permission(file, MAY_WRITE) != 0
45 && current_uid() != server->m.mounted_uid)
46 return -EACCES;
47
48 if (copy_from_user(&info, arg, sizeof(info))) 43 if (copy_from_user(&info, arg, sizeof(info)))
49 return -EFAULT; 44 return -EFAULT;
50 45
@@ -65,16 +60,11 @@ ncp_get_fs_info(struct ncp_server * server, struct file *file,
65} 60}
66 61
67static int 62static int
68ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, 63ncp_get_fs_info_v2(struct ncp_server * server, struct inode *inode,
69 struct ncp_fs_info_v2 __user * arg) 64 struct ncp_fs_info_v2 __user * arg)
70{ 65{
71 struct inode *inode = file->f_path.dentry->d_inode;
72 struct ncp_fs_info_v2 info2; 66 struct ncp_fs_info_v2 info2;
73 67
74 if (file_permission(file, MAY_WRITE) != 0
75 && current_uid() != server->m.mounted_uid)
76 return -EACCES;
77
78 if (copy_from_user(&info2, arg, sizeof(info2))) 68 if (copy_from_user(&info2, arg, sizeof(info2)))
79 return -EFAULT; 69 return -EFAULT;
80 70
@@ -136,16 +126,11 @@ struct compat_ncp_privatedata_ioctl
136#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl) 126#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct compat_ncp_privatedata_ioctl)
137 127
138static int 128static int
139ncp_get_compat_fs_info_v2(struct ncp_server * server, struct file *file, 129ncp_get_compat_fs_info_v2(struct ncp_server * server, struct inode *inode,
140 struct compat_ncp_fs_info_v2 __user * arg) 130 struct compat_ncp_fs_info_v2 __user * arg)
141{ 131{
142 struct inode *inode = file->f_path.dentry->d_inode;
143 struct compat_ncp_fs_info_v2 info2; 132 struct compat_ncp_fs_info_v2 info2;
144 133
145 if (file_permission(file, MAY_WRITE) != 0
146 && current_uid() != server->m.mounted_uid)
147 return -EACCES;
148
149 if (copy_from_user(&info2, arg, sizeof(info2))) 134 if (copy_from_user(&info2, arg, sizeof(info2)))
150 return -EFAULT; 135 return -EFAULT;
151 136
@@ -182,11 +167,8 @@ ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
182 struct nls_table *iocharset; 167 struct nls_table *iocharset;
183 struct nls_table *oldset_io; 168 struct nls_table *oldset_io;
184 struct nls_table *oldset_cp; 169 struct nls_table *oldset_cp;
185 170 int utf8;
186 if (!capable(CAP_SYS_ADMIN)) 171 int err;
187 return -EACCES;
188 if (server->root_setuped)
189 return -EBUSY;
190 172
191 if (copy_from_user(&user, arg, sizeof(user))) 173 if (copy_from_user(&user, arg, sizeof(user)))
192 return -EFAULT; 174 return -EFAULT;
@@ -206,28 +188,40 @@ ncp_set_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
206 user.iocharset[NCP_IOCSNAME_LEN] = 0; 188 user.iocharset[NCP_IOCSNAME_LEN] = 0;
207 if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) { 189 if (!user.iocharset[0] || !strcmp(user.iocharset, "default")) {
208 iocharset = load_nls_default(); 190 iocharset = load_nls_default();
209 NCP_CLR_FLAG(server, NCP_FLAG_UTF8); 191 utf8 = 0;
210 } else if (!strcmp(user.iocharset, "utf8")) { 192 } else if (!strcmp(user.iocharset, "utf8")) {
211 iocharset = load_nls_default(); 193 iocharset = load_nls_default();
212 NCP_SET_FLAG(server, NCP_FLAG_UTF8); 194 utf8 = 1;
213 } else { 195 } else {
214 iocharset = load_nls(user.iocharset); 196 iocharset = load_nls(user.iocharset);
215 if (!iocharset) { 197 if (!iocharset) {
216 unload_nls(codepage); 198 unload_nls(codepage);
217 return -EBADRQC; 199 return -EBADRQC;
218 } 200 }
219 NCP_CLR_FLAG(server, NCP_FLAG_UTF8); 201 utf8 = 0;
220 } 202 }
221 203
222 oldset_cp = server->nls_vol; 204 mutex_lock(&server->root_setup_lock);
223 server->nls_vol = codepage; 205 if (server->root_setuped) {
224 oldset_io = server->nls_io; 206 oldset_cp = codepage;
225 server->nls_io = iocharset; 207 oldset_io = iocharset;
226 208 err = -EBUSY;
209 } else {
210 if (utf8)
211 NCP_SET_FLAG(server, NCP_FLAG_UTF8);
212 else
213 NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
214 oldset_cp = server->nls_vol;
215 server->nls_vol = codepage;
216 oldset_io = server->nls_io;
217 server->nls_io = iocharset;
218 err = 0;
219 }
220 mutex_unlock(&server->root_setup_lock);
227 unload_nls(oldset_cp); 221 unload_nls(oldset_cp);
228 unload_nls(oldset_io); 222 unload_nls(oldset_io);
229 223
230 return 0; 224 return err;
231} 225}
232 226
233static int 227static int
@@ -237,6 +231,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
237 int len; 231 int len;
238 232
239 memset(&user, 0, sizeof(user)); 233 memset(&user, 0, sizeof(user));
234 mutex_lock(&server->root_setup_lock);
240 if (server->nls_vol && server->nls_vol->charset) { 235 if (server->nls_vol && server->nls_vol->charset) {
241 len = strlen(server->nls_vol->charset); 236 len = strlen(server->nls_vol->charset);
242 if (len > NCP_IOCSNAME_LEN) 237 if (len > NCP_IOCSNAME_LEN)
@@ -254,6 +249,7 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
254 strncpy(user.iocharset, server->nls_io->charset, len); 249 strncpy(user.iocharset, server->nls_io->charset, len);
255 user.iocharset[len] = 0; 250 user.iocharset[len] = 0;
256 } 251 }
252 mutex_unlock(&server->root_setup_lock);
257 253
258 if (copy_to_user(arg, &user, sizeof(user))) 254 if (copy_to_user(arg, &user, sizeof(user)))
259 return -EFAULT; 255 return -EFAULT;
@@ -261,25 +257,19 @@ ncp_get_charsets(struct ncp_server* server, struct ncp_nls_ioctl __user *arg)
261} 257}
262#endif /* CONFIG_NCPFS_NLS */ 258#endif /* CONFIG_NCPFS_NLS */
263 259
264static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 260static long __ncp_ioctl(struct inode *inode, unsigned int cmd, unsigned long arg)
265{ 261{
266 struct inode *inode = filp->f_dentry->d_inode;
267 struct ncp_server *server = NCP_SERVER(inode); 262 struct ncp_server *server = NCP_SERVER(inode);
268 int result; 263 int result;
269 struct ncp_ioctl_request request; 264 struct ncp_ioctl_request request;
270 char* bouncebuffer; 265 char* bouncebuffer;
271 void __user *argp = (void __user *)arg; 266 void __user *argp = (void __user *)arg;
272 uid_t uid = current_uid();
273 267
274 switch (cmd) { 268 switch (cmd) {
275#ifdef CONFIG_COMPAT 269#ifdef CONFIG_COMPAT
276 case NCP_IOC_NCPREQUEST_32: 270 case NCP_IOC_NCPREQUEST_32:
277#endif 271#endif
278 case NCP_IOC_NCPREQUEST: 272 case NCP_IOC_NCPREQUEST:
279 if (file_permission(filp, MAY_WRITE) != 0
280 && uid != server->m.mounted_uid)
281 return -EACCES;
282
283#ifdef CONFIG_COMPAT 273#ifdef CONFIG_COMPAT
284 if (cmd == NCP_IOC_NCPREQUEST_32) { 274 if (cmd == NCP_IOC_NCPREQUEST_32) {
285 struct compat_ncp_ioctl_request request32; 275 struct compat_ncp_ioctl_request request32;
@@ -314,7 +304,7 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
314 server->current_size = request.size; 304 server->current_size = request.size;
315 memcpy(server->packet, bouncebuffer, request.size); 305 memcpy(server->packet, bouncebuffer, request.size);
316 306
317 result = ncp_request2(server, request.function, 307 result = ncp_request2(server, request.function,
318 bouncebuffer, NCP_PACKET_SIZE_INTERNAL); 308 bouncebuffer, NCP_PACKET_SIZE_INTERNAL);
319 if (result < 0) 309 if (result < 0)
320 result = -EIO; 310 result = -EIO;
@@ -331,69 +321,69 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
331 321
332 case NCP_IOC_CONN_LOGGED_IN: 322 case NCP_IOC_CONN_LOGGED_IN:
333 323
334 if (!capable(CAP_SYS_ADMIN))
335 return -EACCES;
336 if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE)) 324 if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
337 return -EINVAL; 325 return -EINVAL;
326 mutex_lock(&server->root_setup_lock);
338 if (server->root_setuped) 327 if (server->root_setuped)
339 return -EBUSY; 328 result = -EBUSY;
340 server->root_setuped = 1; 329 else {
341 return ncp_conn_logged_in(inode->i_sb); 330 result = ncp_conn_logged_in(inode->i_sb);
331 if (result == 0)
332 server->root_setuped = 1;
333 }
334 mutex_unlock(&server->root_setup_lock);
335 return result;
342 336
343 case NCP_IOC_GET_FS_INFO: 337 case NCP_IOC_GET_FS_INFO:
344 return ncp_get_fs_info(server, filp, argp); 338 return ncp_get_fs_info(server, inode, argp);
345 339
346 case NCP_IOC_GET_FS_INFO_V2: 340 case NCP_IOC_GET_FS_INFO_V2:
347 return ncp_get_fs_info_v2(server, filp, argp); 341 return ncp_get_fs_info_v2(server, inode, argp);
348 342
349#ifdef CONFIG_COMPAT 343#ifdef CONFIG_COMPAT
350 case NCP_IOC_GET_FS_INFO_V2_32: 344 case NCP_IOC_GET_FS_INFO_V2_32:
351 return ncp_get_compat_fs_info_v2(server, filp, argp); 345 return ncp_get_compat_fs_info_v2(server, inode, argp);
352#endif 346#endif
353 /* we have too many combinations of CONFIG_COMPAT, 347 /* we have too many combinations of CONFIG_COMPAT,
354 * CONFIG_64BIT and CONFIG_UID16, so just handle 348 * CONFIG_64BIT and CONFIG_UID16, so just handle
355 * any of the possible ioctls */ 349 * any of the possible ioctls */
356 case NCP_IOC_GETMOUNTUID16: 350 case NCP_IOC_GETMOUNTUID16:
357 case NCP_IOC_GETMOUNTUID32: 351 {
358 case NCP_IOC_GETMOUNTUID64:
359 if (file_permission(filp, MAY_READ) != 0
360 && uid != server->m.mounted_uid)
361 return -EACCES;
362
363 if (cmd == NCP_IOC_GETMOUNTUID16) {
364 u16 uid; 352 u16 uid;
353
365 SET_UID(uid, server->m.mounted_uid); 354 SET_UID(uid, server->m.mounted_uid);
366 if (put_user(uid, (u16 __user *)argp)) 355 if (put_user(uid, (u16 __user *)argp))
367 return -EFAULT; 356 return -EFAULT;
368 } else if (cmd == NCP_IOC_GETMOUNTUID32) { 357 return 0;
369 if (put_user(server->m.mounted_uid,
370 (u32 __user *)argp))
371 return -EFAULT;
372 } else {
373 if (put_user(server->m.mounted_uid,
374 (u64 __user *)argp))
375 return -EFAULT;
376 } 358 }
359 case NCP_IOC_GETMOUNTUID32:
360 if (put_user(server->m.mounted_uid,
361 (u32 __user *)argp))
362 return -EFAULT;
363 return 0;
364 case NCP_IOC_GETMOUNTUID64:
365 if (put_user(server->m.mounted_uid,
366 (u64 __user *)argp))
367 return -EFAULT;
377 return 0; 368 return 0;
378 369
379 case NCP_IOC_GETROOT: 370 case NCP_IOC_GETROOT:
380 { 371 {
381 struct ncp_setroot_ioctl sr; 372 struct ncp_setroot_ioctl sr;
382 373
383 if (file_permission(filp, MAY_READ) != 0 374 result = -EACCES;
384 && uid != server->m.mounted_uid) 375 mutex_lock(&server->root_setup_lock);
385 return -EACCES;
386
387 if (server->m.mounted_vol[0]) { 376 if (server->m.mounted_vol[0]) {
388 struct dentry* dentry = inode->i_sb->s_root; 377 struct dentry* dentry = inode->i_sb->s_root;
389 378
390 if (dentry) { 379 if (dentry) {
391 struct inode* s_inode = dentry->d_inode; 380 struct inode* s_inode = dentry->d_inode;
392 381
393 if (s_inode) { 382 if (s_inode) {
394 sr.volNumber = NCP_FINFO(s_inode)->volNumber; 383 sr.volNumber = NCP_FINFO(s_inode)->volNumber;
395 sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; 384 sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum;
396 sr.namespace = server->name_space[sr.volNumber]; 385 sr.namespace = server->name_space[sr.volNumber];
386 result = 0;
397 } else 387 } else
398 DPRINTK("ncpfs: s_root->d_inode==NULL\n"); 388 DPRINTK("ncpfs: s_root->d_inode==NULL\n");
399 } else 389 } else
@@ -402,10 +392,12 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
402 sr.volNumber = -1; 392 sr.volNumber = -1;
403 sr.namespace = 0; 393 sr.namespace = 0;
404 sr.dirEntNum = 0; 394 sr.dirEntNum = 0;
395 result = 0;
405 } 396 }
406 if (copy_to_user(argp, &sr, sizeof(sr))) 397 mutex_unlock(&server->root_setup_lock);
407 return -EFAULT; 398 if (!result && copy_to_user(argp, &sr, sizeof(sr)))
408 return 0; 399 result = -EFAULT;
400 return result;
409 } 401 }
410 402
411 case NCP_IOC_SETROOT: 403 case NCP_IOC_SETROOT:
@@ -416,103 +408,114 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
416 __le32 dosde; 408 __le32 dosde;
417 struct dentry* dentry; 409 struct dentry* dentry;
418 410
419 if (!capable(CAP_SYS_ADMIN))
420 {
421 return -EACCES;
422 }
423 if (server->root_setuped) return -EBUSY;
424 if (copy_from_user(&sr, argp, sizeof(sr))) 411 if (copy_from_user(&sr, argp, sizeof(sr)))
425 return -EFAULT; 412 return -EFAULT;
426 if (sr.volNumber < 0) { 413 mutex_lock(&server->root_setup_lock);
427 server->m.mounted_vol[0] = 0; 414 if (server->root_setuped)
428 vnum = NCP_NUMBER_OF_VOLUMES; 415 result = -EBUSY;
429 de = 0; 416 else {
430 dosde = 0; 417 if (sr.volNumber < 0) {
431 } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) { 418 server->m.mounted_vol[0] = 0;
432 return -EINVAL; 419 vnum = NCP_NUMBER_OF_VOLUMES;
433 } else if (ncp_mount_subdir(server, sr.volNumber, 420 de = 0;
434 sr.namespace, sr.dirEntNum, 421 dosde = 0;
435 &vnum, &de, &dosde)) { 422 result = 0;
436 return -ENOENT; 423 } else if (sr.volNumber >= NCP_NUMBER_OF_VOLUMES) {
437 } 424 result = -EINVAL;
438 425 } else if (ncp_mount_subdir(server, sr.volNumber,
439 dentry = inode->i_sb->s_root; 426 sr.namespace, sr.dirEntNum,
440 server->root_setuped = 1; 427 &vnum, &de, &dosde)) {
441 if (dentry) { 428 result = -ENOENT;
442 struct inode* s_inode = dentry->d_inode;
443
444 if (s_inode) {
445 NCP_FINFO(s_inode)->volNumber = vnum;
446 NCP_FINFO(s_inode)->dirEntNum = de;
447 NCP_FINFO(s_inode)->DosDirNum = dosde;
448 } else 429 } else
449 DPRINTK("ncpfs: s_root->d_inode==NULL\n"); 430 result = 0;
450 } else 431
451 DPRINTK("ncpfs: s_root==NULL\n"); 432 if (result == 0) {
433 dentry = inode->i_sb->s_root;
434 if (dentry) {
435 struct inode* s_inode = dentry->d_inode;
436
437 if (s_inode) {
438 NCP_FINFO(s_inode)->volNumber = vnum;
439 NCP_FINFO(s_inode)->dirEntNum = de;
440 NCP_FINFO(s_inode)->DosDirNum = dosde;
441 server->root_setuped = 1;
442 } else {
443 DPRINTK("ncpfs: s_root->d_inode==NULL\n");
444 result = -EIO;
445 }
446 } else {
447 DPRINTK("ncpfs: s_root==NULL\n");
448 result = -EIO;
449 }
450 }
451 result = 0;
452 }
453 mutex_unlock(&server->root_setup_lock);
452 454
453 return 0; 455 return result;
454 } 456 }
455 457
456#ifdef CONFIG_NCPFS_PACKET_SIGNING 458#ifdef CONFIG_NCPFS_PACKET_SIGNING
457 case NCP_IOC_SIGN_INIT: 459 case NCP_IOC_SIGN_INIT:
458 if (file_permission(filp, MAY_WRITE) != 0 460 {
459 && uid != server->m.mounted_uid) 461 struct ncp_sign_init sign;
460 return -EACCES;
461
462 if (argp) {
463 if (server->sign_wanted)
464 {
465 struct ncp_sign_init sign;
466 462
463 if (argp)
467 if (copy_from_user(&sign, argp, sizeof(sign))) 464 if (copy_from_user(&sign, argp, sizeof(sign)))
468 return -EFAULT; 465 return -EFAULT;
469 memcpy(server->sign_root,sign.sign_root,8); 466 ncp_lock_server(server);
470 memcpy(server->sign_last,sign.sign_last,16); 467 mutex_lock(&server->rcv.creq_mutex);
471 server->sign_active = 1; 468 if (argp) {
469 if (server->sign_wanted) {
470 memcpy(server->sign_root,sign.sign_root,8);
471 memcpy(server->sign_last,sign.sign_last,16);
472 server->sign_active = 1;
473 }
474 /* ignore when signatures not wanted */
475 } else {
476 server->sign_active = 0;
472 } 477 }
473 /* ignore when signatures not wanted */ 478 mutex_unlock(&server->rcv.creq_mutex);
474 } else { 479 ncp_unlock_server(server);
475 server->sign_active = 0; 480 return 0;
476 } 481 }
477 return 0; 482
478
479 case NCP_IOC_SIGN_WANTED: 483 case NCP_IOC_SIGN_WANTED:
480 if (file_permission(filp, MAY_READ) != 0 484 {
481 && uid != server->m.mounted_uid) 485 int state;
482 return -EACCES; 486
483 487 ncp_lock_server(server);
484 if (put_user(server->sign_wanted, (int __user *)argp)) 488 state = server->sign_wanted;
485 return -EFAULT; 489 ncp_unlock_server(server);
486 return 0; 490 if (put_user(state, (int __user *)argp))
491 return -EFAULT;
492 return 0;
493 }
487 494
488 case NCP_IOC_SET_SIGN_WANTED: 495 case NCP_IOC_SET_SIGN_WANTED:
489 { 496 {
490 int newstate; 497 int newstate;
491 498
492 if (file_permission(filp, MAY_WRITE) != 0
493 && uid != server->m.mounted_uid)
494 return -EACCES;
495
496 /* get only low 8 bits... */ 499 /* get only low 8 bits... */
497 if (get_user(newstate, (unsigned char __user *)argp)) 500 if (get_user(newstate, (unsigned char __user *)argp))
498 return -EFAULT; 501 return -EFAULT;
502 result = 0;
503 ncp_lock_server(server);
499 if (server->sign_active) { 504 if (server->sign_active) {
500 /* cannot turn signatures OFF when active */ 505 /* cannot turn signatures OFF when active */
501 if (!newstate) return -EINVAL; 506 if (!newstate)
507 result = -EINVAL;
502 } else { 508 } else {
503 server->sign_wanted = newstate != 0; 509 server->sign_wanted = newstate != 0;
504 } 510 }
505 return 0; 511 ncp_unlock_server(server);
512 return result;
506 } 513 }
507 514
508#endif /* CONFIG_NCPFS_PACKET_SIGNING */ 515#endif /* CONFIG_NCPFS_PACKET_SIGNING */
509 516
510#ifdef CONFIG_NCPFS_IOCTL_LOCKING 517#ifdef CONFIG_NCPFS_IOCTL_LOCKING
511 case NCP_IOC_LOCKUNLOCK: 518 case NCP_IOC_LOCKUNLOCK:
512 if (file_permission(filp, MAY_WRITE) != 0
513 && uid != server->m.mounted_uid)
514 return -EACCES;
515
516 { 519 {
517 struct ncp_lock_ioctl rqdata; 520 struct ncp_lock_ioctl rqdata;
518 521
@@ -541,16 +544,13 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
541 { 544 {
542 return result; 545 return result;
543 } 546 }
544 result = -EIO;
545 if (!ncp_conn_valid(server))
546 goto outrel;
547 result = -EISDIR; 547 result = -EISDIR;
548 if (!S_ISREG(inode->i_mode)) 548 if (!S_ISREG(inode->i_mode))
549 goto outrel; 549 goto outrel;
550 if (rqdata.cmd == NCP_LOCK_CLEAR) 550 if (rqdata.cmd == NCP_LOCK_CLEAR)
551 { 551 {
552 result = ncp_ClearPhysicalRecord(NCP_SERVER(inode), 552 result = ncp_ClearPhysicalRecord(NCP_SERVER(inode),
553 NCP_FINFO(inode)->file_handle, 553 NCP_FINFO(inode)->file_handle,
554 rqdata.offset, 554 rqdata.offset,
555 rqdata.length); 555 rqdata.length);
556 if (result > 0) result = 0; /* no such lock */ 556 if (result > 0) result = 0; /* no such lock */
@@ -573,7 +573,7 @@ static long __ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
573 rqdata.timeout); 573 rqdata.timeout);
574 if (result > 0) result = -EAGAIN; 574 if (result > 0) result = -EAGAIN;
575 } 575 }
576outrel: 576outrel:
577 ncp_inode_close(inode); 577 ncp_inode_close(inode);
578 return result; 578 return result;
579 } 579 }
@@ -581,60 +581,62 @@ outrel:
581 581
582#ifdef CONFIG_COMPAT 582#ifdef CONFIG_COMPAT
583 case NCP_IOC_GETOBJECTNAME_32: 583 case NCP_IOC_GETOBJECTNAME_32:
584 if (uid != server->m.mounted_uid)
585 return -EACCES;
586 { 584 {
587 struct compat_ncp_objectname_ioctl user; 585 struct compat_ncp_objectname_ioctl user;
588 size_t outl; 586 size_t outl;
589 587
590 if (copy_from_user(&user, argp, sizeof(user))) 588 if (copy_from_user(&user, argp, sizeof(user)))
591 return -EFAULT; 589 return -EFAULT;
590 down_read(&server->auth_rwsem);
592 user.auth_type = server->auth.auth_type; 591 user.auth_type = server->auth.auth_type;
593 outl = user.object_name_len; 592 outl = user.object_name_len;
594 user.object_name_len = server->auth.object_name_len; 593 user.object_name_len = server->auth.object_name_len;
595 if (outl > user.object_name_len) 594 if (outl > user.object_name_len)
596 outl = user.object_name_len; 595 outl = user.object_name_len;
596 result = 0;
597 if (outl) { 597 if (outl) {
598 if (copy_to_user(compat_ptr(user.object_name), 598 if (copy_to_user(compat_ptr(user.object_name),
599 server->auth.object_name, 599 server->auth.object_name,
600 outl)) return -EFAULT; 600 outl))
601 result = -EFAULT;
601 } 602 }
602 if (copy_to_user(argp, &user, sizeof(user))) 603 up_read(&server->auth_rwsem);
603 return -EFAULT; 604 if (!result && copy_to_user(argp, &user, sizeof(user)))
604 return 0; 605 result = -EFAULT;
606 return result;
605 } 607 }
606#endif 608#endif
607 609
608 case NCP_IOC_GETOBJECTNAME: 610 case NCP_IOC_GETOBJECTNAME:
609 if (uid != server->m.mounted_uid)
610 return -EACCES;
611 { 611 {
612 struct ncp_objectname_ioctl user; 612 struct ncp_objectname_ioctl user;
613 size_t outl; 613 size_t outl;
614 614
615 if (copy_from_user(&user, argp, sizeof(user))) 615 if (copy_from_user(&user, argp, sizeof(user)))
616 return -EFAULT; 616 return -EFAULT;
617 down_read(&server->auth_rwsem);
617 user.auth_type = server->auth.auth_type; 618 user.auth_type = server->auth.auth_type;
618 outl = user.object_name_len; 619 outl = user.object_name_len;
619 user.object_name_len = server->auth.object_name_len; 620 user.object_name_len = server->auth.object_name_len;
620 if (outl > user.object_name_len) 621 if (outl > user.object_name_len)
621 outl = user.object_name_len; 622 outl = user.object_name_len;
623 result = 0;
622 if (outl) { 624 if (outl) {
623 if (copy_to_user(user.object_name, 625 if (copy_to_user(user.object_name,
624 server->auth.object_name, 626 server->auth.object_name,
625 outl)) return -EFAULT; 627 outl))
628 result = -EFAULT;
626 } 629 }
627 if (copy_to_user(argp, &user, sizeof(user))) 630 up_read(&server->auth_rwsem);
628 return -EFAULT; 631 if (!result && copy_to_user(argp, &user, sizeof(user)))
629 return 0; 632 result = -EFAULT;
633 return result;
630 } 634 }
631 635
632#ifdef CONFIG_COMPAT 636#ifdef CONFIG_COMPAT
633 case NCP_IOC_SETOBJECTNAME_32: 637 case NCP_IOC_SETOBJECTNAME_32:
634#endif 638#endif
635 case NCP_IOC_SETOBJECTNAME: 639 case NCP_IOC_SETOBJECTNAME:
636 if (uid != server->m.mounted_uid)
637 return -EACCES;
638 { 640 {
639 struct ncp_objectname_ioctl user; 641 struct ncp_objectname_ioctl user;
640 void* newname; 642 void* newname;
@@ -666,9 +668,7 @@ outrel:
666 } else { 668 } else {
667 newname = NULL; 669 newname = NULL;
668 } 670 }
669 /* enter critical section */ 671 down_write(&server->auth_rwsem);
670 /* maybe that kfree can sleep so do that this way */
671 /* it is at least more SMP friendly (in future...) */
672 oldname = server->auth.object_name; 672 oldname = server->auth.object_name;
673 oldnamelen = server->auth.object_name_len; 673 oldnamelen = server->auth.object_name_len;
674 oldprivate = server->priv.data; 674 oldprivate = server->priv.data;
@@ -678,7 +678,7 @@ outrel:
678 server->auth.object_name = newname; 678 server->auth.object_name = newname;
679 server->priv.len = 0; 679 server->priv.len = 0;
680 server->priv.data = NULL; 680 server->priv.data = NULL;
681 /* leave critical section */ 681 up_write(&server->auth_rwsem);
682 kfree(oldprivate); 682 kfree(oldprivate);
683 kfree(oldname); 683 kfree(oldname);
684 return 0; 684 return 0;
@@ -688,8 +688,6 @@ outrel:
688 case NCP_IOC_GETPRIVATEDATA_32: 688 case NCP_IOC_GETPRIVATEDATA_32:
689#endif 689#endif
690 case NCP_IOC_GETPRIVATEDATA: 690 case NCP_IOC_GETPRIVATEDATA:
691 if (uid != server->m.mounted_uid)
692 return -EACCES;
693 { 691 {
694 struct ncp_privatedata_ioctl user; 692 struct ncp_privatedata_ioctl user;
695 size_t outl; 693 size_t outl;
@@ -706,14 +704,20 @@ outrel:
706 if (copy_from_user(&user, argp, sizeof(user))) 704 if (copy_from_user(&user, argp, sizeof(user)))
707 return -EFAULT; 705 return -EFAULT;
708 706
707 down_read(&server->auth_rwsem);
709 outl = user.len; 708 outl = user.len;
710 user.len = server->priv.len; 709 user.len = server->priv.len;
711 if (outl > user.len) outl = user.len; 710 if (outl > user.len) outl = user.len;
711 result = 0;
712 if (outl) { 712 if (outl) {
713 if (copy_to_user(user.data, 713 if (copy_to_user(user.data,
714 server->priv.data, 714 server->priv.data,
715 outl)) return -EFAULT; 715 outl))
716 result = -EFAULT;
716 } 717 }
718 up_read(&server->auth_rwsem);
719 if (result)
720 return result;
717#ifdef CONFIG_COMPAT 721#ifdef CONFIG_COMPAT
718 if (cmd == NCP_IOC_GETPRIVATEDATA_32) { 722 if (cmd == NCP_IOC_GETPRIVATEDATA_32) {
719 struct compat_ncp_privatedata_ioctl user32; 723 struct compat_ncp_privatedata_ioctl user32;
@@ -733,8 +737,6 @@ outrel:
733 case NCP_IOC_SETPRIVATEDATA_32: 737 case NCP_IOC_SETPRIVATEDATA_32:
734#endif 738#endif
735 case NCP_IOC_SETPRIVATEDATA: 739 case NCP_IOC_SETPRIVATEDATA:
736 if (uid != server->m.mounted_uid)
737 return -EACCES;
738 { 740 {
739 struct ncp_privatedata_ioctl user; 741 struct ncp_privatedata_ioctl user;
740 void* new; 742 void* new;
@@ -762,12 +764,12 @@ outrel:
762 } else { 764 } else {
763 new = NULL; 765 new = NULL;
764 } 766 }
765 /* enter critical section */ 767 down_write(&server->auth_rwsem);
766 old = server->priv.data; 768 old = server->priv.data;
767 oldlen = server->priv.len; 769 oldlen = server->priv.len;
768 server->priv.len = user.len; 770 server->priv.len = user.len;
769 server->priv.data = new; 771 server->priv.data = new;
770 /* leave critical section */ 772 up_write(&server->auth_rwsem);
771 kfree(old); 773 kfree(old);
772 return 0; 774 return 0;
773 } 775 }
@@ -775,17 +777,13 @@ outrel:
775#ifdef CONFIG_NCPFS_NLS 777#ifdef CONFIG_NCPFS_NLS
776 case NCP_IOC_SETCHARSETS: 778 case NCP_IOC_SETCHARSETS:
777 return ncp_set_charsets(server, argp); 779 return ncp_set_charsets(server, argp);
778 780
779 case NCP_IOC_GETCHARSETS: 781 case NCP_IOC_GETCHARSETS:
780 return ncp_get_charsets(server, argp); 782 return ncp_get_charsets(server, argp);
781 783
782#endif /* CONFIG_NCPFS_NLS */ 784#endif /* CONFIG_NCPFS_NLS */
783 785
784 case NCP_IOC_SETDENTRYTTL: 786 case NCP_IOC_SETDENTRYTTL:
785 if (file_permission(filp, MAY_WRITE) != 0 &&
786 uid != server->m.mounted_uid)
787 return -EACCES;
788
789 { 787 {
790 u_int32_t user; 788 u_int32_t user;
791 789
@@ -795,13 +793,13 @@ outrel:
795 if (user > 20000) 793 if (user > 20000)
796 return -EINVAL; 794 return -EINVAL;
797 user = (user * HZ) / 1000; 795 user = (user * HZ) / 1000;
798 server->dentry_ttl = user; 796 atomic_set(&server->dentry_ttl, user);
799 return 0; 797 return 0;
800 } 798 }
801 799
802 case NCP_IOC_GETDENTRYTTL: 800 case NCP_IOC_GETDENTRYTTL:
803 { 801 {
804 u_int32_t user = (server->dentry_ttl * 1000) / HZ; 802 u_int32_t user = (atomic_read(&server->dentry_ttl) * 1000) / HZ;
805 if (copy_to_user(argp, &user, sizeof(user))) 803 if (copy_to_user(argp, &user, sizeof(user)))
806 return -EFAULT; 804 return -EFAULT;
807 return 0; 805 return 0;
@@ -811,59 +809,103 @@ outrel:
811 return -EINVAL; 809 return -EINVAL;
812} 810}
813 811
814static int ncp_ioctl_need_write(unsigned int cmd) 812long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
815{ 813{
814 struct inode *inode = filp->f_dentry->d_inode;
815 struct ncp_server *server = NCP_SERVER(inode);
816 uid_t uid = current_uid();
817 int need_drop_write = 0;
818 long ret;
819
816 switch (cmd) { 820 switch (cmd) {
817 case NCP_IOC_GET_FS_INFO:
818 case NCP_IOC_GET_FS_INFO_V2:
819 case NCP_IOC_NCPREQUEST:
820 case NCP_IOC_SETDENTRYTTL:
821 case NCP_IOC_SIGN_INIT:
822 case NCP_IOC_LOCKUNLOCK:
823 case NCP_IOC_SET_SIGN_WANTED:
824 return 1;
825 case NCP_IOC_GETOBJECTNAME:
826 case NCP_IOC_SETOBJECTNAME:
827 case NCP_IOC_GETPRIVATEDATA:
828 case NCP_IOC_SETPRIVATEDATA:
829 case NCP_IOC_SETCHARSETS: 821 case NCP_IOC_SETCHARSETS:
830 case NCP_IOC_GETCHARSETS:
831 case NCP_IOC_CONN_LOGGED_IN: 822 case NCP_IOC_CONN_LOGGED_IN:
832 case NCP_IOC_GETDENTRYTTL:
833 case NCP_IOC_GETMOUNTUID2:
834 case NCP_IOC_SIGN_WANTED:
835 case NCP_IOC_GETROOT:
836 case NCP_IOC_SETROOT: 823 case NCP_IOC_SETROOT:
837 return 0; 824 if (!capable(CAP_SYS_ADMIN)) {
838 default: 825 ret = -EACCES;
839 /* unknown IOCTL command, assume write */ 826 goto out;
840 return 1; 827 }
828 break;
841 } 829 }
842} 830 if (server->m.mounted_uid != uid) {
843 831 switch (cmd) {
844long ncp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
845{
846 long ret;
847
848 lock_kernel();
849 if (ncp_ioctl_need_write(cmd)) {
850 /* 832 /*
851 * inside the ioctl(), any failures which 833 * Only mount owner can issue these ioctls. Information
852 * are because of file_permission() are 834 * necessary to authenticate to other NDS servers are
853 * -EACCESS, so it seems consistent to keep 835 * stored here.
854 * that here.
855 */ 836 */
856 if (mnt_want_write(filp->f_path.mnt)) { 837 case NCP_IOC_GETOBJECTNAME:
838 case NCP_IOC_SETOBJECTNAME:
839 case NCP_IOC_GETPRIVATEDATA:
840 case NCP_IOC_SETPRIVATEDATA:
841#ifdef CONFIG_COMPAT
842 case NCP_IOC_GETOBJECTNAME_32:
843 case NCP_IOC_SETOBJECTNAME_32:
844 case NCP_IOC_GETPRIVATEDATA_32:
845 case NCP_IOC_SETPRIVATEDATA_32:
846#endif
857 ret = -EACCES; 847 ret = -EACCES;
858 goto out; 848 goto out;
849 /*
850 * These require write access on the inode if user id
851 * does not match. Note that they do not write to the
852 * file... But old code did mnt_want_write, so I keep
853 * it as is. Of course not for mountpoint owner, as
854 * that breaks read-only mounts altogether as ncpmount
855 * needs working NCP_IOC_NCPREQUEST and
856 * NCP_IOC_GET_FS_INFO. Some of these codes (setdentryttl,
857 * signinit, setsignwanted) should be probably restricted
858 * to owner only, or even more to CAP_SYS_ADMIN).
859 */
860 case NCP_IOC_GET_FS_INFO:
861 case NCP_IOC_GET_FS_INFO_V2:
862 case NCP_IOC_NCPREQUEST:
863 case NCP_IOC_SETDENTRYTTL:
864 case NCP_IOC_SIGN_INIT:
865 case NCP_IOC_LOCKUNLOCK:
866 case NCP_IOC_SET_SIGN_WANTED:
867#ifdef CONFIG_COMPAT
868 case NCP_IOC_GET_FS_INFO_V2_32:
869 case NCP_IOC_NCPREQUEST_32:
870#endif
871 ret = mnt_want_write_file(filp);
872 if (ret)
873 goto out;
874 need_drop_write = 1;
875 ret = inode_permission(inode, MAY_WRITE);
876 if (ret)
877 goto outDropWrite;
878 break;
879 /*
880 * Read access required.
881 */
882 case NCP_IOC_GETMOUNTUID16:
883 case NCP_IOC_GETMOUNTUID32:
884 case NCP_IOC_GETMOUNTUID64:
885 case NCP_IOC_GETROOT:
886 case NCP_IOC_SIGN_WANTED:
887 ret = inode_permission(inode, MAY_READ);
888 if (ret)
889 goto out;
890 break;
891 /*
892 * Anybody can read these.
893 */
894 case NCP_IOC_GETCHARSETS:
895 case NCP_IOC_GETDENTRYTTL:
896 default:
897 /* Three codes below are protected by CAP_SYS_ADMIN above. */
898 case NCP_IOC_SETCHARSETS:
899 case NCP_IOC_CONN_LOGGED_IN:
900 case NCP_IOC_SETROOT:
901 break;
859 } 902 }
860 } 903 }
861 ret = __ncp_ioctl(filp, cmd, arg); 904 ret = __ncp_ioctl(inode, cmd, arg);
862 if (ncp_ioctl_need_write(cmd)) 905outDropWrite:
906 if (need_drop_write)
863 mnt_drop_write(filp->f_path.mnt); 907 mnt_drop_write(filp->f_path.mnt);
864
865out: 908out:
866 unlock_kernel();
867 return ret; 909 return ret;
868} 910}
869 911
@@ -872,10 +914,8 @@ long ncp_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
872{ 914{
873 long ret; 915 long ret;
874 916
875 lock_kernel();
876 arg = (unsigned long) compat_ptr(arg); 917 arg = (unsigned long) compat_ptr(arg);
877 ret = ncp_ioctl(file, cmd, arg); 918 ret = ncp_ioctl(file, cmd, arg);
878 unlock_kernel();
879 return ret; 919 return ret;
880} 920}
881#endif 921#endif
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 0ec6237a5970..a95615a0b6ac 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -107,17 +107,17 @@ ncp_reply_data(struct ncp_server *server, int offset)
107 return &(server->packet[sizeof(struct ncp_reply_header) + offset]); 107 return &(server->packet[sizeof(struct ncp_reply_header) + offset]);
108} 108}
109 109
110static inline u8 BVAL(void *data) 110static inline u8 BVAL(const void *data)
111{ 111{
112 return *(u8 *)data; 112 return *(const u8 *)data;
113} 113}
114 114
115static u8 ncp_reply_byte(struct ncp_server *server, int offset) 115static u8 ncp_reply_byte(struct ncp_server *server, int offset)
116{ 116{
117 return *(u8 *)ncp_reply_data(server, offset); 117 return *(const u8 *)ncp_reply_data(server, offset);
118} 118}
119 119
120static inline u16 WVAL_LH(void *data) 120static inline u16 WVAL_LH(const void *data)
121{ 121{
122 return get_unaligned_le16(data); 122 return get_unaligned_le16(data);
123} 123}
@@ -134,7 +134,7 @@ ncp_reply_be16(struct ncp_server *server, int offset)
134 return get_unaligned_be16(ncp_reply_data(server, offset)); 134 return get_unaligned_be16(ncp_reply_data(server, offset));
135} 135}
136 136
137static inline u32 DVAL_LH(void *data) 137static inline u32 DVAL_LH(const void *data)
138{ 138{
139 return get_unaligned_le32(data); 139 return get_unaligned_le32(data);
140} 140}
@@ -349,9 +349,9 @@ int ncp_dirhandle_free(struct ncp_server* server, __u8 dirhandle) {
349 return result; 349 return result;
350} 350}
351 351
352void ncp_extract_file_info(void *structure, struct nw_info_struct *target) 352void ncp_extract_file_info(const void *structure, struct nw_info_struct *target)
353{ 353{
354 __u8 *name_len; 354 const __u8 *name_len;
355 const int info_struct_size = offsetof(struct nw_info_struct, nameLen); 355 const int info_struct_size = offsetof(struct nw_info_struct, nameLen);
356 356
357 memcpy(target, structure, info_struct_size); 357 memcpy(target, structure, info_struct_size);
@@ -364,7 +364,7 @@ void ncp_extract_file_info(void *structure, struct nw_info_struct *target)
364} 364}
365 365
366#ifdef CONFIG_NCPFS_NFS_NS 366#ifdef CONFIG_NCPFS_NFS_NS
367static inline void ncp_extract_nfs_info(unsigned char *structure, 367static inline void ncp_extract_nfs_info(const unsigned char *structure,
368 struct nw_nfs_info *target) 368 struct nw_nfs_info *target)
369{ 369{
370 target->mode = DVAL_LH(structure); 370 target->mode = DVAL_LH(structure);
@@ -417,7 +417,7 @@ int ncp_obtain_nfs_info(struct ncp_server *server,
417 * Returns information for a (one-component) name relative to 417 * Returns information for a (one-component) name relative to
418 * the specified directory. 418 * the specified directory.
419 */ 419 */
420int ncp_obtain_info(struct ncp_server *server, struct inode *dir, char *path, 420int ncp_obtain_info(struct ncp_server *server, struct inode *dir, const char *path,
421 struct nw_info_struct *target) 421 struct nw_info_struct *target)
422{ 422{
423 __u8 volnum = NCP_FINFO(dir)->volNumber; 423 __u8 volnum = NCP_FINFO(dir)->volNumber;
@@ -452,16 +452,16 @@ out:
452#ifdef CONFIG_NCPFS_NFS_NS 452#ifdef CONFIG_NCPFS_NFS_NS
453static int 453static int
454ncp_obtain_DOS_dir_base(struct ncp_server *server, 454ncp_obtain_DOS_dir_base(struct ncp_server *server,
455 __u8 volnum, __le32 dirent, 455 __u8 ns, __u8 volnum, __le32 dirent,
456 char *path, /* At most 1 component */ 456 const char *path, /* At most 1 component */
457 __le32 *DOS_dir_base) 457 __le32 *DOS_dir_base)
458{ 458{
459 int result; 459 int result;
460 460
461 ncp_init_request(server); 461 ncp_init_request(server);
462 ncp_add_byte(server, 6); /* subfunction */ 462 ncp_add_byte(server, 6); /* subfunction */
463 ncp_add_byte(server, server->name_space[volnum]); 463 ncp_add_byte(server, ns);
464 ncp_add_byte(server, server->name_space[volnum]); 464 ncp_add_byte(server, ns);
465 ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */ 465 ncp_add_word(server, cpu_to_le16(0x8006)); /* get all */
466 ncp_add_dword(server, RIM_DIRECTORY); 466 ncp_add_dword(server, RIM_DIRECTORY);
467 ncp_add_handle_path(server, volnum, dirent, 1, path); 467 ncp_add_handle_path(server, volnum, dirent, 1, path);
@@ -523,10 +523,27 @@ ncp_get_known_namespace(struct ncp_server *server, __u8 volume)
523#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */ 523#endif /* defined(CONFIG_NCPFS_OS2_NS) || defined(CONFIG_NCPFS_NFS_NS) */
524} 524}
525 525
526int
527ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns)
528{
529 int ns = ncp_get_known_namespace(server, volume);
530
531 if (ret_ns)
532 *ret_ns = ns;
533
534 DPRINTK("lookup_vol: namespace[%d] = %d\n",
535 volume, server->name_space[volume]);
536
537 if (server->name_space[volume] == ns)
538 return 0;
539 server->name_space[volume] = ns;
540 return 1;
541}
542
526static int 543static int
527ncp_ObtainSpecificDirBase(struct ncp_server *server, 544ncp_ObtainSpecificDirBase(struct ncp_server *server,
528 __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base, 545 __u8 nsSrc, __u8 nsDst, __u8 vol_num, __le32 dir_base,
529 char *path, /* At most 1 component */ 546 const char *path, /* At most 1 component */
530 __le32 *dirEntNum, __le32 *DosDirNum) 547 __le32 *dirEntNum, __le32 *DosDirNum)
531{ 548{
532 int result; 549 int result;
@@ -560,14 +577,13 @@ ncp_mount_subdir(struct ncp_server *server,
560{ 577{
561 int dstNS; 578 int dstNS;
562 int result; 579 int result;
563 580
564 dstNS = ncp_get_known_namespace(server, volNumber); 581 ncp_update_known_namespace(server, volNumber, &dstNS);
565 if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber, 582 if ((result = ncp_ObtainSpecificDirBase(server, srcNS, dstNS, volNumber,
566 dirEntNum, NULL, newDirEnt, newDosEnt)) != 0) 583 dirEntNum, NULL, newDirEnt, newDosEnt)) != 0)
567 { 584 {
568 return result; 585 return result;
569 } 586 }
570 server->name_space[volNumber] = dstNS;
571 *volume = volNumber; 587 *volume = volNumber;
572 server->m.mounted_vol[1] = 0; 588 server->m.mounted_vol[1] = 0;
573 server->m.mounted_vol[0] = 'X'; 589 server->m.mounted_vol[0] = 'X';
@@ -575,11 +591,10 @@ ncp_mount_subdir(struct ncp_server *server,
575} 591}
576 592
577int 593int
578ncp_get_volume_root(struct ncp_server *server, const char *volname, 594ncp_get_volume_root(struct ncp_server *server,
579 __u32* volume, __le32* dirent, __le32* dosdirent) 595 const char *volname, __u32* volume, __le32* dirent, __le32* dosdirent)
580{ 596{
581 int result; 597 int result;
582 __u8 volnum;
583 598
584 DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname); 599 DPRINTK("ncp_get_volume_root: looking up vol %s\n", volname);
585 600
@@ -601,21 +616,14 @@ ncp_get_volume_root(struct ncp_server *server, const char *volname,
601 return result; 616 return result;
602 } 617 }
603 *dirent = *dosdirent = ncp_reply_dword(server, 4); 618 *dirent = *dosdirent = ncp_reply_dword(server, 4);
604 volnum = ncp_reply_byte(server, 8); 619 *volume = ncp_reply_byte(server, 8);
605 ncp_unlock_server(server); 620 ncp_unlock_server(server);
606 *volume = volnum;
607
608 server->name_space[volnum] = ncp_get_known_namespace(server, volnum);
609
610 DPRINTK("lookup_vol: namespace[%d] = %d\n",
611 volnum, server->name_space[volnum]);
612
613 return 0; 621 return 0;
614} 622}
615 623
616int 624int
617ncp_lookup_volume(struct ncp_server *server, const char *volname, 625ncp_lookup_volume(struct ncp_server *server,
618 struct nw_info_struct *target) 626 const char *volname, struct nw_info_struct *target)
619{ 627{
620 int result; 628 int result;
621 629
@@ -625,6 +633,7 @@ ncp_lookup_volume(struct ncp_server *server, const char *volname,
625 if (result) { 633 if (result) {
626 return result; 634 return result;
627 } 635 }
636 ncp_update_known_namespace(server, target->volNumber, NULL);
628 target->nameLen = strlen(volname); 637 target->nameLen = strlen(volname);
629 memcpy(target->entryName, volname, target->nameLen+1); 638 memcpy(target->entryName, volname, target->nameLen+1);
630 target->attributes = aDIR; 639 target->attributes = aDIR;
@@ -676,8 +685,8 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
676{ 685{
677 int result = 0; 686 int result = 0;
678 687
688 ncp_init_request(server);
679 if (server->name_space[volnum] == NW_NS_NFS) { 689 if (server->name_space[volnum] == NW_NS_NFS) {
680 ncp_init_request(server);
681 ncp_add_byte(server, 25); /* subfunction */ 690 ncp_add_byte(server, 25); /* subfunction */
682 ncp_add_byte(server, server->name_space[volnum]); 691 ncp_add_byte(server, server->name_space[volnum]);
683 ncp_add_byte(server, NW_NS_NFS); 692 ncp_add_byte(server, NW_NS_NFS);
@@ -690,8 +699,8 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
690 ncp_add_dword_lh(server, 1); /* nlinks */ 699 ncp_add_dword_lh(server, 1); /* nlinks */
691 ncp_add_dword_lh(server, rdev); 700 ncp_add_dword_lh(server, rdev);
692 result = ncp_request(server, 87); 701 result = ncp_request(server, 87);
693 ncp_unlock_server(server);
694 } 702 }
703 ncp_unlock_server(server);
695 return result; 704 return result;
696} 705}
697#endif 706#endif
@@ -700,7 +709,7 @@ int ncp_modify_nfs_info(struct ncp_server *server, __u8 volnum, __le32 dirent,
700static int 709static int
701ncp_DeleteNSEntry(struct ncp_server *server, 710ncp_DeleteNSEntry(struct ncp_server *server,
702 __u8 have_dir_base, __u8 volnum, __le32 dirent, 711 __u8 have_dir_base, __u8 volnum, __le32 dirent,
703 char* name, __u8 ns, __le16 attr) 712 const char* name, __u8 ns, __le16 attr)
704{ 713{
705 int result; 714 int result;
706 715
@@ -734,23 +743,25 @@ ncp_del_file_or_subdir2(struct ncp_server *server,
734 743
735int 744int
736ncp_del_file_or_subdir(struct ncp_server *server, 745ncp_del_file_or_subdir(struct ncp_server *server,
737 struct inode *dir, char *name) 746 struct inode *dir, const char *name)
738{ 747{
739 __u8 volnum = NCP_FINFO(dir)->volNumber; 748 __u8 volnum = NCP_FINFO(dir)->volNumber;
740 __le32 dirent = NCP_FINFO(dir)->dirEntNum; 749 __le32 dirent = NCP_FINFO(dir)->dirEntNum;
750 int name_space;
741 751
752 name_space = server->name_space[volnum];
742#ifdef CONFIG_NCPFS_NFS_NS 753#ifdef CONFIG_NCPFS_NFS_NS
743 if (server->name_space[volnum]==NW_NS_NFS) 754 if (name_space == NW_NS_NFS)
744 { 755 {
745 int result; 756 int result;
746 757
747 result=ncp_obtain_DOS_dir_base(server, volnum, dirent, name, &dirent); 758 result=ncp_obtain_DOS_dir_base(server, name_space, volnum, dirent, name, &dirent);
748 if (result) return result; 759 if (result) return result;
749 return ncp_DeleteNSEntry(server, 1, volnum, dirent, NULL, NW_NS_DOS, cpu_to_le16(0x8006)); 760 name = NULL;
761 name_space = NW_NS_DOS;
750 } 762 }
751 else
752#endif /* CONFIG_NCPFS_NFS_NS */ 763#endif /* CONFIG_NCPFS_NFS_NS */
753 return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, server->name_space[volnum], cpu_to_le16(0x8006)); 764 return ncp_DeleteNSEntry(server, 1, volnum, dirent, name, name_space, cpu_to_le16(0x8006));
754} 765}
755 766
756static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6]) 767static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
@@ -765,7 +776,7 @@ static inline void ConvertToNWfromDWORD(__u16 v0, __u16 v1, __u8 ret[6])
765/* If both dir and name are NULL, then in target there's already a 776/* If both dir and name are NULL, then in target there's already a
766 looked-up entry that wants to be opened. */ 777 looked-up entry that wants to be opened. */
767int ncp_open_create_file_or_subdir(struct ncp_server *server, 778int ncp_open_create_file_or_subdir(struct ncp_server *server,
768 struct inode *dir, char *name, 779 struct inode *dir, const char *name,
769 int open_create_mode, 780 int open_create_mode,
770 __le32 create_attributes, 781 __le32 create_attributes,
771 __le16 desired_acc_rights, 782 __le16 desired_acc_rights,
@@ -890,8 +901,8 @@ int ncp_search_for_fileset(struct ncp_server *server,
890 901
891static int 902static int
892ncp_RenameNSEntry(struct ncp_server *server, 903ncp_RenameNSEntry(struct ncp_server *server,
893 struct inode *old_dir, char *old_name, __le16 old_type, 904 struct inode *old_dir, const char *old_name, __le16 old_type,
894 struct inode *new_dir, char *new_name) 905 struct inode *new_dir, const char *new_name)
895{ 906{
896 int result = -EINVAL; 907 int result = -EINVAL;
897 908
@@ -929,8 +940,8 @@ out:
929} 940}
930 941
931int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, 942int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
932 struct inode *old_dir, char *old_name, 943 struct inode *old_dir, const char *old_name,
933 struct inode *new_dir, char *new_name) 944 struct inode *new_dir, const char *new_name)
934{ 945{
935 int result; 946 int result;
936 __le16 old_type = cpu_to_le16(0x06); 947 __le16 old_type = cpu_to_le16(0x06);
@@ -958,7 +969,7 @@ int
958ncp_read_kernel(struct ncp_server *server, const char *file_id, 969ncp_read_kernel(struct ncp_server *server, const char *file_id,
959 __u32 offset, __u16 to_read, char *target, int *bytes_read) 970 __u32 offset, __u16 to_read, char *target, int *bytes_read)
960{ 971{
961 char *source; 972 const char *source;
962 int result; 973 int result;
963 974
964 ncp_init_request(server); 975 ncp_init_request(server);
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 2441d1ab57dc..3c57eca634ce 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -65,10 +65,11 @@ static inline void ncp_inode_close(struct inode *inode) {
65 atomic_dec(&NCP_FINFO(inode)->opened); 65 atomic_dec(&NCP_FINFO(inode)->opened);
66} 66}
67 67
68void ncp_extract_file_info(void* src, struct nw_info_struct* target); 68void ncp_extract_file_info(const void* src, struct nw_info_struct* target);
69int ncp_obtain_info(struct ncp_server *server, struct inode *, char *, 69int ncp_obtain_info(struct ncp_server *server, struct inode *, const char *,
70 struct nw_info_struct *target); 70 struct nw_info_struct *target);
71int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target); 71int ncp_obtain_nfs_info(struct ncp_server *server, struct nw_info_struct *target);
72int ncp_update_known_namespace(struct ncp_server *server, __u8 volume, int *ret_ns);
72int ncp_get_volume_root(struct ncp_server *server, const char *volname, 73int ncp_get_volume_root(struct ncp_server *server, const char *volname,
73 __u32 *volume, __le32 *dirent, __le32 *dosdirent); 74 __u32 *volume, __le32 *dirent, __le32 *dosdirent);
74int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *); 75int ncp_lookup_volume(struct ncp_server *, const char *, struct nw_info_struct *);
@@ -80,8 +81,8 @@ int ncp_modify_nfs_info(struct ncp_server *, __u8 volnum, __le32 dirent,
80 __u32 mode, __u32 rdev); 81 __u32 mode, __u32 rdev);
81 82
82int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*); 83int ncp_del_file_or_subdir2(struct ncp_server *, struct dentry*);
83int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, char *); 84int ncp_del_file_or_subdir(struct ncp_server *, struct inode *, const char *);
84int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *, 85int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, const char *,
85 int, __le32, __le16, struct ncp_entry_info *); 86 int, __le32, __le16, struct ncp_entry_info *);
86 87
87int ncp_initialize_search(struct ncp_server *, struct inode *, 88int ncp_initialize_search(struct ncp_server *, struct inode *,
@@ -93,7 +94,7 @@ int ncp_search_for_fileset(struct ncp_server *server,
93 char** rbuf, size_t* rsize); 94 char** rbuf, size_t* rsize);
94 95
95int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server, 96int ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
96 struct inode *, char *, struct inode *, char *); 97 struct inode *, const char *, struct inode *, const char *);
97 98
98 99
99int 100int
@@ -170,13 +171,13 @@ static inline int ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
170#endif /* CONFIG_NCPFS_NLS */ 171#endif /* CONFIG_NCPFS_NLS */
171 172
172#define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time) 173#define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time)
173#define NCP_MAX_AGE(server) ((server)->dentry_ttl) 174#define NCP_MAX_AGE(server) atomic_read(&(server)->dentry_ttl)
174#define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server)) 175#define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
175 176
176static inline void 177static inline void
177ncp_age_dentry(struct ncp_server* server, struct dentry* dentry) 178ncp_age_dentry(struct ncp_server* server, struct dentry* dentry)
178{ 179{
179 dentry->d_time = jiffies - server->dentry_ttl; 180 dentry->d_time = jiffies - NCP_MAX_AGE(server);
180} 181}
181 182
182static inline void 183static inline void
diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
index 7c0b5c21e6cf..d8b2d7e6910b 100644
--- a/fs/ncpfs/ncpsign_kernel.c
+++ b/fs/ncpfs/ncpsign_kernel.c
@@ -15,21 +15,21 @@
15 15
16/* i386: 32-bit, little endian, handles mis-alignment */ 16/* i386: 32-bit, little endian, handles mis-alignment */
17#ifdef __i386__ 17#ifdef __i386__
18#define GET_LE32(p) (*(int *)(p)) 18#define GET_LE32(p) (*(const int *)(p))
19#define PUT_LE32(p,v) { *(int *)(p)=v; } 19#define PUT_LE32(p,v) { *(int *)(p)=v; }
20#else 20#else
21/* from include/ncplib.h */ 21/* from include/ncplib.h */
22#define BVAL(buf,pos) (((__u8 *)(buf))[pos]) 22#define BVAL(buf,pos) (((const __u8 *)(buf))[pos])
23#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos)) 23#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
24#define BSET(buf,pos,val) (BVAL(buf,pos) = (val)) 24#define BSET(buf,pos,val) (((__u8 *)(buf))[pos] = (val))
25 25
26static inline __u16 26static inline __u16
27WVAL_LH(__u8 * buf, int pos) 27WVAL_LH(const __u8 * buf, int pos)
28{ 28{
29 return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8; 29 return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8;
30} 30}
31static inline __u32 31static inline __u32
32DVAL_LH(__u8 * buf, int pos) 32DVAL_LH(const __u8 * buf, int pos)
33{ 33{
34 return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16; 34 return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16;
35} 35}
diff --git a/fs/ncpfs/sock.c b/fs/ncpfs/sock.c
index c7ff6c700a6e..668bd267346e 100644
--- a/fs/ncpfs/sock.c
+++ b/fs/ncpfs/sock.c
@@ -746,7 +746,6 @@ static int ncp_do_request(struct ncp_server *server, int size,
746 return -EIO; 746 return -EIO;
747 } 747 }
748 if (!ncp_conn_valid(server)) { 748 if (!ncp_conn_valid(server)) {
749 printk(KERN_ERR "ncpfs: Connection invalid!\n");
750 return -EIO; 749 return -EIO;
751 } 750 }
752 { 751 {
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 4522aed00906..ef663061d5ac 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -241,34 +241,6 @@ int ncp_mmap(struct file *, struct vm_area_struct *);
241/* linux/fs/ncpfs/ncplib_kernel.c */ 241/* linux/fs/ncpfs/ncplib_kernel.c */
242int ncp_make_closed(struct inode *); 242int ncp_make_closed(struct inode *);
243 243
244#define ncp_namespace(i) (NCP_SERVER(i)->name_space[NCP_FINFO(i)->volNumber])
245
246static inline int ncp_preserve_entry_case(struct inode *i, __u32 nscreator)
247{
248#ifdef CONFIG_NCPFS_SMALLDOS
249 int ns = ncp_namespace(i);
250
251 if ((ns == NW_NS_DOS)
252#ifdef CONFIG_NCPFS_OS2_NS
253 || ((ns == NW_NS_OS2) && (nscreator == NW_NS_DOS))
254#endif /* CONFIG_NCPFS_OS2_NS */
255 )
256 return 0;
257#endif /* CONFIG_NCPFS_SMALLDOS */
258 return 1;
259}
260
261#define ncp_preserve_case(i) (ncp_namespace(i) != NW_NS_DOS)
262
263static inline int ncp_case_sensitive(struct inode *i)
264{
265#ifdef CONFIG_NCPFS_NFS_NS
266 return ncp_namespace(i) == NW_NS_NFS;
267#else
268 return 0;
269#endif /* CONFIG_NCPFS_NFS_NS */
270}
271
272#endif /* __KERNEL__ */ 244#endif /* __KERNEL__ */
273 245
274#endif /* _LINUX_NCP_FS_H */ 246#endif /* _LINUX_NCP_FS_H */
diff --git a/include/linux/ncp_fs_sb.h b/include/linux/ncp_fs_sb.h
index 8da05bc098ca..d64b0e894336 100644
--- a/include/linux/ncp_fs_sb.h
+++ b/include/linux/ncp_fs_sb.h
@@ -62,6 +62,7 @@ struct ncp_server {
62 int ncp_reply_size; 62 int ncp_reply_size;
63 63
64 int root_setuped; 64 int root_setuped;
65 struct mutex root_setup_lock;
65 66
66 /* info for packet signing */ 67 /* info for packet signing */
67 int sign_wanted; /* 1=Server needs signed packets */ 68 int sign_wanted; /* 1=Server needs signed packets */
@@ -81,13 +82,14 @@ struct ncp_server {
81 size_t len; 82 size_t len;
82 void* data; 83 void* data;
83 } priv; 84 } priv;
85 struct rw_semaphore auth_rwsem;
84 86
85 /* nls info: codepage for volume and charset for I/O */ 87 /* nls info: codepage for volume and charset for I/O */
86 struct nls_table *nls_vol; 88 struct nls_table *nls_vol;
87 struct nls_table *nls_io; 89 struct nls_table *nls_io;
88 90
89 /* maximum age in jiffies */ 91 /* maximum age in jiffies */
90 int dentry_ttl; 92 atomic_t dentry_ttl;
91 93
92 /* miscellaneous */ 94 /* miscellaneous */
93 unsigned int flags; 95 unsigned int flags;