提交 5cf11daf 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: (21 commits)
  [CIFS] Remove debug statement
  Fix possible access to undefined memory region.
  [CIFS] Enable DFS support for Windows query path info
  [CIFS] Enable DFS support for Unix query path info
  [CIFS] add missing seq_printf to cifs_show_options for hard mount option
  [CIFS] add more complete mount options to cifs_show_options
  [CIFS] Add missing defines for DFS
  CIFSGetDFSRefer cleanup + dfs_referral_level_3 fixed to conform REFERRAL_V3 the MS-DFSC spec.
  Fixed DFS code to work with new 'build_path_from_dentry', that returns full path if share in the dfs, now.
  [CIFS] enable parsing for transport encryption mount parm
  [CIFS] Finishup DFS code
  [CIFS] BKL-removal: convert CIFS over to unlocked_ioctl
  [CIFS] suppress duplicate warning
  [CIFS] Fix paths when share is in DFS to include proper prefix
  add function to convert access flags to legacy open mode
  clarify return value of cifs_convert_flags()
  [CIFS] don't explicitly do a FindClose on rewind when directory search has ended
  [CIFS] cleanup old checkpatch warnings
  [CIFS] CIFSSMBPosixLock should return -EINVAL on error
  fix memory leak in CIFSFindNext
  ...
