diff options
author | Paulo Alcantara <pc@manguebit.com> | 2025-04-01 01:13:49 -0300 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2025-04-07 01:08:27 -0500 |
commit | 3d48316df903a48a533bb313e5da821a163738cd (patch) | |
tree | dd79845c8866574c00667ffda329282ae40b77c0 | |
parent | b365b9d404b7376c60c91cd079218bfef11b7822 (diff) | |
download | linux-3d48316df903a48a533bb313e5da821a163738cd.tar.gz linux-3d48316df903a48a533bb313e5da821a163738cd.tar.bz2 linux-3d48316df903a48a533bb313e5da821a163738cd.zip |
smb: client: optimize pathname checking
The default mapping for CIFS mounts (SFM) allows mapping backslash, so
fix it by mapping them to 0xf026 in UCS-2 and then allow files and
directories to be created with backslash in their names.
This will optimize cifs_check_name() as it won't need to check for
backslashes anymore when using default SFM mapping.
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202504021549.evbuYKS3-lkp@intel.com/
Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r-- | fs/smb/client/cached_dir.c | 3 | ||||
-rw-r--r-- | fs/smb/client/cifs_unicode.c | 22 | ||||
-rw-r--r-- | fs/smb/client/cifs_unicode.h | 14 | ||||
-rw-r--r-- | fs/smb/client/cifsacl.c | 36 | ||||
-rw-r--r-- | fs/smb/client/cifsfs.c | 24 | ||||
-rw-r--r-- | fs/smb/client/cifsglob.h | 25 | ||||
-rw-r--r-- | fs/smb/client/cifsproto.h | 119 | ||||
-rw-r--r-- | fs/smb/client/cifssmb.c | 570 | ||||
-rw-r--r-- | fs/smb/client/connect.c | 24 | ||||
-rw-r--r-- | fs/smb/client/dir.c | 74 | ||||
-rw-r--r-- | fs/smb/client/file.c | 3 | ||||
-rw-r--r-- | fs/smb/client/fs_context.c | 3 | ||||
-rw-r--r-- | fs/smb/client/inode.c | 39 | ||||
-rw-r--r-- | fs/smb/client/link.c | 9 | ||||
-rw-r--r-- | fs/smb/client/misc.c | 2 | ||||
-rw-r--r-- | fs/smb/client/namespace.c | 1 | ||||
-rw-r--r-- | fs/smb/client/smb1ops.c | 37 | ||||
-rw-r--r-- | fs/smb/client/smb2misc.c | 30 |
18 files changed, 384 insertions, 651 deletions
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index fe738623cf1b..9522710092b2 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -83,9 +83,8 @@ path_to_dentry(struct cifs_sb_info *cifs_sb, const char *path) { struct dentry *dentry; const char *s, *p; - char sep; + char sep = '/'; - sep = CIFS_DIR_SEP(cifs_sb); dentry = dget(cifs_sb->root); s = path; diff --git a/fs/smb/client/cifs_unicode.c b/fs/smb/client/cifs_unicode.c index 4cc6e0896fad..eef00470f86b 100644 --- a/fs/smb/client/cifs_unicode.c +++ b/fs/smb/client/cifs_unicode.c @@ -96,6 +96,9 @@ convert_sfm_char(const __u16 src_char, char *target) case SFM_PERIOD: *target = '.'; break; + case SFM_SLASH: + *target = '\\'; + break; default: return false; } @@ -436,6 +439,9 @@ static __le16 convert_to_sfm_char(char src_char, bool end_of_string) else dest_char = 0; break; + case '\\': + dest_char = cpu_to_le16(SFM_SLASH); + break; default: dest_char = 0; } @@ -488,17 +494,17 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, * They are treated as non-end-of-string to avoid * remapping and breaking symlinks pointing to . or .. **/ - if ((i == 0 || source[i-1] == '\\') && + if ((i == 0 || source[i-1] == '/') && source[i] == '.' && - (i == srclen-1 || source[i+1] == '\\')) + (i == srclen-1 || source[i+1] == '/')) end_of_string = false; /* "." case */ else if (i >= 1 && - (i == 1 || source[i-2] == '\\') && + (i == 1 || source[i-2] == '/') && source[i-1] == '.' && source[i] == '.' && - (i == srclen-1 || source[i+1] == '\\')) + (i == srclen-1 || source[i+1] == '/')) end_of_string = false; /* ".." case */ - else if ((i == srclen - 1) || (source[i+1] == '\\')) + else if ((i == srclen - 1) || (source[i+1] == '/')) end_of_string = true; else end_of_string = false; @@ -506,11 +512,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, dst_char = convert_to_sfm_char(src_char, end_of_string); } else dst_char = 0; - /* - * FIXME: We can not handle remapping backslash (UNI_SLASH) - * until all the calls to build_path_from_dentry are modified, - * as they use backslash as separator. - */ + if (dst_char == 0) { charlen = cp->char2uni(source + i, srclen - i, &tmp); dst_char = cpu_to_le16(tmp); diff --git a/fs/smb/client/cifs_unicode.h b/fs/smb/client/cifs_unicode.h index e137a0dfbbe9..a4f0e05dd4bd 100644 --- a/fs/smb/client/cifs_unicode.h +++ b/fs/smb/client/cifs_unicode.h @@ -21,6 +21,7 @@ #include <asm/byteorder.h> #include <linux/types.h> #include <linux/nls.h> +#include <linux/unaligned.h> #include "../../nls/nls_ucs2_utils.h" /* @@ -73,4 +74,17 @@ extern __le16 *cifs_strndup_to_utf16(const char *src, const int maxlen, wchar_t cifs_toupper(wchar_t in); +static inline void cifs_set_utf16_path_delim(struct cifs_sb_info *cifs_sb, + __le16 *path) +{ + __u16 c; + + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) { + for (; (c = get_unaligned_le16(path)); path++) { + if (c == '/') + put_unaligned_le16('\\', path); + } + } +} + #endif /* _CIFS_UNICODE_H */ diff --git a/fs/smb/client/cifsacl.c b/fs/smb/client/cifsacl.c index 63b3b1290bed..cd2a83a35810 100644 --- a/fs/smb/client/cifsacl.c +++ b/fs/smb/client/cifsacl.c @@ -1743,19 +1743,13 @@ struct posix_acl *cifs_get_acl(struct mnt_idmap *idmap, /* return alt name if available as pseudo attr */ switch (type) { case ACL_TYPE_ACCESS: - if (sb->s_flags & SB_POSIXACL) - rc = cifs_do_get_acl(xid, pTcon, full_path, &acl, - ACL_TYPE_ACCESS, - cifs_sb->local_nls, - cifs_remap(cifs_sb)); - break; - case ACL_TYPE_DEFAULT: - if (sb->s_flags & SB_POSIXACL) - rc = cifs_do_get_acl(xid, pTcon, full_path, &acl, - ACL_TYPE_DEFAULT, - cifs_sb->local_nls, - cifs_remap(cifs_sb)); + if (sb->s_flags & SB_POSIXACL) { + rc = cifs_do_get_acl(xid, pTcon, full_path, + &acl, type, cifs_sb); + } + break; + default: break; } @@ -1820,19 +1814,13 @@ int cifs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, switch (type) { case ACL_TYPE_ACCESS: - if (sb->s_flags & SB_POSIXACL) - rc = cifs_do_set_acl(xid, pTcon, full_path, acl, - ACL_TYPE_ACCESS, - cifs_sb->local_nls, - cifs_remap(cifs_sb)); - break; - case ACL_TYPE_DEFAULT: - if (sb->s_flags & SB_POSIXACL) - rc = cifs_do_set_acl(xid, pTcon, full_path, acl, - ACL_TYPE_DEFAULT, - cifs_sb->local_nls, - cifs_remap(cifs_sb)); + if (sb->s_flags & SB_POSIXACL) { + rc = cifs_do_set_acl(xid, pTcon, full_path, + acl, type, cifs_sb); + } + break; + default: break; } diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index a08c42363ffc..1d426fc13701 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -527,23 +527,14 @@ cifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb) seq_puts(s, "loose"); } -/* - * cifs_show_devname() is used so we show the mount device name with correct - * format (e.g. forward slashes vs. back slashes) in /proc/mounts - */ static int cifs_show_devname(struct seq_file *m, struct dentry *root) { - struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb); - char *devname = kstrdup(cifs_sb->ctx->source, GFP_KERNEL); + const char *devname = CIFS_SB(root->d_sb)->ctx->source; - if (devname == NULL) + if (!devname) seq_puts(m, "none"); - else { - convert_delimiter(devname, '/'); - /* escape all spaces in share names */ + else seq_escape(m, devname, " \t"); - kfree(devname); - } return 0; } @@ -889,23 +880,22 @@ static const struct super_operations cifs_super_ops = { static struct dentry * cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb) { - struct dentry *dentry; + struct cifs_tcon *tcon = cifs_sb_master_tcon(CIFS_SB(sb)); struct cifs_sb_info *cifs_sb = CIFS_SB(sb); char *full_path = NULL; + struct dentry *dentry; + char sep = '/'; char *s, *p; - char sep; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) return dget(sb->s_root); - full_path = cifs_build_path_to_root(ctx, cifs_sb, - cifs_sb_master_tcon(cifs_sb), 0); + full_path = cifs_build_path_to_root(ctx, tcon, false); if (full_path == NULL) return ERR_PTR(-ENOMEM); cifs_dbg(FYI, "Get root dentry for %s\n", full_path); - sep = CIFS_DIR_SEP(cifs_sb); dentry = dget(sb->s_root); s = full_path; diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 07c4688ec4c9..734690e5d229 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -2367,4 +2367,29 @@ static inline bool cifs_netbios_name(const char *name, size_t namelen) return ret; } +/* + * Don't allow path components longer than the server max. + * The VFS will not allow "/", but "\" is allowed by posix & sfm mapping. + */ +static inline int cifs_check_name(struct dentry *dentry, struct cifs_tcon *tcon) +{ + unsigned int maxlen; + unsigned int flags; + int i; + + maxlen = le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength); + flags = CIFS_SB(dentry->d_sb)->mnt_cifs_flags; + + if (maxlen && unlikely(dentry->d_name.len > maxlen)) + return -ENAMETOOLONG; + + if (unlikely(!(flags & (CIFS_MOUNT_POSIX_PATHS | CIFS_MOUNT_MAP_SFM_CHR)))) { + for (i = 0; i < dentry->d_name.len; i++) { + if (dentry->d_name.name[i] == '\\') + return -EINVAL; + } + } + return 0; +} + #endif /* _CIFS_GLOB_H */ diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index cfcc07905bdf..fc17393e7812 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -77,10 +77,8 @@ static inline void free_dentry_path(void *page) __putname(page); } -extern char *cifs_build_path_to_root(struct smb3_fs_context *ctx, - struct cifs_sb_info *cifs_sb, - struct cifs_tcon *tcon, - int add_treename); +char *cifs_build_path_to_root(struct smb3_fs_context *ctx, + struct cifs_tcon *tcon, bool add_treename); extern char *build_wildcard_path_from_dentry(struct dentry *direntry); char *cifs_build_devname(char *nodename, const char *prepath); extern void delete_mid(struct mid_q_entry *mid); @@ -349,22 +347,19 @@ extern int CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, u16 netfid, FILE_ALL_INFO *pFindData); -extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, - const char *search_Name, FILE_ALL_INFO *data, - int legacy /* whether to use old info level */, - const struct nls_table *nls_codepage, int remap); +int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, FILE_ALL_INFO *data, + int legacy /* old style infolevel */, + struct cifs_sb_info *cifs_sb); extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, const char *search_name, FILE_ALL_INFO *data, - const struct nls_table *nls_codepage, int remap); - + struct cifs_sb_info *cifs_sb); extern int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, u16 netfid, FILE_UNIX_BASIC_INFO *pFindData); -extern int CIFSSMBUnixQPathInfo(const unsigned int xid, - struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_UNIX_BASIC_INFO *pFindData, - const struct nls_table *nls_codepage, int remap); - +int CIFSSMBUnixQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + const unsigned char *searchName, + FILE_UNIX_BASIC_INFO *pFindData, + struct cifs_sb_info *cifs_sb); extern int CIFSGetDFSRefer(const unsigned int xid, struct cifs_ses *ses, const char *search_name, struct dfs_info3_param **target_nodes, @@ -426,22 +421,19 @@ extern int CIFSSMBUnixSetFileInfo(const unsigned int xid, struct cifs_tcon *tcon, const struct cifs_unix_set_info_args *args, u16 fid, u32 pid_of_opener); - -extern int CIFSSMBUnixSetPathInfo(const unsigned int xid, - struct cifs_tcon *tcon, const char *file_name, - const struct cifs_unix_set_info_args *args, - const struct nls_table *nls_codepage, - int remap); - +int CIFSSMBUnixSetPathInfo(const unsigned int xid, struct cifs_tcon *tcon, + const char *file_name, + const struct cifs_unix_set_info_args *args, + struct cifs_sb_info *cifs_sb); extern int CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode, struct cifs_tcon *tcon, const char *name, struct cifs_sb_info *cifs_sb); extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, struct cifs_sb_info *cifs_sb); -extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, - const char *name, __u16 type, - const struct nls_table *nls_codepage, - int remap_special_chars); +int CIFSPOSIXDelFile(const unsigned int xid, + struct cifs_tcon *tcon, + const char *fileName, __u16 type, + struct cifs_sb_info *cifs_sb); extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name, struct cifs_sb_info *cifs_sb, struct dentry *dentry); @@ -449,28 +441,26 @@ int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, struct dentry *source_dentry, const char *from_name, const char *to_name, struct cifs_sb_info *cifs_sb); -extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon, - int netfid, const char *target_name, - const struct nls_table *nls_codepage, - int remap_special_chars); +int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon, + int netfid, const char *target_name, + struct cifs_sb_info *cifs_sb); int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, struct dentry *source_dentry, const char *from_name, const char *to_name, struct cifs_sb_info *cifs_sb); -extern int CIFSUnixCreateHardLink(const unsigned int xid, - struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, - int remap_special_chars); -extern int CIFSUnixCreateSymLink(const unsigned int xid, - struct cifs_tcon *tcon, - const char *fromName, const char *toName, - const struct nls_table *nls_codepage, int remap); -extern int CIFSSMBUnixQuerySymLink(const unsigned int xid, - struct cifs_tcon *tcon, - const unsigned char *searchName, char **syminfo, - const struct nls_table *nls_codepage, int remap); +int CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon, + const char *fromName, const char *toName, + struct cifs_sb_info *cifs_sb); +int CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, + const char *fromName, const char *toName, + struct cifs_sb_info *cifs_sb); +int CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, + const char *fromName, const char *toName, + struct cifs_sb_info *cifs_sb); +int CIFSSMBUnixQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, + const unsigned char *searchName, char **symlinkinfo, + struct cifs_sb_info *cifs_sb); extern int cifs_query_reparse_point(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, @@ -481,16 +471,15 @@ extern int CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid); extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, FILE_ALL_INFO *buf); -extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, - const char *fileName, const int disposition, - const int access_flags, const int omode, - __u16 *netfid, int *pOplock, FILE_ALL_INFO *, - const struct nls_table *nls_codepage, int remap); -extern int CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon, - u32 posix_flags, __u64 mode, __u16 *netfid, - FILE_UNIX_BASIC_INFO *pRetData, - __u32 *pOplock, const char *name, - const struct nls_table *nls_codepage, int remap); +int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, + const char *fileName, const int openDisposition, + const int access_flags, const int create_options, + __u16 *netfid, int *pOplock, FILE_ALL_INFO *pfile_info, + struct cifs_sb_info *cifs_sb); +int CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon, + __u32 posix_flags, __u64 mode, __u16 *netfid, + FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock, + const char *name, struct cifs_sb_info *cifs_sb); extern int CIFSSMBClose(const unsigned int xid, struct cifs_tcon *tcon, const int smb_file_id); @@ -504,11 +493,9 @@ extern int CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, const char *buf); extern int CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, struct kvec *iov, const int nvec); -extern int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon, - const char *search_name, __u64 *inode_number, - const struct nls_table *nls_codepage, - int remap); - +int CIFSGetSrvInodeNumber(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, __u64 *inode_number, + struct cifs_sb_info *cifs_sb); extern int cifs_lockv(const unsigned int xid, struct cifs_tcon *tcon, const __u16 netfid, const __u8 lock_type, const __u32 num_unlock, const __u32 num_lock, @@ -563,14 +550,12 @@ extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, struct smb_ntsd **acl_inf, __u32 *buflen, __u32 info); extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16, struct smb_ntsd *pntsd, __u32 len, int aclflag); -extern int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - struct posix_acl **acl, const int acl_type, - const struct nls_table *nls_codepage, int remap); -extern int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon, - const unsigned char *fileName, - const struct posix_acl *acl, const int acl_type, - const struct nls_table *nls_codepage, int remap); +int cifs_do_get_acl(const unsigned int xid, struct cifs_tcon *tcon, + const unsigned char *searchName, struct posix_acl **acl, + const int acl_type, struct cifs_sb_info *cifs_sb); +int cifs_do_set_acl(const unsigned int xid, struct cifs_tcon *tcon, + const unsigned char *fileName, const struct posix_acl *acl, + const int acl_type, struct cifs_sb_info *cifs_sb); extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, const int netfid, __u64 *pExtAttrBits, __u64 *pMask); #endif /* CIFS_ALLOW_INSECURE_LEGACY */ diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 60cb264a01e5..b1abc86e0a57 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -678,10 +678,30 @@ session_already_dead: return rc; } -int -CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon, - const char *fileName, __u16 type, - const struct nls_table *nls_codepage, int remap) +static int copy_cifs_path(__le16 flags2, void *dst, const void *src, + struct cifs_sb_info *cifs_sb) +{ + int len; + + if (likely(flags2 & SMBFLG2_UNICODE)) { + len = cifsConvertToUTF16(dst, src, PATH_MAX, + cifs_sb->local_nls, + cifs_remap(cifs_sb)); + cifs_set_utf16_path_delim(cifs_sb, dst); + /* include trailing null */ + return (len + 1) * sizeof(__le16); + } + + len = copy_path_name(dst, src); + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) + convert_delimiter(dst, '\\'); + return len; +} + +int CIFSPOSIXDelFile(const unsigned int xid, + struct cifs_tcon *tcon, + const char *fileName, __u16 type, + struct cifs_sb_info *cifs_sb) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -698,16 +718,8 @@ PsxDelete: if (rc) return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { - name_len = copy_path_name(pSMB->FileName, fileName); - } - + name_len = copy_cifs_path(pSMB->hdr.Flags2, pSMB->FileName, + fileName, cifs_sb); params = 6 + name_len; pSMB->MaxParameterCount = cpu_to_le16(2); pSMB->MaxDataCount = 0; /* BB double check this with jra */ @@ -764,7 +776,6 @@ CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon, const char *name, int rc = 0; int bytes_returned; int name_len; - int remap = cifs_remap(cifs_sb); DelFileRetry: rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB, @@ -772,15 +783,8 @@ DelFileRetry: if (rc) return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->fileName, name, - PATH_MAX, cifs_sb->local_nls, - remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { - name_len = copy_path_name(pSMB->fileName, name); - } + name_len = copy_cifs_path(pSMB->hdr.Flags2, pSMB->fileName, + name, cifs_sb); pSMB->SearchAttributes = cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM); pSMB->BufferFormat = 0x04; @@ -808,7 +812,6 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, int rc = 0; int bytes_returned; int name_len; - int remap = cifs_remap(cifs_sb); cifs_dbg(FYI, "In CIFSSMBRmDir\n"); RmDirRetry: @@ -817,16 +820,8 @@ RmDirRetry: if (rc) return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, - PATH_MAX, cifs_sb->local_nls, - remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { - name_len = copy_path_name(pSMB->DirName, name); - } - + name_len = copy_cifs_path(pSMB->hdr.Flags2, pSMB->DirName, + name, cifs_sb); pSMB->BufferFormat = 0x04; inc_rfc1001_len(pSMB, name_len + 1); pSMB->ByteCount = cpu_to_le16(name_len + 1); @@ -852,7 +847,6 @@ CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode, CREATE_DIRECTORY_RSP *pSMBr = NULL; int bytes_returned; int name_len; - int remap = cifs_remap(cifs_sb); cifs_dbg(FYI, "In CIFSSMBMkDir\n"); MkDirRetry: @@ -861,16 +855,8 @@ MkDirRetry: if (rc) return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, - PATH_MAX, cifs_sb->local_nls, - remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { - name_len = copy_path_name(pSMB->DirName, name); - } - + name_len = copy_cifs_path(pSMB->hdr.Flags2, pSMB->DirName, + name, cifs_sb); pSMB->BufferFormat = 0x04; inc_rfc1001_len(pSMB, name_len + 1); pSMB->ByteCount = cpu_to_le16(name_len + 1); @@ -886,12 +872,10 @@ MkDirRetry: return rc; } -int -CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon, - __u32 posix_flags, __u64 mode, __u16 *netfid, - FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock, - const char *name, const struct nls_table *nls_codepage, - int remap) +int CIFSPOSIXCreate(const unsigned int xid, struct cifs_tcon *tcon, + __u32 posix_flags, __u64 mode, __u16 *netfid, + FILE_UNIX_BASIC_INFO *pRetData, __u32 *pOplock, + const char *name, struct cifs_sb_info *cifs_sb) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -909,16 +893,8 @@ PsxCreat: if (rc) return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, name, - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { - name_len = copy_path_name(pSMB->FileName, name); - } - + name_len = copy_cifs_path(pSMB->hdr.Flags2, pSMB->FileName, + name, cifs_sb); params = 6 + name_len; count = sizeof(OPEN_PSX_REQ); pSMB->MaxParameterCount = cpu_to_le16(2); @@ -1070,10 +1046,10 @@ access_flags_to_smbopen_mode(const int access_flags) int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, - const char *fileName, const int openDisposition, - const int access_flags, const int create_options, __u16 *netfid, - int *pOplock, FILE_ALL_INFO *pfile_info, - const struct nls_table *nls_codepage, int remap) + const char *fileName, const int openDisposition, + const int access_flags, const int create_options, + __u16 *netfid, int *pOplock, FILE_ALL_INFO *pfile_info, + struct cifs_sb_info *cifs_sb) { int rc; OPENX_REQ *pSMB = NULL; @@ -1090,17 +1066,10 @@ OldOpenRetry: pSMB->AndXCommand = 0xFF; /* none */ - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - count = 1; /* account for one byte pad to word boundary */ - name_len = - cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), - fileName, PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - } else { - count = 0; /* no pad */ - name_len = copy_path_name(pSMB->fileName, fileName); - } + name_len = copy_cifs_path(pSMB->hdr.Flags2, &pSMB->fileName[1], + fileName, cifs_sb); + count = !!(pSMB->hdr.Flags2 & SMBFLG2_UNICODE); + if (*pOplock & REQ_OPLOCK) pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK); else if (*pOplock & REQ_BATCHOPLOCK) @@ -1176,20 +1145,18 @@ int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock, FILE_ALL_INFO *buf) { - int rc; - OPEN_REQ *req = NULL; - OPEN_RSP *rsp = NULL; - int bytes_returned; - int name_len; - __u16 count; struct cifs_sb_info *cifs_sb = oparms->cifs_sb; - struct cifs_tcon *tcon = oparms->tcon; - int remap = cifs_remap(cifs_sb); - const struct nls_table *nls = cifs_sb->local_nls; int create_options = oparms->create_options; int desired_access = oparms->desired_access; int disposition = oparms->disposition; + struct cifs_tcon *tcon = oparms->tcon; const char *path = oparms->path; + OPEN_REQ *req = NULL; + OPEN_RSP *rsp = NULL; + int bytes_returned; + int name_len; + __u16 count; + int rc; openRetry: rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req, @@ -1200,22 +1167,10 @@ openRetry: /* no commands go after this */ req->AndXCommand = 0xFF; - if (req->hdr.Flags2 & SMBFLG2_UNICODE) { - /* account for one byte pad to word boundary */ - count = 1; - name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1), - path, PATH_MAX, nls, remap); - /* trailing null */ - name_len++; - name_len *= 2; - req->NameLength = cpu_to_le16(name_len); - } else { - /* BB improve check for buffer overruns BB */ - /* no pad */ - count = 0; - name_len = copy_path_name(req->fileName, path); - req->NameLength = cpu_to_le16(name_len); - } + count = !!(req->hdr.Flags2 & SMBFLG2_UNICODE); + name_len = copy_cifs_path(req->hdr.Flags2, &req->fileName[count], + path, cifs_sb); + req->NameLength = cpu_to_le16(name_len); if (*oplock & REQ_OPLOCK) req->OpenFlags = cpu_to_le32(REQ_OPLOCK); @@ -2229,13 +2184,13 @@ int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon, const char *from_name, const char *to_name, struct cifs_sb_info *cifs_sb) { - int rc = 0; - RENAME_REQ *pSMB = NULL; RENAME_RSP *pSMBr = NULL; - int bytes_returned; + RENAME_REQ *pSMB = NULL; int name_len, name_len2; + const __u8 pad = 0x4; + int bytes_returned; __u16 count; - int remap = cifs_remap(cifs_sb); + int rc = 0; cifs_dbg(FYI, "In CIFSSMBRename\n"); renameRetry: @@ -2244,31 +2199,23 @@ renameRetry: if (rc) return rc; - pSMB->BufferFormat = 0x04; + pSMB->BufferFormat = pad; pSMB->SearchAttributes = cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); + name_len = copy_cifs_path(pSMB->hdr.Flags2, pSMB->OldFileName, + from_name, cifs_sb); + pSMB->OldFileName[name_len] = pad; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName, - from_name, PATH_MAX, - cifs_sb->local_nls, remap); - name_len++; /* trailing null */ - name_len *= 2; - pSMB->OldFileName[name_len] = 0x04; /* pad */ - /* protocol requires ASCII signature byte on Unicode string */ - pSMB->OldFileName[name_len + 1] = 0x00; - name_len2 = - cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], - to_name, PATH_MAX, cifs_sb->local_nls, - remap); - name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; - name_len2 *= 2; /* convert to bytes */ + pSMB->OldFileName[name_len + 1] = 0; + name_len2 = copy_cifs_path(pSMB->hdr.Flags2, + &pSMB->OldFileName[name_len + 2], + to_name, cifs_sb) + sizeof(__le16); } else { - name_len = copy_path_name(pSMB->OldFileName, from_name); - name_len2 = copy_path_name(pSMB->OldFileName+name_len+1, to_name); - pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */ - name_len2++; /* signature byte */ + name_len2 = copy_cifs_path(pSMB->hdr.Flags2, + &pSMB->OldFileName[name_len + 1], + to_name, cifs_sb) + sizeof(__u8); } count = 1 /* 1st signature byte */ + name_len + name_len2; @@ -2290,8 +2237,8 @@ renameRetry: } int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon, - int netfid, const char *target_name, - const struct nls_table *nls_codepage, int remap) + int netfid, const char *target_name, + struct cifs_sb_info *cifs_sb) { struct smb_com_transaction2_sfi_req *pSMB = NULL; struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; @@ -2337,14 +2284,14 @@ int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon, /* unicode only call */ if (target_name == NULL) { sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid); - len_of_str = - cifsConvertToUTF16((__le16 *)rename_info->target_name, - dummy_string, 24, nls_codepage, remap); + len_of_str = cifsConvertToUTF16((__le16 *)rename_info->target_name, + dummy_string, 24, cifs_sb->local_nls, + cifs_remap(cifs_sb)); } else { - len_of_str = - cifsConvertToUTF16((__le16 *)rename_info->target_name, - target_name, PATH_MAX, nls_codepage, - remap); + len_of_str = cifsConvertToUTF16((__le16 *)rename_info->target_name, + target_name, PATH_MAX, cifs_sb->local_nls, + cifs_remap(cifs_sb)); + cifs_set_utf16_path_delim(cifs_sb, (__le16 *)rename_info->target_name); } rename_info->target_name_len = cpu_to_le32(2 * len_of_str); count = sizeof(struct set_file_rename) + (2 * len_of_str); @@ -2375,7 +2322,7 @@ int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *pTcon, int CIFSUnixCreateSymLink(const unsigned int xid, struct cifs_tcon *tcon, const char *fromName, const char *toName, - const struct nls_table *nls_codepage, int remap) + struct cifs_sb_info *cifs_sb) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -2393,17 +2340,8 @@ createSymLinkRetry: if (rc) return rc; - if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fromName, - /* find define for this maxpathcomponent */ - PATH_MAX, nls_codepage, remap); - name_len++; /* trailing null */ - name_len *= 2; - - } else { - name_len = copy_path_name(pSMB->FileName, fromName); - } + name_len = copy_cifs_path(pSMB->hdr.Flags2, pSMB->FileName, + fromName, cifs_sb); params = 6 + name_len; pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; @@ -2416,17 +2354,8 @@ createSymLinkRetry: /* SMB offsets are from the beginning of SMB which is 4 bytes in, a |