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 ...
This commit is contained in:
Коммит
5cf11daf9a
|
@ -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
|
||||
-------------------------------------
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
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
|
||||
|
|
15
fs/cifs/TODO
15
fs/cifs/TODO
|
@ -1,4 +1,4 @@
|
|||
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 */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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 @@ OldOpenRetry:
|
|||
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 @@ OldOpenRetry:
|
|||
} 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 @@ renameRetry:
|
|||
/* 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 @@ setAclRetry:
|
|||
}
|
||||
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 @@ QPathInfoRetry:
|
|||
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 @@ QPathInfoRetry:
|
|||
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 @@ GetInodeNumOut:
|
|||
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 @@ getDFSRetry:
|
|||
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 @@ getDFSRetry:
|
|||
(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);
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
goto GetDFSRefExit;
|
||||
}
|
||||
|
||||
cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d",
|
||||
pSMBr->ByteCount,
|
||||
le16_to_cpu(pSMBr->t2.DataOffset)));
|
||||
|
||||
/* 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 @@ QFSAttributeRetry:
|
|||
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 @@ QFSDeviceRetry:
|
|||
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 @@ QFSUnixRetry:
|
|||
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 @@ SETFSUnixRetry:
|
|||
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 @@ QFSPosixRetry:
|
|||
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 @@ SetTimesRetry:
|
|||
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 @@ setPermsRetry:
|
|||
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 @@ QAllEAsRetry:
|
|||
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 @@ QEARetry:
|
|||
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 @@ SetEARetry:
|
|||
|
||||
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 @@ cifs_bp_rename_retry:
|
|||
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 @@ cifs_bp_rename_retry:
|
|||
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 @@ skip_upcall:
|
|||
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)
|
||||
|
|
523
fs/cifs/inode.c
523
fs/cifs/inode.c
|
@ -161,118 +161,115 @@ static void cifs_unix_info_to_inode(struct inode *inode,
|
|||
spin_unlock(&inode->i_lock);
|
||||
}
|
||||
|
||||
static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb,
|
||||
const char *search_path)
|
||||
|
||||
/*
|
||||
* Needed to setup inode data for the directory which is the
|
||||
* junction to the new submount (ie to setup the fake directory
|
||||
* which represents a DFS referral)
|
||||
*/
|
||||
static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
|
||||
struct super_block *sb)
|
||||
{
|
||||
int tree_len;
|
||||
int path_len;
|
||||
int i;
|
||||
char *tmp_path;
|
||||
struct cifsTconInfo *pTcon = cifs_sb->tcon;
|
||||
struct inode *pinode = NULL;
|
||||
|
||||
if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
|
||||
return search_path;
|
||||
memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0);
|
||||
|
||||
/* use full path name for working with DFS */
|
||||
tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1);
|
||||
path_len = strnlen(search_path, MAX_PATHCONF);
|
||||
/* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0);
|
||||
__le64 pfnd_dat->NumOfBytes = cpu_to_le64(0);
|
||||
__u64 UniqueId = 0; */
|
||||
pfnd_dat->LastStatusChange =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->LastAccessTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->LastModificationTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->Type = cpu_to_le32(UNIX_DIR);
|
||||
pfnd_dat->Permissions = cpu_to_le64(S_IXUGO | S_IRWXU);
|
||||
pfnd_dat->Nlinks = cpu_to_le64(2);
|
||||
if (sb->s_root)
|
||||
pinode = sb->s_root->d_inode;
|
||||
if (pinode == NULL)
|
||||
return;
|
||||
|
||||
tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL);
|
||||
if (tmp_path == NULL)
|
||||
return search_path;
|
||||
|
||||
strncpy(tmp_path, pTcon->treeName, tree_len);
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
|
||||
for (i = 0; i < tree_len; i++) {
|
||||
if (tmp_path[i] == '\\')
|
||||
tmp_path[i] = '/';
|
||||
}
|
||||
strncpy(tmp_path+tree_len, search_path, path_len);
|
||||
tmp_path[tree_len+path_len] = 0;
|
||||
return tmp_path;
|
||||
/* fill in default values for the remaining based on root
|
||||
inode since we can not query the server for this inode info */
|
||||
pfnd_dat->DevMajor = cpu_to_le64(MAJOR(pinode->i_rdev));
|
||||
pfnd_dat->DevMinor = cpu_to_le64(MINOR(pinode->i_rdev));
|
||||
pfnd_dat->Uid = cpu_to_le64(pinode->i_uid);
|
||||
pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
|
||||
}
|
||||
|
||||
int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
const unsigned char *search_path, struct super_block *sb, int xid)
|
||||
const unsigned char *full_path, struct super_block *sb, int xid)
|
||||
{
|
||||
int rc = 0;
|
||||
FILE_UNIX_BASIC_INFO findData;
|
||||
FILE_UNIX_BASIC_INFO find_data;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
const unsigned char *full_path;
|
||||
bool is_dfs_referral = false;
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
__u64 num_of_bytes;
|
||||
__u64 end_of_file;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
cFYI(1, ("Getting info on %s", search_path));
|
||||
cFYI(1, ("Getting info on %s", full_path));
|
||||
|
||||
full_path = cifs_get_search_path(cifs_sb, search_path);
|
||||
|
||||
try_again_CIFSSMBUnixQPathInfo:
|
||||
/* could have done a find first instead but this returns more info */
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData,
|
||||
rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &find_data,
|
||||
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
/* dump_mem("\nUnixQPathInfo return data", &findData,
|
||||
sizeof(findData)); */
|
||||
if (rc) {
|
||||
if (rc == -EREMOTE && !is_dfs_referral) {
|
||||
is_dfs_referral = true;
|
||||
if (full_path != search_path) {
|
||||
kfree(full_path);
|
||||
full_path = search_path;
|
||||
}
|
||||
goto try_again_CIFSSMBUnixQPathInfo;
|
||||
cFYI(DBG2, ("DFS ref"));
|
||||
/* for DFS, server does not give us real inode data */
|
||||
fill_fake_finddataunix(&find_data, sb);
|
||||
rc = 0;
|
||||
}
|
||||
goto cgiiu_exit;
|
||||
} else {
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
|
||||
__u64 end_of_file = le64_to_cpu(findData.EndOfFile);
|
||||
|
||||
/* get new inode */
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgiiu_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
(*pinode)->i_ino =
|
||||
(unsigned long)findData.UniqueId;
|
||||
} /* note ino incremented to unique num in new_inode */
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
|
||||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
|
||||
cFYI(1, ("Old time %ld", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||
/* this is ok to set on every inode revalidate */
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
|
||||
cifs_unix_info_to_inode(inode, &findData, 0);
|
||||
|
||||
|
||||
if (num_of_bytes < end_of_file)
|
||||
cFYI(1, ("allocation size less than end of file"));
|
||||
cFYI(1, ("Size %ld and blocks %llu",
|
||||
(unsigned long) inode->i_size,
|
||||
(unsigned long long)inode->i_blocks));
|
||||
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
}
|
||||
num_of_bytes = le64_to_cpu(find_data.NumOfBytes);
|
||||
end_of_file = le64_to_cpu(find_data.EndOfFile);
|
||||
|
||||
/* get new inode */
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgiiu_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? */
|
||||
/* note ino incremented to unique num in new_inode */
|
||||
/* Are there sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
|
||||
(*pinode)->i_ino = (unsigned long)find_data.UniqueId;
|
||||
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
|
||||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
|
||||
cFYI(1, ("Old time %ld", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||
/* this is ok to set on every inode revalidate */
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
|
||||
cifs_unix_info_to_inode(inode, &find_data, 0);
|
||||
|
||||
if (num_of_bytes < end_of_file)
|
||||
cFYI(1, ("allocation size less than end of file"));
|
||||
cFYI(1, ("Size %ld and blocks %llu",
|
||||
(unsigned long) inode->i_size,
|
||||
(unsigned long long)inode->i_blocks));
|
||||
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
cgiiu_exit:
|
||||
if (full_path != search_path)
|
||||
kfree(full_path);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -379,21 +376,51 @@ static int get_sfu_mode(struct inode *inode,
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Needed to setup inode data for the directory which is the
|
||||
* junction to the new submount (ie to setup the fake directory
|
||||
* which represents a DFS referral)
|
||||
*/
|
||||
static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat,
|
||||
struct super_block *sb)
|
||||
{
|
||||
memset(pfnd_dat, sizeof(FILE_ALL_INFO), 0);
|
||||
|
||||
/* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0);
|
||||
__le64 pfnd_dat->EndOfFile = cpu_to_le64(0);
|
||||
__u8 pfnd_dat->DeletePending = 0;
|
||||
__u8 pfnd_data->Directory = 0;
|
||||
__le32 pfnd_dat->EASize = 0;
|
||||
__u64 pfnd_dat->IndexNumber = 0;
|
||||
__u64 pfnd_dat->IndexNumber1 = 0; */
|
||||
pfnd_dat->CreationTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->LastAccessTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->LastWriteTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->ChangeTime =
|
||||
cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
|
||||
pfnd_dat->Attributes = cpu_to_le32(ATTR_DIRECTORY);
|
||||
pfnd_dat->NumberOfLinks = cpu_to_le32(2);
|
||||
}
|
||||
|
||||
int cifs_get_inode_info(struct inode **pinode,
|
||||
const unsigned char *search_path, FILE_ALL_INFO *pfindData,
|
||||
const unsigned char *full_path, FILE_ALL_INFO *pfindData,
|
||||
struct super_block *sb, int xid, const __u16 *pfid)
|
||||
{
|
||||
int rc = 0;
|
||||
__u32 attr;
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
struct cifsTconInfo *pTcon;
|
||||
struct inode *inode;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
|
||||
const unsigned char *full_path = NULL;
|
||||
char *buf = NULL;
|
||||
bool adjustTZ = false;
|
||||
bool is_dfs_referral = false;
|
||||
|
||||
pTcon = cifs_sb->tcon;
|
||||
cFYI(1, ("Getting info on %s", search_path));
|
||||
cFYI(1, ("Getting info on %s", full_path));
|
||||
|
||||
if ((pfindData == NULL) && (*pinode != NULL)) {
|
||||
if (CIFS_I(*pinode)->clientCanCacheRead) {
|
||||
|
@ -409,9 +436,6 @@ int cifs_get_inode_info(struct inode **pinode,
|
|||
return -ENOMEM;
|
||||
pfindData = (FILE_ALL_INFO *)buf;
|
||||
|
||||
full_path = cifs_get_search_path(cifs_sb, search_path);
|
||||
|
||||
try_again_CIFSSMBQPathInfo:
|
||||
/* could do find first instead but this returns more info */
|
||||
rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
|
||||
0 /* not legacy */,
|
||||
|
@ -429,178 +453,168 @@ try_again_CIFSSMBQPathInfo:
|
|||
}
|
||||
}
|
||||
/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
|
||||
if (rc) {
|
||||
if (rc == -EREMOTE && !is_dfs_referral) {
|
||||
is_dfs_referral = true;
|
||||
if (full_path != search_path) {
|
||||
kfree(full_path);
|
||||
full_path = search_path;
|
||||
}
|
||||
goto try_again_CIFSSMBQPathInfo;
|
||||
}
|
||||
if (rc == -EREMOTE) {
|
||||
is_dfs_referral = true;
|
||||
fill_fake_finddata(pfindData, sb);
|
||||
rc = 0;
|
||||
} else if (rc)
|
||||
goto cgii_exit;
|
||||
} else {
|
||||
struct cifsInodeInfo *cifsInfo;
|
||||
__u32 attr = le32_to_cpu(pfindData->Attributes);
|
||||
|
||||
/* get new inode */
|
||||
attr = le32_to_cpu(pfindData->Attributes);
|
||||
|
||||
/* get new inode */
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL) {
|
||||
*pinode = new_inode(sb);
|
||||
if (*pinode == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto cgii_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? Can we use that to check
|
||||
if the server supports returning inode numbers? Are
|
||||
there other sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
rc = -ENOMEM;
|
||||
goto cgii_exit;
|
||||
}
|
||||
/* Is an i_ino of zero legal? Can we use that to check
|
||||
if the server supports returning inode numbers? Are
|
||||
there other sanity checks we can use to ensure that
|
||||
the server is really filling in that field? */
|
||||
|
||||
/* We can not use the IndexNumber field by default from
|
||||
Windows or Samba (in ALL_INFO buf) but we can request
|
||||
it explicitly. It may not be unique presumably if
|
||||
the server has multiple devices mounted under one
|
||||
share */
|
||||
/* We can not use the IndexNumber field by default from
|
||||
Windows or Samba (in ALL_INFO buf) but we can request
|
||||
it explicitly. It may not be unique presumably if
|
||||
the server has multiple devices mounted under one share */
|
||||
|
||||
/* There may be higher info levels that work but are
|
||||
there Windows server or network appliances for which
|
||||
IndexNumber field is not guaranteed unique? */
|
||||
/* There may be higher info levels that work but are
|
||||
there Windows server or network appliances for which
|
||||
IndexNumber field is not guaranteed unique? */
|
||||
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
int rc1 = 0;
|
||||
__u64 inode_num;
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
|
||||
int rc1 = 0;
|
||||
__u64 inode_num;
|
||||
|
||||
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
||||
search_path, &inode_num,
|
||||
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
|
||||
full_path, &inode_num,
|
||||
cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_flags &
|
||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||
if (rc1) {
|
||||
cFYI(1, ("GetSrvInodeNum rc %d", rc1));
|
||||
/* BB EOPNOSUPP disable SERVER_INUM? */
|
||||
} else /* do we need cast or hash to ino? */
|
||||
(*pinode)->i_ino = inode_num;
|
||||
} /* else ino incremented to unique num in new_inode*/
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
cifsInfo->cifsAttrs = attr;
|
||||
cFYI(1, ("Old time %ld", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||
|
||||
/* blksize needs to be multiple of two. So safer to default to
|
||||
blksize and blkbits set in superblock so 2**blkbits and blksize
|
||||
will match rather than setting to:
|
||||
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
|
||||
|
||||
/* Linux can not store file creation time so ignore it */
|
||||
if (pfindData->LastAccessTime)
|
||||
inode->i_atime = cifs_NTtimeToUnix
|
||||
(le64_to_cpu(pfindData->LastAccessTime));
|
||||
else /* do not need to use current_fs_time - time not stored */
|
||||
inode->i_atime = CURRENT_TIME;
|
||||
inode->i_mtime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
|
||||
inode->i_ctime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
|
||||
cFYI(0, ("Attributes came in as 0x%x", attr));
|
||||
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
|
||||
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
}
|
||||
|
||||
/* set default mode. will override for dirs below */
|
||||
if (atomic_read(&cifsInfo->inUse) == 0)
|
||||
/* new inode, can safely set these fields */
|
||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
else /* since we set the inode type below we need to mask off
|
||||
to avoid strange results if type changes and both
|
||||
get orred in */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
/* if (attr & ATTR_REPARSE) */
|
||||
/* We no longer handle these as symlinks because we could not
|
||||
follow them due to the absolute path with drive letter */
|
||||
if (attr & ATTR_DIRECTORY) {
|
||||
/* override default perms since we do not do byte range locking
|
||||
on dirs */
|
||||
inode->i_mode = cifs_sb->mnt_dir_mode;
|
||||
inode->i_mode |= S_IFDIR;
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
|
||||
/* No need to le64 convert size of zero */
|
||||
(pfindData->EndOfFile == 0)) {
|
||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
inode->i_mode |= S_IFIFO;
|
||||
/* BB Finish for SFU style symlinks and devices */
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
|
||||
if (decode_sfu_inode(inode,
|
||||
le64_to_cpu(pfindData->EndOfFile),
|
||||
search_path,
|
||||
cifs_sb, xid))
|
||||
cFYI(1, ("Unrecognized sfu inode type"));
|
||||
|
||||
cFYI(1, ("sfu mode 0%o", inode->i_mode));
|
||||
} else {
|
||||
inode->i_mode |= S_IFREG;
|
||||
/* treat the dos attribute of read-only as read-only
|
||||
mode e.g. 555 */
|
||||
if (cifsInfo->cifsAttrs & ATTR_READONLY)
|
||||
inode->i_mode &= ~(S_IWUGO);
|
||||
else if ((inode->i_mode & S_IWUGO) == 0)
|
||||
/* the ATTR_READONLY flag may have been */
|
||||
/* changed on server -- set any w bits */
|
||||
/* allowed by mnt_file_mode */
|
||||
inode->i_mode |= (S_IWUGO &
|
||||
cifs_sb->mnt_file_mode);
|
||||
/* BB add code here -
|
||||
validate if device or weird share or device type? */
|
||||
}
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (is_size_safe_to_change(cifsInfo,
|
||||
le64_to_cpu(pfindData->EndOfFile))) {
|
||||
/* can not safely shrink the file size here if the
|
||||
client is writing to it due to potential races */
|
||||
i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
|
||||
|
||||
/* 512 bytes (2**9) is the fake blocksize that must be
|
||||
used for this calculation */
|
||||
inode->i_blocks = (512 - 1 + le64_to_cpu(
|
||||
pfindData->AllocationSize)) >> 9;
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
||||
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
|
||||
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
or retrieve from NTFS stream extended attribute */
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
/* fill in 0777 bits from ACL */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
cFYI(1, ("Getting mode bits from ACL"));
|
||||
acl_to_uid_mode(inode, search_path, pfid);
|
||||
}
|
||||
#endif
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
/* fill in remaining high mode bits e.g. SUID, VTX */
|
||||
get_sfu_mode(inode, search_path, cifs_sb, xid);
|
||||
} else if (atomic_read(&cifsInfo->inUse) == 0) {
|
||||
inode->i_uid = cifs_sb->mnt_uid;
|
||||
inode->i_gid = cifs_sb->mnt_gid;
|
||||
/* set so we do not keep refreshing these fields with
|
||||
bad data after user has changed them in memory */
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
}
|
||||
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
if (rc1) {
|
||||
cFYI(1, ("GetSrvInodeNum rc %d", rc1));
|
||||
/* BB EOPNOSUPP disable SERVER_INUM? */
|
||||
} else /* do we need cast or hash to ino? */
|
||||
(*pinode)->i_ino = inode_num;
|
||||
} /* else ino incremented to unique num in new_inode*/
|
||||
if (sb->s_flags & MS_NOATIME)
|
||||
(*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
|
||||
insert_inode_hash(*pinode);
|
||||
}
|
||||
inode = *pinode;
|
||||
cifsInfo = CIFS_I(inode);
|
||||
cifsInfo->cifsAttrs = attr;
|
||||
cFYI(1, ("Old time %ld", cifsInfo->time));
|
||||
cifsInfo->time = jiffies;
|
||||
cFYI(1, ("New time %ld", cifsInfo->time));
|
||||
|
||||
/* blksize needs to be multiple of two. So safer to default to
|
||||
blksize and blkbits set in superblock so 2**blkbits and blksize
|
||||
will match rather than setting to:
|
||||
(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
|
||||
|
||||
/* Linux can not store file creation time so ignore it */
|
||||
if (pfindData->LastAccessTime)
|
||||
inode->i_atime = cifs_NTtimeToUnix
|
||||
(le64_to_cpu(pfindData->LastAccessTime));
|
||||
else /* do not need to use current_fs_time - time not stored */
|
||||
inode->i_atime = CURRENT_TIME;
|
||||
inode->i_mtime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
|
||||
inode->i_ctime =
|
||||
cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
|
||||
cFYI(DBG2, ("Attributes came in as 0x%x", attr));
|
||||
if (adjustTZ && (pTcon->ses) && (pTcon->ses->server)) {
|
||||
inode->i_ctime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
|
||||
}
|
||||
|
||||
/* set default mode. will override for dirs below */
|
||||
if (atomic_read(&cifsInfo->inUse) == 0)
|
||||
/* new inode, can safely set these fields */
|
||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
else /* since we set the inode type below we need to mask off
|
||||
to avoid strange results if type changes and both
|
||||
get orred in */
|
||||
inode->i_mode &= ~S_IFMT;
|
||||
/* if (attr & ATTR_REPARSE) */
|
||||
/* We no longer handle these as symlinks because we could not
|
||||
follow them due to the absolute path with drive letter */
|
||||
if (attr & ATTR_DIRECTORY) {
|
||||
/* override default perms since we do not do byte range locking
|
||||
on dirs */
|
||||
inode->i_mode = cifs_sb->mnt_dir_mode;
|
||||
inode->i_mode |= S_IFDIR;
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(cifsInfo->cifsAttrs & ATTR_SYSTEM) &&
|
||||
/* No need to le64 convert size of zero */
|
||||
(pfindData->EndOfFile == 0)) {
|
||||
inode->i_mode = cifs_sb->mnt_file_mode;
|
||||
inode->i_mode |= S_IFIFO;
|
||||
/* BB Finish for SFU style symlinks and devices */
|
||||
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
|
||||
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
|
||||
if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile),
|
||||
full_path, cifs_sb, xid))
|
||||
cFYI(1, ("Unrecognized sfu inode type"));
|
||||
|
||||
cFYI(1, ("sfu mode 0%o", inode->i_mode));
|
||||
} else {
|
||||
inode->i_mode |= S_IFREG;
|
||||
/* treat dos attribute of read-only as read-only mode eg 555 */
|
||||
if (cifsInfo->cifsAttrs & ATTR_READONLY)
|
||||
inode->i_mode &= ~(S_IWUGO);
|
||||
else if ((inode->i_mode & S_IWUGO) == 0)
|
||||
/* the ATTR_READONLY flag may have been */
|
||||
/* changed on server -- set any w bits */
|
||||
/* allowed by mnt_file_mode */
|
||||
inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode);
|
||||
/* BB add code to validate if device or weird share or device type? */
|
||||
}
|
||||
|
||||
spin_lock(&inode->i_lock);
|
||||
if (is_size_safe_to_change(cifsInfo,
|
||||
le64_to_cpu(pfindData->EndOfFile))) {
|
||||
/* can not safely shrink the file size here if the
|
||||
client is writing to it due to potential races */
|
||||
i_size_write(inode, le64_to_cpu(pfindData->EndOfFile));
|
||||
|
||||
/* 512 bytes (2**9) is the fake blocksize that must be
|
||||
used for this calculation */
|
||||
inode->i_blocks = (512 - 1 + le64_to_cpu(
|
||||
pfindData->AllocationSize)) >> 9;
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
|
||||
inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks);
|
||||
|
||||
/* BB fill in uid and gid here? with help from winbind?
|
||||
or retrieve from NTFS stream extended attribute */
|
||||
#ifdef CONFIG_CIFS_EXPERIMENTAL
|
||||
/* fill in 0777 bits from ACL */
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
|
||||
cFYI(1, ("Getting mode bits from ACL"));
|
||||
acl_to_uid_mode(inode, full_path, pfid);
|
||||
}
|
||||
#endif
|
||||
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
|
||||
/* fill in remaining high mode bits e.g. SUID, VTX */
|
||||
get_sfu_mode(inode, full_path, cifs_sb, xid);
|
||||
} else if (atomic_read(&cifsInfo->inUse) == 0) {
|
||||
inode->i_uid = cifs_sb->mnt_uid;
|
||||
inode->i_gid = cifs_sb->mnt_gid;
|
||||
/* set so we do not keep refreshing these fields with
|
||||
bad data after user has changed them in memory */
|
||||
atomic_set(&cifsInfo->inUse, 1);
|
||||
}
|
||||
|
||||
cifs_set_ops(inode, is_dfs_referral);
|
||||
|
||||
|
||||
|
||||
|
||||
cgii_exit:
|
||||
if (full_path != search_path)
|
||||
kfree(full_path);
|
||||
kfree(buf);
|
||||
return rc;
|
||||
}
|
||||
|
@ -1502,8 +1516,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
|
|||
int oplock = 0;
|
||||
|
||||
rc = SMBLegacyOpen(xid, pTcon, full_path,
|
||||
FILE_OPEN,
|
||||
SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
|
||||
FILE_OPEN, GENERIC_WRITE,
|
||||
CREATE_NOT_DIR, &netfid, &oplock,
|
||||
NULL, cifs_sb->local_nls,
|
||||
cifs_sb->mnt_cifs_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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче