summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2025-04-01 01:13:49 -0300
committerSteve French <stfrench@microsoft.com>2025-04-07 01:08:27 -0500
commit3d48316df903a48a533bb313e5da821a163738cd (patch)
treedd79845c8866574c00667ffda329282ae40b77c0
parentb365b9d404b7376c60c91cd079218bfef11b7822 (diff)
downloadlinux-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.c3
-rw-r--r--fs/smb/client/cifs_unicode.c22
-rw-r--r--fs/smb/client/cifs_unicode.h14
-rw-r--r--fs/smb/client/cifsacl.c36
-rw-r--r--fs/smb/client/cifsfs.c24
-rw-r--r--fs/smb/client/cifsglob.h25
-rw-r--r--fs/smb/client/cifsproto.h119
-rw-r--r--fs/smb/client/cifssmb.c570
-rw-r--r--fs/smb/client/connect.c24
-rw-r--r--fs/smb/client/dir.c74
-rw-r--r--fs/smb/client/file.c3
-rw-r--r--fs/smb/client/fs_context.c3
-rw-r--r--fs/smb/client/inode.c39
-rw-r--r--fs/smb/client/link.c9
-rw-r--r--fs/smb/client/misc.c2
-rw-r--r--fs/smb/client/namespace.c1
-rw-r--r--fs/smb/client/smb1ops.c37
-rw-r--r--fs/smb/client/smb2misc.c30
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