mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
smb: client: implement ->query_reparse_point() for SMB1
Reparse points are not limited to symlinks, so implement ->query_reparse_point() in order to handle different file types. Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
a15ccef82d
commit
ed3e0a149b
@ -1356,7 +1356,7 @@ typedef struct smb_com_transaction_ioctl_rsp {
|
|||||||
__le32 DataDisplacement;
|
__le32 DataDisplacement;
|
||||||
__u8 SetupCount; /* 1 */
|
__u8 SetupCount; /* 1 */
|
||||||
__le16 ReturnedDataLen;
|
__le16 ReturnedDataLen;
|
||||||
__u16 ByteCount;
|
__le16 ByteCount;
|
||||||
} __attribute__((packed)) TRANSACT_IOCTL_RSP;
|
} __attribute__((packed)) TRANSACT_IOCTL_RSP;
|
||||||
|
|
||||||
#define CIFS_ACL_OWNER 1
|
#define CIFS_ACL_OWNER 1
|
||||||
|
@ -458,6 +458,12 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid,
|
|||||||
struct cifs_tcon *tcon,
|
struct cifs_tcon *tcon,
|
||||||
const unsigned char *searchName, char **syminfo,
|
const unsigned char *searchName, char **syminfo,
|
||||||
const struct nls_table *nls_codepage, int remap);
|
const struct nls_table *nls_codepage, int remap);
|
||||||
|
extern int cifs_query_reparse_point(const unsigned int xid,
|
||||||
|
struct cifs_tcon *tcon,
|
||||||
|
struct cifs_sb_info *cifs_sb,
|
||||||
|
const char *full_path,
|
||||||
|
u32 *tag, struct kvec *rsp,
|
||||||
|
int *rsp_buftype);
|
||||||
extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
__u16 fid, char **symlinkinfo,
|
__u16 fid, char **symlinkinfo,
|
||||||
const struct nls_table *nls_codepage);
|
const struct nls_table *nls_codepage);
|
||||||
@ -659,6 +665,9 @@ void cifs_put_tcp_super(struct super_block *sb);
|
|||||||
int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
|
int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix);
|
||||||
char *extract_hostname(const char *unc);
|
char *extract_hostname(const char *unc);
|
||||||
char *extract_sharename(const char *unc);
|
char *extract_sharename(const char *unc);
|
||||||
|
int parse_reparse_point(struct reparse_data_buffer *buf,
|
||||||
|
u32 plen, struct cifs_sb_info *cifs_sb,
|
||||||
|
bool unicode, char **target_path);
|
||||||
|
|
||||||
#ifdef CONFIG_CIFS_DFS_UPCALL
|
#ifdef CONFIG_CIFS_DFS_UPCALL
|
||||||
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
|
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
|
||||||
|
@ -2690,136 +2690,97 @@ querySymLinkRetry:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
int cifs_query_reparse_point(const unsigned int xid,
|
||||||
* Recent Windows versions now create symlinks more frequently
|
struct cifs_tcon *tcon,
|
||||||
* and they use the "reparse point" mechanism below. We can of course
|
struct cifs_sb_info *cifs_sb,
|
||||||
* do symlinks nicely to Samba and other servers which support the
|
const char *full_path,
|
||||||
* CIFS Unix Extensions and we can also do SFU symlinks and "client only"
|
u32 *tag, struct kvec *rsp,
|
||||||
* "MF" symlinks optionally, but for recent Windows we really need to
|
int *rsp_buftype)
|
||||||
* reenable the code below and fix the cifs_symlink callers to handle this.
|
|
||||||
* In the interim this code has been moved to its own config option so
|
|
||||||
* it is not compiled in by default until callers fixed up and more tested.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
|
|
||||||
__u16 fid, char **symlinkinfo,
|
|
||||||
const struct nls_table *nls_codepage)
|
|
||||||
{
|
{
|
||||||
int rc = 0;
|
struct cifs_open_parms oparms;
|
||||||
int bytes_returned;
|
TRANSACT_IOCTL_REQ *io_req = NULL;
|
||||||
struct smb_com_transaction_ioctl_req *pSMB;
|
TRANSACT_IOCTL_RSP *io_rsp = NULL;
|
||||||
struct smb_com_transaction_ioctl_rsp *pSMBr;
|
struct cifs_fid fid;
|
||||||
bool is_unicode;
|
|
||||||
unsigned int sub_len;
|
|
||||||
char *sub_start;
|
|
||||||
struct reparse_symlink_data *reparse_buf;
|
|
||||||
struct reparse_posix_data *posix_buf;
|
|
||||||
__u32 data_offset, data_count;
|
__u32 data_offset, data_count;
|
||||||
char *end_of_smb;
|
__u8 *start, *end;
|
||||||
|
int io_rsp_len;
|
||||||
|
int oplock = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid);
|
cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
|
||||||
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
|
|
||||||
(void **) &pSMBr);
|
if (cap_unix(tcon->ses))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
oparms = (struct cifs_open_parms) {
|
||||||
|
.tcon = tcon,
|
||||||
|
.cifs_sb = cifs_sb,
|
||||||
|
.desired_access = FILE_READ_ATTRIBUTES,
|
||||||
|
.create_options = cifs_create_options(cifs_sb,
|
||||||
|
OPEN_REPARSE_POINT),
|
||||||
|
.disposition = FILE_OPEN,
|
||||||
|
.path = full_path,
|
||||||
|
.fid = &fid,
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
pSMB->TotalParameterCount = 0 ;
|
rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon,
|
||||||
pSMB->TotalDataCount = 0;
|
(void **)&io_req, (void **)&io_rsp);
|
||||||
pSMB->MaxParameterCount = cpu_to_le32(2);
|
if (rc)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
io_req->TotalParameterCount = 0;
|
||||||
|
io_req->TotalDataCount = 0;
|
||||||
|
io_req->MaxParameterCount = cpu_to_le32(2);
|
||||||
/* BB find exact data count max from sess structure BB */
|
/* BB find exact data count max from sess structure BB */
|
||||||
pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
|
io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
|
||||||
pSMB->MaxSetupCount = 4;
|
io_req->MaxSetupCount = 4;
|
||||||
pSMB->Reserved = 0;
|
io_req->Reserved = 0;
|
||||||
pSMB->ParameterOffset = 0;
|
io_req->ParameterOffset = 0;
|
||||||
pSMB->DataCount = 0;
|
io_req->DataCount = 0;
|
||||||
pSMB->DataOffset = 0;
|
io_req->DataOffset = 0;
|
||||||
pSMB->SetupCount = 4;
|
io_req->SetupCount = 4;
|
||||||
pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
|
io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
|
||||||
pSMB->ParameterCount = pSMB->TotalParameterCount;
|
io_req->ParameterCount = io_req->TotalParameterCount;
|
||||||
pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
|
io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
|
||||||
pSMB->IsFsctl = 1; /* FSCTL */
|
io_req->IsFsctl = 1;
|
||||||
pSMB->IsRootFlag = 0;
|
io_req->IsRootFlag = 0;
|
||||||
pSMB->Fid = fid; /* file handle always le */
|
io_req->Fid = fid.netfid;
|
||||||
pSMB->ByteCount = 0;
|
io_req->ByteCount = 0;
|
||||||
|
|
||||||
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
|
rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req,
|
||||||
(struct smb_hdr *) pSMBr, &bytes_returned, 0);
|
(struct smb_hdr *)io_rsp, &io_rsp_len, 0);
|
||||||
if (rc) {
|
if (rc)
|
||||||
cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc);
|
goto error;
|
||||||
goto qreparse_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_offset = le32_to_cpu(pSMBr->DataOffset);
|
data_offset = le32_to_cpu(io_rsp->DataOffset);
|
||||||
data_count = le32_to_cpu(pSMBr->DataCount);
|
data_count = le32_to_cpu(io_rsp->DataCount);
|
||||||
if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) {
|
if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 ||
|
||||||
/* BB also check enough total bytes returned */
|
!data_count || data_count > 2048) {
|
||||||
rc = -EIO; /* bad smb */
|
|
||||||
goto qreparse_out;
|
|
||||||
}
|
|
||||||
if (!data_count || (data_count > 2048)) {
|
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n");
|
goto error;
|
||||||
goto qreparse_out;
|
|
||||||
}
|
}
|
||||||
end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount;
|
|
||||||
reparse_buf = (struct reparse_symlink_data *)
|
end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
|
||||||
((char *)&pSMBr->hdr.Protocol + data_offset);
|
start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
|
||||||
if ((char *)reparse_buf >= end_of_smb) {
|
if (start >= end) {
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
goto qreparse_out;
|
goto error;
|
||||||
}
|
|
||||||
if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) {
|
|
||||||
cifs_dbg(FYI, "NFS style reparse tag\n");
|
|
||||||
posix_buf = (struct reparse_posix_data *)reparse_buf;
|
|
||||||
|
|
||||||
if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) {
|
|
||||||
cifs_dbg(FYI, "unsupported file type 0x%llx\n",
|
|
||||||
le64_to_cpu(posix_buf->InodeType));
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
goto qreparse_out;
|
|
||||||
}
|
|
||||||
is_unicode = true;
|
|
||||||
sub_len = le16_to_cpu(reparse_buf->ReparseDataLength);
|
|
||||||
if (posix_buf->PathBuffer + sub_len > end_of_smb) {
|
|
||||||
cifs_dbg(FYI, "reparse buf beyond SMB\n");
|
|
||||||
rc = -EIO;
|
|
||||||
goto qreparse_out;
|
|
||||||
}
|
|
||||||
*symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer,
|
|
||||||
sub_len, is_unicode, nls_codepage);
|
|
||||||
goto qreparse_out;
|
|
||||||
} else if (reparse_buf->ReparseTag !=
|
|
||||||
cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) {
|
|
||||||
rc = -EOPNOTSUPP;
|
|
||||||
goto qreparse_out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reparse tag is NTFS symlink */
|
*tag = le32_to_cpu(((struct reparse_data_buffer *)start)->ReparseTag);
|
||||||
sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) +
|
rsp->iov_base = io_rsp;
|
||||||
reparse_buf->PathBuffer;
|
rsp->iov_len = io_rsp_len;
|
||||||
sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength);
|
*rsp_buftype = CIFS_LARGE_BUFFER;
|
||||||
if (sub_start + sub_len > end_of_smb) {
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
cifs_dbg(FYI, "reparse buf beyond SMB\n");
|
return 0;
|
||||||
rc = -EIO;
|
|
||||||
goto qreparse_out;
|
|
||||||
}
|
|
||||||
if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
|
|
||||||
is_unicode = true;
|
|
||||||
else
|
|
||||||
is_unicode = false;
|
|
||||||
|
|
||||||
/* BB FIXME investigate remapping reserved chars here */
|
error:
|
||||||
*symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode,
|
cifs_buf_release(io_req);
|
||||||
nls_codepage);
|
CIFSSMBClose(xid, tcon, fid.netfid);
|
||||||
if (!*symlinkinfo)
|
|
||||||
rc = -ENOMEM;
|
|
||||||
qreparse_out:
|
|
||||||
cifs_buf_release(pSMB);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note: On -EAGAIN error only caller can retry on handle based calls
|
|
||||||
* since file handle passed in no longer valid.
|
|
||||||
*/
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,18 +979,13 @@ static int cifs_query_symlink(const unsigned int xid,
|
|||||||
char **target_path,
|
char **target_path,
|
||||||
struct kvec *rsp_iov)
|
struct kvec *rsp_iov)
|
||||||
{
|
{
|
||||||
|
struct reparse_data_buffer *buf;
|
||||||
|
TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
|
||||||
|
bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
|
||||||
|
u32 plen = le16_to_cpu(io->ByteCount);
|
||||||
int rc;
|
int rc;
|
||||||
int oplock = 0;
|
|
||||||
bool is_reparse_point = !!rsp_iov;
|
|
||||||
struct cifs_fid fid;
|
|
||||||
struct cifs_open_parms oparms;
|
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
|
||||||
|
|
||||||
if (is_reparse_point) {
|
|
||||||
cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n");
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for unix extensions */
|
/* Check for unix extensions */
|
||||||
if (cap_unix(tcon->ses)) {
|
if (cap_unix(tcon->ses)) {
|
||||||
@ -1001,37 +996,12 @@ static int cifs_query_symlink(const unsigned int xid,
|
|||||||
rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
|
rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
|
||||||
target_path,
|
target_path,
|
||||||
cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
|
return rc;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oparms = (struct cifs_open_parms) {
|
buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
|
||||||
.tcon = tcon,
|
le32_to_cpu(io->DataOffset));
|
||||||
.cifs_sb = cifs_sb,
|
return parse_reparse_point(buf, plen, cifs_sb, unicode, target_path);
|
||||||
.desired_access = FILE_READ_ATTRIBUTES,
|
|
||||||
.create_options = cifs_create_options(cifs_sb,
|
|
||||||
OPEN_REPARSE_POINT),
|
|
||||||
.disposition = FILE_OPEN,
|
|
||||||
.path = full_path,
|
|
||||||
.fid = &fid,
|
|
||||||
};
|
|
||||||
|
|
||||||
rc = CIFS_open(xid, &oparms, &oplock, NULL);
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
|
|
||||||
cifs_sb->local_nls);
|
|
||||||
if (rc)
|
|
||||||
goto out_close;
|
|
||||||
|
|
||||||
convert_delimiter(*target_path, '/');
|
|
||||||
out_close:
|
|
||||||
CIFSSMBClose(xid, tcon, fid.netfid);
|
|
||||||
out:
|
|
||||||
if (!rc)
|
|
||||||
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -1214,6 +1184,7 @@ struct smb_version_operations smb1_operations = {
|
|||||||
.is_path_accessible = cifs_is_path_accessible,
|
.is_path_accessible = cifs_is_path_accessible,
|
||||||
.can_echo = cifs_can_echo,
|
.can_echo = cifs_can_echo,
|
||||||
.query_path_info = cifs_query_path_info,
|
.query_path_info = cifs_query_path_info,
|
||||||
|
.query_reparse_point = cifs_query_reparse_point,
|
||||||
.query_file_info = cifs_query_file_info,
|
.query_file_info = cifs_query_file_info,
|
||||||
.get_srv_inum = cifs_get_srv_inum,
|
.get_srv_inum = cifs_get_srv_inum,
|
||||||
.set_path_size = CIFSSMBSetEOF,
|
.set_path_size = CIFSSMBSetEOF,
|
||||||
|
@ -2894,27 +2894,26 @@ parse_reparse_posix(struct reparse_posix_data *symlink_buf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
|
||||||
parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
|
u32 plen, bool unicode, char **target_path,
|
||||||
u32 plen, char **target_path,
|
struct cifs_sb_info *cifs_sb)
|
||||||
struct cifs_sb_info *cifs_sb)
|
|
||||||
{
|
{
|
||||||
unsigned int sub_len;
|
unsigned int sub_len;
|
||||||
unsigned int sub_offset;
|
unsigned int sub_offset;
|
||||||
|
|
||||||
/* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */
|
/* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */
|
||||||
|
|
||||||
sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset);
|
sub_offset = le16_to_cpu(sym->SubstituteNameOffset);
|
||||||
sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength);
|
sub_len = le16_to_cpu(sym->SubstituteNameLength);
|
||||||
if (sub_offset + 20 > plen ||
|
if (sub_offset + 20 > plen ||
|
||||||
sub_offset + sub_len + 20 > plen) {
|
sub_offset + sub_len + 20 > plen) {
|
||||||
cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
|
cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
*target_path = cifs_strndup_from_utf16(
|
*target_path = cifs_strndup_from_utf16(sym->PathBuffer + sub_offset,
|
||||||
symlink_buf->PathBuffer + sub_offset,
|
sub_len, unicode,
|
||||||
sub_len, true, cifs_sb->local_nls);
|
cifs_sb->local_nls);
|
||||||
if (!(*target_path))
|
if (!(*target_path))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -2924,19 +2923,17 @@ parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int parse_reparse_point(struct reparse_data_buffer *buf,
|
||||||
parse_reparse_point(struct reparse_data_buffer *buf,
|
u32 plen, struct cifs_sb_info *cifs_sb,
|
||||||
u32 plen, char **target_path,
|
bool unicode, char **target_path)
|
||||||
struct cifs_sb_info *cifs_sb)
|
|
||||||
{
|
{
|
||||||
if (plen < sizeof(struct reparse_data_buffer)) {
|
if (plen < sizeof(*buf)) {
|
||||||
cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n",
|
cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n",
|
||||||
plen);
|
plen);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plen < le16_to_cpu(buf->ReparseDataLength) +
|
if (plen < le16_to_cpu(buf->ReparseDataLength) + sizeof(*buf)) {
|
||||||
sizeof(struct reparse_data_buffer)) {
|
|
||||||
cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n",
|
cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n",
|
||||||
plen);
|
plen);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@ -2951,7 +2948,7 @@ parse_reparse_point(struct reparse_data_buffer *buf,
|
|||||||
case IO_REPARSE_TAG_SYMLINK:
|
case IO_REPARSE_TAG_SYMLINK:
|
||||||
return parse_reparse_symlink(
|
return parse_reparse_symlink(
|
||||||
(struct reparse_symlink_data_buffer *)buf,
|
(struct reparse_symlink_data_buffer *)buf,
|
||||||
plen, target_path, cifs_sb);
|
plen, unicode, target_path, cifs_sb);
|
||||||
default:
|
default:
|
||||||
cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
|
cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n",
|
||||||
le32_to_cpu(buf->ReparseTag));
|
le32_to_cpu(buf->ReparseTag));
|
||||||
@ -2970,11 +2967,11 @@ static int smb2_query_symlink(const unsigned int xid,
|
|||||||
struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
|
struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
|
||||||
u32 plen = le32_to_cpu(io->OutputCount);
|
u32 plen = le32_to_cpu(io->OutputCount);
|
||||||
|
|
||||||
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
cifs_tcon_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
||||||
|
|
||||||
buf = (struct reparse_data_buffer *)((u8 *)io +
|
buf = (struct reparse_data_buffer *)((u8 *)io +
|
||||||
le32_to_cpu(io->OutputOffset));
|
le32_to_cpu(io->OutputOffset));
|
||||||
return parse_reparse_point(buf, plen, target_path, cifs_sb);
|
return parse_reparse_point(buf, plen, cifs_sb, true, target_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int smb2_query_reparse_point(const unsigned int xid,
|
static int smb2_query_reparse_point(const unsigned int xid,
|
||||||
|
Loading…
Reference in New Issue
Block a user