diff options
author | Steve French <smfrench@austin.rr.com> | 2005-04-29 01:41:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-29 01:41:05 -0400 |
commit | 6a0b48245a135cd132e747815854e3999967f8a7 (patch) | |
tree | 55fffb67b924fbca2a5a16e83100a5d1000daaf4 | |
parent | cbe0476fa6a76b01b79e7c117963d45ed0a28758 (diff) |
[PATCH] cifs: Add new mount parm mapchars
For handling seven special characters that shells use for filenames.
This first parts implements conversions from Unicode.
Signed-off-by: Steve French
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/cifs/CHANGES | 4 | ||||
-rw-r--r-- | fs/cifs/README | 11 | ||||
-rw-r--r-- | fs/cifs/TODO | 19 | ||||
-rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/connect.c | 7 | ||||
-rw-r--r-- | fs/cifs/misc.c | 69 | ||||
-rw-r--r-- | fs/cifs/readdir.c | 15 |
8 files changed, 116 insertions, 12 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index ce16b0ae772e..412b6d243d53 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -7,7 +7,9 @@ as new protocol extensions. Do not send Get/Set calls for POSIX ACLs | |||
7 | unless server explicitly claims to support them in CIFS Unix extensions | 7 | unless server explicitly claims to support them in CIFS Unix extensions |
8 | POSIX ACL capability bit. Fix packet signing when multiuser mounting with | 8 | POSIX ACL capability bit. Fix packet signing when multiuser mounting with |
9 | different users from the same client to the same server. Fix oops in | 9 | different users from the same client to the same server. Fix oops in |
10 | cifs_close. | 10 | cifs_close. Add mount option for remapping reserved characters in |
11 | filenames (also allow recognizing files with created by SFU which have any | ||
12 | of these seven reserved characters to be recognized). | ||
11 | 13 | ||
12 | Version 1.31 | 14 | Version 1.31 |
13 | ------------ | 15 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index 0f20edc935b5..83e054576258 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -376,6 +376,17 @@ A partial list of the supported mount options follows: | |||
376 | attributes) to the server (default) e.g. via setfattr | 376 | attributes) to the server (default) e.g. via setfattr |
377 | and getfattr utilities. | 377 | and getfattr utilities. |
378 | nouser_xattr Do not allow getfattr/setfattr to get/set xattrs | 378 | nouser_xattr Do not allow getfattr/setfattr to get/set xattrs |
379 | mapchars Translate the seven reserved characters | ||
380 | *?<>|:\ | ||
381 | to the remap range (above 0xF000), which also | ||
382 | allows the CIFS client to recognize files created with | ||
383 | such characters by Windows's POSIX emulation. This can | ||
384 | also be useful when mounting to most versions of Samba | ||
385 | (which also forbids creating and opening files | ||
386 | whose names contain any of these seven characters). | ||
387 | This has no effect if the server does not support | ||
388 | Unicode on the wire. | ||
389 | nomapchars Do not translate any of these seven characters (default). | ||
379 | 390 | ||
380 | The mount.cifs mount helper also accepts a few mount options before -o | 391 | The mount.cifs mount helper also accepts a few mount options before -o |
381 | including: | 392 | including: |
diff --git a/fs/cifs/TODO b/fs/cifs/TODO index f4e3e1f67ee4..a69227415a73 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO | |||
@@ -1,4 +1,4 @@ | |||
1 | version 1.22 July 30, 2004 | 1 | version 1.32 April 3, 2005 |
2 | 2 | ||
3 | A Partial List of Missing Features | 3 | A Partial List of Missing Features |
4 | ================================== | 4 | ================================== |
@@ -14,7 +14,7 @@ b) Better pam/winbind integration (e.g. to handle uid mapping | |||
14 | better) | 14 | better) |
15 | 15 | ||
16 | c) multi-user mounts - multiplexed sessionsetups over single vc | 16 | c) multi-user mounts - multiplexed sessionsetups over single vc |
17 | (ie tcp session) - prettying up needed, and more testing needed | 17 | (ie tcp session) - more testing needed |
18 | 18 | ||
19 | d) Kerberos/SPNEGO session setup support - (started) | 19 | d) Kerberos/SPNEGO session setup support - (started) |
20 | 20 | ||
@@ -67,12 +67,15 @@ q) implement support for security and trusted categories of xattrs | |||
67 | 67 | ||
68 | r) Implement O_DIRECT flag on open (already supported on mount) | 68 | r) Implement O_DIRECT flag on open (already supported on mount) |
69 | 69 | ||
70 | KNOWN BUGS (updated December 10, 2004) | 70 | KNOWN BUGS (updated April 3, 2005) |
71 | ==================================== | 71 | ==================================== |
72 | See http://bugzilla.samba.org - search on product "CifsVFS" for | ||
73 | current bug list. | ||
74 | |||
72 | 1) existing symbolic links (Windows reparse points) are recognized but | 75 | 1) existing symbolic links (Windows reparse points) are recognized but |
73 | can not be created remotely. They are implemented for Samba and those that | 76 | can not be created remotely. They are implemented for Samba and those that |
74 | support the CIFS Unix extensions but Samba has a bug currently handling | 77 | support the CIFS Unix extensions, although earlier versions of Samba |
75 | symlink text beginning with slash | 78 | overly restrict the pathnames. |
76 | 2) follow_link and readdir code does not follow dfs junctions | 79 | 2) follow_link and readdir code does not follow dfs junctions |
77 | but recognizes them | 80 | but recognizes them |
78 | 3) create of new files to FAT partitions on Windows servers can | 81 | 3) create of new files to FAT partitions on Windows servers can |
@@ -98,7 +101,5 @@ there are some easy changes that can be done to parallelize sequential writes, | |||
98 | and when signing is disabled to request larger read sizes (larger than | 101 | and when signing is disabled to request larger read sizes (larger than |
99 | negotiated size) and send larger write sizes to modern servers. | 102 | negotiated size) and send larger write sizes to modern servers. |
100 | 103 | ||
101 | 4) More exhaustively test the recently added NT4 support against various | 104 | 4) More exhaustively test against less common servers. More testing |
102 | NT4 service pack levels, and fix cifs_setattr for setting file times and | 105 | against Windows 9x, Windows ME servers. |
103 | size to fall back to level 1 when error invalid level returned. | ||
104 | |||
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 77da902d8f32..ec00d61d5308 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ | 23 | #define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ |
24 | #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ | 24 | #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ |
25 | #define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ | 25 | #define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ |
26 | #define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ | ||
26 | 27 | ||
27 | struct cifs_sb_info { | 28 | struct cifs_sb_info { |
28 | struct cifsTconInfo *tcon; /* primary mount */ | 29 | struct cifsTconInfo *tcon; /* primary mount */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index dd95c2bcbc25..b486ba738d95 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -212,6 +212,8 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, | |||
212 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, | 212 | extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, |
213 | const unsigned char *searchName, __u64 * inode_number, | 213 | const unsigned char *searchName, __u64 * inode_number, |
214 | const struct nls_table *nls_codepage); | 214 | const struct nls_table *nls_codepage); |
215 | extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, | ||
216 | const struct nls_table * codepage); | ||
215 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 217 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
216 | 218 | ||
217 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, | 219 | extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 814e709ca0ca..3d036bf689d8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -72,6 +72,7 @@ struct smb_vol { | |||
72 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ | 72 | unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ |
73 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ | 73 | unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ |
74 | unsigned direct_io:1; | 74 | unsigned direct_io:1; |
75 | unsigned remap:1; /* set to remap seven reserved chars in filenames */ | ||
75 | unsigned int rsize; | 76 | unsigned int rsize; |
76 | unsigned int wsize; | 77 | unsigned int wsize; |
77 | unsigned int sockopt; | 78 | unsigned int sockopt; |
@@ -771,6 +772,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) | |||
771 | vol->noperm = 0; | 772 | vol->noperm = 0; |
772 | } else if (strnicmp(data, "noperm", 6) == 0) { | 773 | } else if (strnicmp(data, "noperm", 6) == 0) { |
773 | vol->noperm = 1; | 774 | vol->noperm = 1; |
775 | } else if (strnicmp(data, "mapchars", 8) == 0) { | ||
776 | vol->remap = 1; | ||
777 | } else if (strnicmp(data, "nomapchars", 10) == 0) { | ||
778 | vol->remap = 0; | ||
774 | } else if (strnicmp(data, "setuids", 7) == 0) { | 779 | } else if (strnicmp(data, "setuids", 7) == 0) { |
775 | vol->setuids = 1; | 780 | vol->setuids = 1; |
776 | } else if (strnicmp(data, "nosetuids", 9) == 0) { | 781 | } else if (strnicmp(data, "nosetuids", 9) == 0) { |
@@ -1421,6 +1426,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
1421 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; | 1426 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; |
1422 | if(volume_info.server_ino) | 1427 | if(volume_info.server_ino) |
1423 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; | 1428 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; |
1429 | if(volume_info.remap) | ||
1430 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; | ||
1424 | if(volume_info.no_xattr) | 1431 | if(volume_info.no_xattr) |
1425 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; | 1432 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; |
1426 | if(volume_info.direct_io) { | 1433 | if(volume_info.direct_io) { |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 7b38d3059a83..f2a026073b62 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -514,3 +514,72 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | |||
514 | printk( " | %s\n", debug_line); | 514 | printk( " | %s\n", debug_line); |
515 | return; | 515 | return; |
516 | } | 516 | } |
517 | |||
518 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
519 | /* Windows maps these to the user defined 16 bit Unicode range since they are | ||
520 | reserved symbols (along with \ and /), otherwise illegal to store | ||
521 | in filenames in NTFS */ | ||
522 | #define UNI_ASTERIK cpu_to_le16('*' + 0xF000) | ||
523 | #define UNI_QUESTION cpu_to_le16('?' + 0xF000) | ||
524 | #define UNI_COLON cpu_to_le16(':' + 0xF000) | ||
525 | #define UNI_GRTRTHAN cpu_to_le16('>' + 0xF000) | ||
526 | #define UNI_LESSTHAN cpu_to_le16('<' + 0xF000) | ||
527 | #define UNI_PIPE cpu_to_le16('|' + 0xF000) | ||
528 | #define UNI_SLASH cpu_to_le16('\\' + 0xF000) | ||
529 | |||
530 | /* Convert 16 bit Unicode pathname from wire format to string in current code | ||
531 | page. Conversion may involve remapping up the seven characters that are | ||
532 | only legal in POSIX-like OS (if they are present in the string). Path | ||
533 | names are little endian 16 bit Unicode on the wire */ | ||
534 | int | ||
535 | cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, | ||
536 | const struct nls_table * cp) | ||
537 | { | ||
538 | int i,j,len; | ||
539 | wchar_t src_char; | ||
540 | |||
541 | for(i = 0, j = 0; i < maxlen; i++) { | ||
542 | src_char = le16_to_cpu(source[i]); | ||
543 | switch (src_char) { | ||
544 | case 0: | ||
545 | goto cUCS_out; /* BB check this BB */ | ||
546 | case UNI_COLON: | ||
547 | target[j] = ':'; | ||
548 | break; | ||
549 | case UNI_ASTERIK: | ||
550 | target[j] = '*'; | ||
551 | break; | ||
552 | case UNI_QUESTION: | ||
553 | target[j] = '?'; | ||
554 | break; | ||
555 | case UNI_SLASH: | ||
556 | target[j] = '\\'; /* BB check this - is there risk here of converting path sep BB */ | ||
557 | break; | ||
558 | case UNI_PIPE: | ||
559 | target[j] = '|'; | ||
560 | break; | ||
561 | case UNI_GRTRTHAN: | ||
562 | target[j] = '>'; | ||
563 | break; | ||
564 | case UNI_LESSTHAN: | ||
565 | target[j] = '<'; | ||
566 | default: | ||
567 | len = cp->uni2char(src_char, &target[j], | ||
568 | NLS_MAX_CHARSET_SIZE); | ||
569 | if(len > 0) { | ||
570 | j += len; | ||
571 | continue; | ||
572 | } else { | ||
573 | target[j] = '?'; | ||
574 | } | ||
575 | } | ||
576 | j++; | ||
577 | /* check to make sure we do not overrun callers allocated temp buffer */ | ||
578 | if(j >= (2 * NAME_MAX)) | ||
579 | break; | ||
580 | } | ||
581 | cUCS_out: | ||
582 | target[j] = 0; | ||
583 | return j; | ||
584 | } | ||
585 | #endif /* CIFS_EXPERIMENTAL */ | ||
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 07838a5ba3a1..4a33add24d53 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -600,7 +600,14 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, | |||
600 | if(unicode) { | 600 | if(unicode) { |
601 | /* BB fixme - test with long names */ | 601 | /* BB fixme - test with long names */ |
602 | /* Note converted filename can be longer than in unicode */ | 602 | /* Note converted filename can be longer than in unicode */ |
603 | pqst->len = cifs_strfromUCS_le((char *)pqst->name,(wchar_t *)filename,len/2,nlt); | 603 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
604 | if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) | ||
605 | pqst->len = cifs_convertUCSpath((char *)pqst->name, | ||
606 | (__le16 *)filename, len/2, nlt); | ||
607 | else | ||
608 | #endif /* CIFS_EXPERIMENTAL */ | ||
609 | pqst->len = cifs_strfromUCS_le((char *)pqst->name, | ||
610 | (wchar_t *)filename,len/2,nlt); | ||
604 | } else { | 611 | } else { |
605 | pqst->name = filename; | 612 | pqst->name = filename; |
606 | pqst->len = len; | 613 | pqst->len = len; |
@@ -829,7 +836,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
829 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + | 836 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + |
830 | smbCalcSize((struct smb_hdr *) | 837 | smbCalcSize((struct smb_hdr *) |
831 | cifsFile->srch_inf.ntwrk_buf_start); | 838 | cifsFile->srch_inf.ntwrk_buf_start); |
832 | tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL); | 839 | /* To be safe - for UCS to UTF-8 with strings loaded |
840 | with the rare long characters alloc more to account for | ||
841 | such multibyte target UTF-8 characters. cifs_unicode.c, | ||
842 | which actually does the conversion, has the same limit */ | ||
843 | tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); | ||
833 | for(i=0;(i<num_to_fill) && (rc == 0);i++) { | 844 | for(i=0;(i<num_to_fill) && (rc == 0);i++) { |
834 | if(current_entry == NULL) { | 845 | if(current_entry == NULL) { |
835 | /* evaluate whether this case is an error */ | 846 | /* evaluate whether this case is an error */ |