......@@ -36,6 +36,7 @@ Miklos Szeredi
Kazeon team for various fixes especially for 2.4 version.
Asser Ferno (Change Notify support)
Shaggy (Dave Kleikamp) for inumerable small fs suggestions and some good cleanup
Igor Mammedov (DFS support)
Test case and Bug Report contributors
-------------------------------------
......
Version 1.53
------------
DFS support added (Microsoft Distributed File System client support needed
for referrals which enable a hierarchical name space among servers).
Version 1.52
------------
......@@ -12,7 +14,8 @@ Add ability to modify cifs acls for handling chmod (when mounted with
cifsacl flag). Fix prefixpath path separator so we can handle mounts
with prefixpaths longer than one directory (one path component) when
mounted to Windows servers. Fix slow file open when cifsacl
enabled.
enabled. Fix memory leak in FindNext when the SMB call returns -EBADF.
Version 1.51
------------
......
......@@ -483,6 +483,11 @@ A partial list of the supported mount options follows:
sign Must use packet signing (helps avoid unwanted data modification
by intermediate systems in the route). Note that signing
does not work with lanman or plaintext authentication.
seal Must seal (encrypt) all data on this mounted share before
sending on the network. Requires support for Unix Extensions.
Note that this differs from the sign mount option in that it
causes encryption of data sent over this mounted share but other
shares mounted to the same server are unaffected.
sec Security mode. Allowed values are:
none attempt to connection as a null user (no name)
krb5 Use Kerberos version 5 authentication
......
Version 1.52 January 3, 2008
Version 1.53 May 20, 2008
A Partial List of Missing Features
==================================
......@@ -20,20 +20,21 @@ d) Cleanup now unneeded SessSetup code in
fs/cifs/connect.c and add back in NTLMSSP code if any servers
need it
e) ms-dfs and ms-dfs host name resolution cleanup
f) fix NTLMv2 signing when two mounts with different users to same
e) fix NTLMv2 signing when two mounts with different users to same
server.
g) Directory entry caching relies on a 1 second timer, rather than
f) Directory entry caching relies on a 1 second timer, rather than
using FindNotify or equivalent. - (started)
h) quota support (needs minor kernel change since quota calls
g) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems)
i) investigate sync behavior (including syncpage) and check
h) investigate sync behavior (including syncpage) and check
for proper behavior of intr/nointr
i) improve support for very old servers (OS/2 and Win9x for example)
Including support for changing the time remotely (utimes command).
j) hook lower into the sockets api (as NFS/SunRPC does) to avoid the
extra copy in/out of the socket buffers in some cases.
......
......@@ -219,53 +219,6 @@ static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent,
}
static char *build_full_dfs_path_from_dentry(struct dentry *dentry)
{
char *full_path = NULL;
char *search_path;
char *tmp_path;
size_t l_max_len;
struct cifs_sb_info *cifs_sb;
if (dentry->d_inode == NULL)
return NULL;
cifs_sb = CIFS_SB(dentry->d_inode->i_sb);
if (cifs_sb->tcon == NULL)
return NULL;
search_path = build_path_from_dentry(dentry);
if (search_path == NULL)
return NULL;
if (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS) {
int i;
/* we should use full path name for correct working with DFS */
l_max_len = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE+1) +
strnlen(search_path, MAX_PATHCONF) + 1;
tmp_path = kmalloc(l_max_len, GFP_KERNEL);
if (tmp_path == NULL) {
kfree(search_path);
return NULL;
}
strncpy(tmp_path, cifs_sb->tcon->treeName, l_max_len);
tmp_path[l_max_len-1] = 0;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
for (i = 0; i < l_max_len; i++) {
if (tmp_path[i] == '\\')
tmp_path[i] = '/';
}
strncat(tmp_path, search_path, l_max_len - strlen(tmp_path));
full_path = tmp_path;
kfree(search_path);
} else {
full_path = search_path;
}
return full_path;
}
static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd,
struct list_head *mntlist)
{
......@@ -333,7 +286,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
goto out_err;
}
full_path = build_full_dfs_path_from_dentry(dentry);
full_path = build_path_from_dentry(dentry);
if (full_path == NULL) {
rc = -ENOMEM;
goto out_err;
......
......@@ -30,6 +30,7 @@
#define CIFS_MOUNT_CIFS_ACL 0x200 /* send ACL requests to non-POSIX srv */
#define CIFS_MOUNT_OVERR_UID 0x400 /* override uid returned from server */
#define CIFS_MOUNT_OVERR_GID 0x800 /* override gid returned from server */
#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
......
/*
* fs/cifs/cifsfs.c
*
* Copyright (C) International Business Machines Corp., 2002,2007
* Copyright (C) International Business Machines Corp., 2002,2008
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Common Internet FileSystem (CIFS) client
......@@ -353,9 +353,41 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
!(cifs_sb->tcon->unix_ext))
seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
if (!cifs_sb->tcon->unix_ext) {
seq_printf(s, ",file_mode=0%o,dir_mode=0%o",
cifs_sb->mnt_file_mode,
cifs_sb->mnt_dir_mode);
}
if (cifs_sb->tcon->seal)
seq_printf(s, ",seal");
if (cifs_sb->tcon->nocase)
seq_printf(s, ",nocase");
if (cifs_sb->tcon->retry)
seq_printf(s, ",hard");
}
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
seq_printf(s, ",posixpaths");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
seq_printf(s, ",setuids");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
seq_printf(s, ",serverino");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
seq_printf(s, ",directio");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
seq_printf(s, ",nouser_xattr");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
seq_printf(s, ",mapchars");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)
seq_printf(s, ",sfu");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
seq_printf(s, ",nobrl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL)
seq_printf(s, ",cifsacl");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
seq_printf(s, ",dynperm");
if (m->mnt_sb->s_flags & MS_POSIXACL)
seq_printf(s, ",acl");
seq_printf(s, ",rsize=%d", cifs_sb->rsize);
seq_printf(s, ",wsize=%d", cifs_sb->wsize);
}
......@@ -657,7 +689,7 @@ const struct file_operations cifs_file_ops = {
.splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
#ifdef CONFIG_CIFS_EXPERIMENTAL
......@@ -677,7 +709,7 @@ const struct file_operations cifs_file_direct_ops = {
.flush = cifs_flush,
.splice_read = generic_file_splice_read,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_EXPERIMENTAL
......@@ -697,7 +729,7 @@ const struct file_operations cifs_file_nobrl_ops = {
.splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
#ifdef CONFIG_CIFS_EXPERIMENTAL
......@@ -716,7 +748,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
.flush = cifs_flush,
.splice_read = generic_file_splice_read,
#ifdef CONFIG_CIFS_POSIX
.ioctl = cifs_ioctl,
.unlocked_ioctl = cifs_ioctl,
#endif /* CONFIG_CIFS_POSIX */
.llseek = cifs_llseek,
#ifdef CONFIG_CIFS_EXPERIMENTAL
......@@ -731,7 +763,7 @@ const struct file_operations cifs_dir_ops = {
#ifdef CONFIG_CIFS_EXPERIMENTAL
.dir_notify = cifs_dir_notify,
#endif /* CONFIG_CIFS_EXPERIMENTAL */
.ioctl = cifs_ioctl,
.unlocked_ioctl = cifs_ioctl,
};
static void
......
......@@ -95,8 +95,7 @@ extern int cifs_setxattr(struct dentry *, const char *, const void *,
size_t, int);
extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl(struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg);
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern const struct export_operations cifs_export_ops;
......
......@@ -281,6 +281,7 @@ struct cifsTconInfo {
bool ipc:1; /* set if connection to IPC$ eg for RPC/PIPES */
bool retry:1;
bool nocase:1;
bool seal:1; /* transport encryption for this mounted share */
bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
for this mount even if server would support */
/* BB add field for back pointer to sb struct(s)? */
......
......@@ -1904,19 +1904,26 @@ typedef struct smb_com_transaction2_get_dfs_refer_req {
char RequestFileName[1];
} __attribute__((packed)) TRANSACTION2_GET_DFS_REFER_REQ;
#define DFS_VERSION cpu_to_le16(0x0003)
/* DFS server target type */
#define DFS_TYPE_LINK 0x0000 /* also for sysvol targets */
#define DFS_TYPE_ROOT 0x0001
/* Referral Entry Flags */
#define DFS_NAME_LIST_REF 0x0200
typedef struct dfs_referral_level_3 {
__le16 VersionNumber;
__le16 ReferralSize;
__le16 ServerType; /* 0x0001 = CIFS server */
__le16 ReferralFlags; /* or proximity - not clear which since it is
always set to zero - SNIA spec says 0x01
means strip off PathConsumed chars before
submitting RequestFileName to remote node */
__le16 TimeToLive;
__le16 Proximity;
__le16 Size;
__le16 ServerType; /* 0x0001 = root targets; 0x0000 = link targets */
__le16 ReferralEntryFlags; /* 0x0200 bit set only for domain
or DC referral responce */
__le32 TimeToLive;
__le16 DfsPathOffset;
__le16 DfsAlternatePathOffset;
__le16 NetworkAddressOffset;
__le16 NetworkAddressOffset; /* offset of the link target */
__le16 ServiceSiteGuid;
} __attribute__((packed)) REFERRAL3;
typedef struct smb_com_transaction_get_dfs_refer_rsp {
......
......@@ -93,7 +93,7 @@ extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path,
FILE_ALL_INFO * pfile_info,
FILE_ALL_INFO *pfile_info,
struct super_block *sb, int xid, const __u16 *pfid);
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
......@@ -130,7 +130,7 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon,
extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_ALL_INFO * findData,
FILE_ALL_INFO *findData,
int legacy /* whether to use old info level */,
const struct nls_table *nls_codepage, int remap);
extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
......@@ -141,18 +141,15 @@ extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
extern int CIFSSMBUnixQPathInfo(const int xid,
struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_UNIX_BASIC_INFO * pFindData,
FILE_UNIX_BASIC_INFO *pFindData,
const struct nls_table *nls_codepage, int remap);
extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
const unsigned char *searchName,
unsigned char **targetUNCs,
unsigned int *number_of_UNC_in_array,
struct dfs_info3_param **target_nodes,
unsigned int *number_of_nodes_in_array,
const struct nls_table *nls_codepage, int remap);
extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path,
const struct nls_table *nls_codepage, int remap);
extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path,
const struct nls_table *nls_codepage,
......
......@@ -81,6 +81,40 @@ static struct {
#endif /* CONFIG_CIFS_WEAK_PW_HASH */
#endif /* CIFS_POSIX */
/* Allocates buffer into dst and copies smb string from src to it.
* caller is responsible for freeing dst if function returned 0.
* returns:
* on success - 0
* on failure - errno
*/
static int
cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
const bool is_unicode, const struct nls_table *nls_codepage)
{
int plen;
if (is_unicode) {
plen = UniStrnlen((wchar_t *)src, maxlen);
*dst = kmalloc(plen + 2, GFP_KERNEL);
if (!*dst)
goto cifs_strncpy_to_host_ErrExit;
cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
} else {
plen = strnlen(src, maxlen);
*dst = kmalloc(plen + 2, GFP_KERNEL);
if (!*dst)
goto cifs_strncpy_to_host_ErrExit;
strncpy(*dst, src, plen);
}
(*dst)[plen] = 0;
(*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
return 0;
cifs_strncpy_to_host_ErrExit:
cERROR(1, ("Failed to allocate buffer for string\n"));
return -ENOMEM;
}
/* Mark as invalid, all open files on tree connections since they
were closed when session to server was lost */
......@@ -1166,6 +1200,20 @@ static __u16 convert_disposition(int disposition)
return ofun;
}
static int
access_flags_to_smbopen_mode(const int access_flags)
{
int masked_flags = access_flags & (GENERIC_READ | GENERIC_WRITE);
if (masked_flags == GENERIC_READ)
return SMBOPEN_READ;
else if (masked_flags == GENERIC_WRITE)
return SMBOPEN_WRITE;
/* just go for read/write */
return SMBOPEN_READWRITE;
}
int
SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
const char *fileName, const int openDisposition,
......@@ -1207,13 +1255,7 @@ SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
/* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
/* 0 = read
1 = write
2 = rw
3 = execute
*/
pSMB->Mode = cpu_to_le16(2);
pSMB->Mode = cpu_to_le16(access_flags_to_smbopen_mode(access_flags));
pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
/* set file as system file if special file such
as fifo and server expecting SFU style and
......@@ -1247,7 +1289,7 @@ SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
} else {
/* BB verify if wct == 15 */
/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field BB */
/* *pOplock = pSMBr->OplockLevel; */ /* BB take from action field*/
*netfid = pSMBr->Fid; /* cifs fid stays in le */
/* Let caller know file was created so we can set the mode. */
......@@ -1767,7 +1809,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
cFYI(1, ("Posix Lock"));
if (pLockData == NULL)
return EINVAL;
return -EINVAL;
rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
......@@ -1944,7 +1986,7 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 =
cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
......@@ -2925,7 +2967,8 @@ CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
}
params = 6 + name_len;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
/* BB find max SMB size from sess */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -3322,7 +3365,8 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -3388,7 +3432,7 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
int
CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_UNIX_BASIC_INFO * pFindData,
FILE_UNIX_BASIC_INFO *pFindData,
const struct nls_table *nls_codepage, int remap)
{
/* SMB_QUERY_FILE_UNIX_BASIC */
......@@ -3679,6 +3723,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
if (rc) {
if (rc == -EBADF) {
psrch_inf->endOfSearch = true;
cifs_buf_release(pSMB);
rc = 0; /* search probably was closed at end of search*/
} else
cFYI(1, ("FindNext returned = %d", rc));
......@@ -3856,25 +3901,112 @@ CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
return rc;
}
/* parses DFS refferal V3 structure
* caller is responsible for freeing target_nodes
* returns:
* on success - 0
* on failure - errno
*/
static int
parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr,
unsigned int *num_of_nodes,
struct dfs_info3_param **target_nodes,
const struct nls_table *nls_codepage)
{
int i, rc = 0;
char *data_end;
bool is_unicode;
struct dfs_referral_level_3 *ref;
is_unicode = pSMBr->hdr.Flags2 & SMBFLG2_UNICODE;
*num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals);
if (*num_of_nodes < 1) {
cERROR(1, ("num_referrals: must be at least > 0,"
"but we get num_referrals = %d\n", *num_of_nodes));
rc = -EINVAL;
goto parse_DFS_referrals_exit;
}
ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals);
if (ref->VersionNumber != 3) {
cERROR(1, ("Referrals of V%d version are not supported,"
"should be V3", ref->VersionNumber));
rc = -EINVAL;
goto parse_DFS_referrals_exit;
}
/* get the upper boundary of the resp buffer */
data_end = (char *)(&(pSMBr->PathConsumed)) +
le16_to_cpu(pSMBr->t2.DataCount);
cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
*num_of_nodes,
le16_to_cpu(pSMBr->DFSFlags)));
*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
*num_of_nodes, GFP_KERNEL);
if (*target_nodes == NULL) {
cERROR(1, ("Failed to allocate buffer for target_nodes\n"));
rc = -ENOMEM;
goto parse_DFS_referrals_exit;
}
/* collect neccessary data from referrals */
for (i = 0; i < *num_of_nodes; i++) {
char *temp;
int max_len;
struct dfs_info3_param *node = (*target_nodes)+i;
node->flags = le16_to_cpu(pSMBr->DFSFlags);
node->path_consumed = le16_to_cpu(pSMBr->PathConsumed);
node->server_type = le16_to_cpu(ref->ServerType);
node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
/* copy DfsPath */
temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
max_len = data_end - temp;
rc = cifs_strncpy_to_host(&(node->path_name), temp,
max_len, is_unicode, nls_codepage);
if (rc)
goto parse_DFS_referrals_exit;
/* copy link target UNC */
temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
max_len = data_end - temp;
rc = cifs_strncpy_to_host(&(node->node_name), temp,
max_len, is_unicode, nls_codepage);
if (rc)
goto parse_DFS_referrals_exit;
ref += ref->Size;
}
parse_DFS_referrals_exit:
if (rc) {
free_dfs_info_array(*target_nodes, *num_of_nodes);
*target_nodes = NULL;
*num_of_nodes = 0;
}
return rc;
}
int
CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
const unsigned char *searchName,
unsigned char **targetUNCs,
unsigned int *number_of_UNC_in_array,
struct dfs_info3_param **target_nodes,
unsigned int *num_of_nodes,
const struct nls_table *nls_codepage, int remap)
{
/* TRANS2_GET_DFS_REFERRAL */
TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
struct dfs_referral_level_3 *referrals = NULL;
int rc = 0;
int bytes_returned;
int name_len;
unsigned int i;
char *temp;
__u16 params, byte_count;
*number_of_UNC_in_array = 0;
*targetUNCs = NULL;
*num_of_nodes = 0;
*target_nodes = NULL;
cFYI(1, ("In GetDFSRefer the path %s", searchName));
if (ses == NULL)
......@@ -3921,7 +4053,8 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->MaxParameterCount = 0;
pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -3943,100 +4076,24 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) {
cFYI(1, ("Send error in GetDFSRefer = %d", rc));
} else { /* decode response */
/* BB Add logic to parse referrals here */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
goto GetDFSRefExit;
}
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
/* BB Also check if enough total bytes returned? */
if (rc || (pSMBr->ByteCount < 17))
rc = -EIO; /* bad smb */
else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
__u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
/* BB Also check if enough total bytes returned? */
if (rc || (pSMBr->ByteCount < 17)) {
rc = -EIO; /* bad smb */
goto GetDFSRefExit;
}
cFYI(1,
("Decoding GetDFSRefer response BCC: %d Offset %d",
pSMBr->ByteCount, data_offset));
referrals =
(struct dfs_referral_level_3 *)
(8 /* sizeof start of data block */ +
data_offset +
(char *) &pSMBr->hdr.Protocol);
cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n"
"for referral one refer size: 0x%x srv "
"type: 0x%x refer flags: 0x%x ttl: 0x%x",
le16_to_cpu(pSMBr->NumberOfReferrals),
le16_to_cpu(pSMBr->DFSFlags),
le16_to_cpu(referrals->ReferralSize),
le16_to_cpu(referrals->ServerType),
le16_to_cpu(referrals->ReferralFlags),
le16_to_cpu(referrals->TimeToLive)));
/* BB This field is actually two bytes in from start of
data block so we could do safety check that DataBlock
begins at address of pSMBr->NumberOfReferrals */
*number_of_UNC_in_array =
le16_to_cpu(pSMBr->NumberOfReferrals);
/* BB Fix below so can return more than one referral */
if (*number_of_UNC_in_array > 1)
*number_of_UNC_in_array = 1;
/* get the length of the strings describing refs */
name_len = 0;
for (i = 0; i < *number_of_UNC_in_array; i++) {
/* make sure that DfsPathOffset not past end */
__u16 offset =
le16_to_cpu(referrals->DfsPathOffset);
if (offset > data_count) {
/* if invalid referral, stop here and do
not try to copy any more */
*number_of_UNC_in_array = i;
break;
}
temp = ((char *)referrals) + offset;
cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
pSMBr->ByteCount,
le16_to_cpu(pSMBr->t2.DataOffset)));
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len += UniStrnlen((wchar_t *)temp,
data_count);
} else {
name_len += strnlen(temp, data_count);
}
referrals++;
/* BB add check that referral pointer does
not fall off end PDU */
}
/* BB add check for name_len bigger than bcc */
*targetUNCs =
kmalloc(name_len+1+(*number_of_UNC_in_array),
GFP_KERNEL);
if (*targetUNCs == NULL) {
rc = -ENOMEM;
goto GetDFSRefExit;
}
/* copy the ref strings */
referrals = (struct dfs_referral_level_3 *)
(8 /* sizeof data hdr */ + data_offset +
(char *) &pSMBr->hdr.Protocol);
for (i = 0; i < *number_of_UNC_in_array; i++) {
temp = ((char *)referrals) +
le16_to_cpu(referrals->DfsPathOffset);
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
cifs_strfromUCS_le(*targetUNCs,
(__le16 *) temp,
name_len,
nls_codepage);
} else {
strncpy(*targetUNCs, temp, name_len);
}
/* BB update target_uncs pointers */
referrals++;
}
temp = *targetUNCs;
temp[name_len] = 0;
}
/* parse returned result into more usable form */
rc = parse_DFS_referrals(pSMBr, num_of_nodes,
target_nodes, nls_codepage);
}
GetDFSRefExit:
if (pSMB)
cifs_buf_release(pSMB);
......@@ -4229,7 +4286,8 @@ CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
params = 2; /* level */
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -4298,7 +4356,8 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
params = 2; /* level */
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -4369,7 +4428,8 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(100);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -4444,7 +4504,8 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
offset = param_offset + params;
pSMB->MaxParameterCount = cpu_to_le16(4);
pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(100);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
......@@ -4512,7 +4573,8 @@ CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
pSMB->DataCount = 0;
pSMB->DataOffset = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(100);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -4702,7 +4764,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
count = sizeof(struct file_end_of_file_info);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
......@@ -4789,7 +4852,8 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon,
count = sizeof(FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
/* BB find max SMB PDU from sess */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->SetupCount = 1;
pSMB->Reserved3 = 0;
pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
......@@ -4856,7 +4920,8 @@ CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
params = 6 + name_len;
count = sizeof(FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -4986,7 +5051,8 @@ CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
params = 6 + name_len;
count = sizeof(FILE_UNIX_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -5169,7 +5235,8 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -5317,7 +5384,8 @@ ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon,
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
pSMB->TotalDataCount = 0;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
/* BB find exact max SMB PDU from sess structure BB */
pSMB->MaxDataCount = cpu_to_le16(4000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......@@ -5475,7 +5543,8 @@ CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
count = sizeof(*parm_data) + ea_value_len + name_len;
pSMB->MaxParameterCount = cpu_to_le16(2);
pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
/* BB find max SMB PDU from sess */
pSMB->MaxDataCount = cpu_to_le16(1000);
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
pSMB->Flags = 0;
......
......@@ -60,7 +60,7 @@ struct smb_vol {
char *domainname;
char *UNC;
char *UNCip;
char *in6_addr; /* ipv6 address as human readable form of in6_addr */
char *in6_addr; /* ipv6 address as human readable form of in6_addr */
char *iocharset; /* local code page for mapping to and from Unicode */
char source_rfc1001_name[16]; /* netbios name of client */
char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */
......@@ -75,19 +75,21 @@ struct smb_vol {
bool setuids:1;
bool override_uid:1;
bool override_gid:1;
bool dynperm:1;
bool noperm:1;
bool no_psx_acl:1; /* set if posix acl support should be disabled */
bool cifs_acl:1;
bool no_xattr:1; /* set if xattr (EA) support should be disabled*/
bool server_ino:1; /* use inode numbers from server ie UniqueId */
bool direct_io:1;
bool remap:1; /* set to remap seven reserved chars in filenames */
bool posix_paths:1; /* unset to not ask for posix pathnames. */
bool remap:1; /* set to remap seven reserved chars in filenames */
bool posix_paths:1; /* unset to not ask for posix pathnames. */
bool no_linux_ext:1;
bool sfu_emul:1;
bool nullauth:1; /* attempt to authenticate with null user */
unsigned nocase; /* request case insensitive filenames */
unsigned nobrl; /* disable sending byte range locks to srv */
bool nullauth:1; /* attempt to authenticate with null user */
bool nocase:1; /* request case insensitive filenames */
bool nobrl:1; /* disable sending byte range locks to srv */
bool seal:1; /* request transport encryption on share */
unsigned int rsize;
unsigned int wsize;
unsigned int sockopt;
......@@ -1246,6 +1248,10 @@ cifs_parse_mount_options(char *options, const char *devname,
vol->setuids = 1;
} else if (strnicmp(data, "nosetuids", 9) == 0) {
vol->setuids = 0;
} else if (strnicmp(data, "dynperm", 7) == 0) {
vol->dynperm = true;
} else if (strnicmp(data, "nodynperm", 9) == 0) {
vol->dynperm = false;
} else if (strnicmp(data, "nohard", 6) == 0) {
vol->retry = 0;
} else if (strnicmp(data, "nosoft", 6) == 0) {
......@@ -1268,8 +1274,12 @@ cifs_parse_mount_options(char *options, const char *devname,
vol->no_psx_acl = 1;
} else if (strnicmp(data, "sign", 4) == 0) {
vol->secFlg |= CIFSSEC_MUST_SIGN;
/* } else if (strnicmp(data, "seal",4) == 0) {
vol->secFlg |= CIFSSEC_MUST_SEAL; */
} else if (strnicmp(data, "seal", 4) == 0) {
/* we do not do the following in secFlags because seal
is a per tree connection (mount) not a per socket
or per-smb connection option in the protocol */
/* vol->secFlg |= CIFSSEC_MUST_SEAL; */
vol->seal = 1;
} else if (strnicmp(data, "direct", 6) == 0) {
vol->direct_io = 1;
} else if (strnicmp(data, "forcedirectio", 13) == 0) {
......@@ -1413,27 +1423,6 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName)
return NULL;
}
int
connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo,
const char *old_path, const struct nls_table *nls_codepage,
int remap)
{
struct dfs_info3_param *referrals = NULL;
unsigned int num_referrals;
int rc = 0;
rc = get_dfs_path(xid, pSesInfo, old_path, nls_codepage,
&num_referrals, &referrals, remap);
/* BB Add in code to: if valid refrl, if not ip address contact
the helper that resolves tcp names, mount to it, try to
tcon to it unmount it if fail */
kfree(referrals);
return rc;
}
int
get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
const struct nls_table *nls_codepage, unsigned int *pnum_referrals,
......@@ -1441,7 +1430,6 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
{
char *temp_unc;
int rc = 0;
unsigned char *targetUNCs;
*pnum_referrals = 0;
*preferrals = NULL;
......@@ -1464,7 +1452,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path,
kfree(temp_unc);
}
if (rc == 0)
rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, &targetUNCs,
rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals,
pnum_referrals, nls_codepage, remap);
/* BB map targetUNCs to dfs_info3 structures, here or
in CIFSGetDFSRefer BB */
......@@ -1815,7 +1803,7 @@ convert_delimiter(char *path, char delim)
if (path == NULL)
return;
if (delim == '/')
if (delim == '/')
old_delim = '\\';
else
old_delim = '/';
......@@ -2125,6 +2113,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
if (volume_info.override_gid)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
if (volume_info.dynperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
if (volume_info.direct_io) {
cFYI(1, ("mounting share using direct i/o"));
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
......@@ -2141,6 +2131,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
for the retry flag is used */
tcon->retry = volume_info.retry;
tcon->nocase = volume_info.nocase;
if (tcon->seal != volume_info.seal)
cERROR(1, ("transport encryption setting "
"conflicts with existing tid"));
} else {
tcon = tconInfoAlloc();
if (tcon == NULL)
......@@ -2154,10 +2147,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
if ((strchr(volume_info.UNC + 3, '\\') == NULL)
&& (strchr(volume_info.UNC + 3, '/') ==
NULL)) {
rc = connect_to_dfs_path(xid, pSesInfo,
/* rc = connect_to_dfs_path(xid, pSesInfo,
"", cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFS_MOUNT_MAP_SPECIAL_CHR);*/
cFYI(1, ("DFS root not supported"));
rc = -ENODEV;
goto out;
} else {
......@@ -2173,6 +2167,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
atomic_inc(&pSesInfo->inUse);
tcon->retry = volume_info.retry;
tcon->nocase = volume_info.nocase;
tcon->seal = volume_info.seal;
}
}
}
......@@ -2314,9 +2309,10 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
user = ses->userName;
domain = ses->domainName;
smb_buffer = cifs_buf_get();
if (smb_buffer == NULL) {
if (smb_buffer == NULL)
return -ENOMEM;
}
smb_buffer_response = smb_buffer;
pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
......
......@@ -49,18 +49,25 @@ build_path_from_dentry(struct dentry *direntry)
struct dentry *temp;
int namelen;
int pplen;
int dfsplen;
char *full_path;
char dirsep;
struct cifs_sb_info *cifs_sb;
if (direntry == NULL)
return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly
when the server crashed */
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
pplen = CIFS_SB(direntry->d_sb)->prepathlen;
cifs_sb = CIFS_SB(direntry->d_sb);
dirsep = CIFS_DIR_SEP(cifs_sb);
pplen = cifs_sb->prepathlen;
if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;
cifs_bp_rename_retry:
namelen = pplen;
namelen = pplen + dfsplen;
for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len);
temp = temp->d_parent;
......@@ -91,7 +98,7 @@ build_path_from_dentry(struct dentry *direntry)
return NULL;
}
}
if (namelen != pplen) {
if (namelen != pplen + dfsplen) {
cERROR(1,
("did not end path lookup where expected namelen is %d",
namelen));
......@@ -107,7 +114,18 @@ build_path_from_dentry(struct dentry *direntry)
since the '\' is a valid posix character so we can not switch
those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of prepath */
strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);
if (dfsplen) {
strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
int i;
for (i = 0; i < dfsplen; i++) {
if (full_path[i] == '\\')
full_path[i] = '/';
}
}
}
strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
return full_path;
}
......@@ -590,7 +608,7 @@ static int cifs_ci_compare(struct dentry *dentry, struct qstr *a,
* case take precedence. If a is not a negative dentry, this
* should have no side effects
*/
memcpy(a->name, b->name, a->len);
memcpy((void *)a->name, b->name, a->len);
return 0;
}
return 1;
......
......@@ -134,10 +134,6 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
rkey = request_key(&key_type_dns_resolver, name, "");
if (!IS_ERR(rkey)) {
data = rkey->payload.data;
cFYI(1, ("%s: resolved: %s to %s", __func__,
rkey->description,
*ip_addr
));
} else {
cERROR(1, ("%s: unable to resolve: %s", __func__, name));
goto out;
......@@ -150,6 +146,11 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
if (*ip_addr) {
memcpy(*ip_addr, data, len);
(*ip_addr)[len] = '\0';
if (!IS_ERR(rkey))
cFYI(1, ("%s: resolved: %s to %s", __func__,
name,
*ip_addr
));
rc = 0;
} else {
rc = -ENOMEM;
......
......@@ -75,7 +75,11 @@ static inline int cifs_convert_flags(unsigned int flags)
return (GENERIC_READ | GENERIC_WRITE);
}
return 0x20197;
return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA |
FILE_READ_DATA);
}
static inline int cifs_get_disposition(unsigned int flags)
......
此差异已折叠。
......@@ -30,9 +30,9 @@
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
int cifs_ioctl(struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg)
long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
{
struct inode *inode = filep->f_dentry->d_inode;
int rc = -ENOTTY; /* strange error - but the precedent */
int xid;
struct cifs_sb_info *cifs_sb;
......
......@@ -234,7 +234,6 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon;
char *full_path = NULL;
char *tmp_path = NULL;
char *tmpbuffer;
int len;
__u16 fid;
......@@ -295,45 +294,9 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
cFYI(1, ("Error closing junction point "
"(open for ioctl)"));
}
/* BB unwind this long, nested function, or remove BB */
if (rc == -EIO) {
/* Query if DFS Junction */
unsigned int num_referrals = 0;
struct dfs_info3_param *refs = NULL;
tmp_path =
kmalloc(MAX_TREE_SIZE + MAX_PATHCONF + 1,
GFP_KERNEL);
if (tmp_path) {
strncpy(tmp_path, pTcon->treeName,
MAX_TREE_SIZE);
strncat(tmp_path, full_path,
MAX_PATHCONF);
rc = get_dfs_path(xid, pTcon->ses,
tmp_path,
cifs_sb->local_nls,
&num_referrals, &refs,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
cFYI(1, ("Get DFS for %s rc = %d ",
tmp_path, rc));
if ((num_referrals == 0) && (rc == 0))
rc = -EACCES;
else {
cFYI(1, ("num referral: %d",
num_referrals));
if (refs && refs->path_name) {
strncpy(tmpbuffer,
refs->path_name,
len-1);
}
}
kfree(refs);
kfree(tmp_path);
}
/* BB add code like else decode referrals
then memcpy to tmpbuffer and free referrals
string array BB */
}
/* If it is a DFS junction earlier we would have gotten
PATH_NOT_COVERED returned from server so we do
not need to request the DFS info here */
}
}
/* BB Anything else to do to handle recursive links? */
......
......@@ -141,11 +141,11 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst)
int ret = 0;
/* calculate length by finding first slash or NULL */
if (address_family == AF_INET) {
if (address_family == AF_INET)
ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL);
} else if (address_family == AF_INET6) {
else if (address_family == AF_INET6)
ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL);
}
cFYI(DBG2, ("address conversion returned %d for %s", ret, cp));
if (ret > 0)
ret = 1;
......
......@@ -64,7 +64,7 @@ typedef struct _SECURITY_BUFFER {
} __attribute__((packed)) SECURITY_BUFFER;
typedef struct _NEGOTIATE_MESSAGE {
__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
__le32 MessageType; /* 1 */
__le32 NegotiateFlags;
SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
......@@ -74,7 +74,7 @@ typedef struct _NEGOTIATE_MESSAGE {
} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
typedef struct _CHALLENGE_MESSAGE {
__u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
__le32 MessageType; /* 2 */
SECURITY_BUFFER TargetName;
__le32 NegotiateFlags;
......
......@@ -670,8 +670,11 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
(index_to_find < first_entry_in_buffer)) {
/* close and restart search */
cFYI(1, ("search backing up - close and restart search"));
cifsFile->invalidHandle = true;
CIFSFindClose(xid, pTcon, cifsFile->netfid);
if (!cifsFile->srch_inf.endOfSearch &&
!cifsFile->invalidHandle) {
cifsFile->invalidHandle = true;
CIFSFindClose(xid, pTcon, cifsFile->netfid);
}
kfree(cifsFile->search_resume_name);
cifsFile->search_resume_name = NULL;
if (cifsFile->srch_inf.ntwrk_buf_start) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册