Commit 68889f26 authored by Pavel Shilovsky's avatar Pavel Shilovsky

CIFS: Move is_path_accessible to ops struct

Signed-off-by: default avatarPavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent af4281dc
...@@ -215,6 +215,9 @@ struct smb_version_operations { ...@@ -215,6 +215,9 @@ struct smb_version_operations {
unsigned int *, const struct nls_table *, int); unsigned int *, const struct nls_table *, int);
/* informational QFS call */ /* informational QFS call */
void (*qfs_tcon)(const unsigned int, struct cifs_tcon *); void (*qfs_tcon)(const unsigned int, struct cifs_tcon *);
/* check if a path is accessible or not */
int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
struct cifs_sb_info *, const char *);
}; };
struct smb_version_values { struct smb_version_values {
......
...@@ -208,14 +208,12 @@ extern int CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -208,14 +208,12 @@ extern int CIFSFindClose(const unsigned int xid, struct cifs_tcon *tcon,
extern int CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
u16 netfid, FILE_ALL_INFO *pFindData); u16 netfid, FILE_ALL_INFO *pFindData);
extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
const unsigned char *searchName, const char *search_Name, FILE_ALL_INFO *data,
FILE_ALL_INFO *findData, int legacy /* whether to use old info level */,
int legacy /* whether to use old info level */, const struct nls_table *nls_codepage, int remap);
const struct nls_table *nls_codepage, int remap);
extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
const unsigned char *searchName, const char *search_name, FILE_ALL_INFO *data,
FILE_ALL_INFO *findData, const struct nls_table *nls_codepage, int remap);
const struct nls_table *nls_codepage, int remap);
extern int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, extern int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
u16 netfid, FILE_UNIX_BASIC_INFO *pFindData); u16 netfid, FILE_UNIX_BASIC_INFO *pFindData);
......
...@@ -3853,10 +3853,10 @@ CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid, ...@@ -3853,10 +3853,10 @@ CIFSSMBSetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, __u16 fid,
/* Legacy Query Path Information call for lookup to old servers such /* Legacy Query Path Information call for lookup to old servers such
as Win9x/WinME */ as Win9x/WinME */
int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, int
const unsigned char *searchName, SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
FILE_ALL_INFO *pFinfo, const char *search_name, FILE_ALL_INFO *data,
const struct nls_table *nls_codepage, int remap) const struct nls_table *nls_codepage, int remap)
{ {
QUERY_INFORMATION_REQ *pSMB; QUERY_INFORMATION_REQ *pSMB;
QUERY_INFORMATION_RSP *pSMBr; QUERY_INFORMATION_RSP *pSMBr;
...@@ -3864,7 +3864,7 @@ int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3864,7 +3864,7 @@ int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
int bytes_returned; int bytes_returned;
int name_len; int name_len;
cFYI(1, "In SMBQPath path %s", searchName); cFYI(1, "In SMBQPath path %s", search_name);
QInfRetry: QInfRetry:
rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB, rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
(void **) &pSMBr); (void **) &pSMBr);
...@@ -3874,14 +3874,14 @@ int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3874,14 +3874,14 @@ int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUTF16((__le16 *) pSMB->FileName, cifsConvertToUTF16((__le16 *) pSMB->FileName,
searchName, PATH_MAX, nls_codepage, search_name, PATH_MAX, nls_codepage,
remap); remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { } else {
name_len = strnlen(searchName, PATH_MAX); name_len = strnlen(search_name, PATH_MAX);
name_len++; /* trailing null */ name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len); strncpy(pSMB->FileName, search_name, name_len);
} }
pSMB->BufferFormat = 0x04; pSMB->BufferFormat = 0x04;
name_len++; /* account for buffer type byte */ name_len++; /* account for buffer type byte */
...@@ -3892,23 +3892,23 @@ int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3892,23 +3892,23 @@ int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon,
(struct smb_hdr *) pSMBr, &bytes_returned, 0); (struct smb_hdr *) pSMBr, &bytes_returned, 0);
if (rc) { if (rc) {
cFYI(1, "Send error in QueryInfo = %d", rc); cFYI(1, "Send error in QueryInfo = %d", rc);
} else if (pFinfo) { } else if (data) {
struct timespec ts; struct timespec ts;
__u32 time = le32_to_cpu(pSMBr->last_write_time); __u32 time = le32_to_cpu(pSMBr->last_write_time);
/* decode response */ /* decode response */
/* BB FIXME - add time zone adjustment BB */ /* BB FIXME - add time zone adjustment BB */
memset(pFinfo, 0, sizeof(FILE_ALL_INFO)); memset(data, 0, sizeof(FILE_ALL_INFO));
ts.tv_nsec = 0; ts.tv_nsec = 0;
ts.tv_sec = time; ts.tv_sec = time;
/* decode time fields */ /* decode time fields */
pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts)); data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts));
pFinfo->LastWriteTime = pFinfo->ChangeTime; data->LastWriteTime = data->ChangeTime;
pFinfo->LastAccessTime = 0; data->LastAccessTime = 0;
pFinfo->AllocationSize = data->AllocationSize =
cpu_to_le64(le32_to_cpu(pSMBr->size)); cpu_to_le64(le32_to_cpu(pSMBr->size));
pFinfo->EndOfFile = pFinfo->AllocationSize; data->EndOfFile = data->AllocationSize;
pFinfo->Attributes = data->Attributes =
cpu_to_le32(le16_to_cpu(pSMBr->attr)); cpu_to_le32(le16_to_cpu(pSMBr->attr));
} else } else
rc = -EIO; /* bad buffer passed in */ rc = -EIO; /* bad buffer passed in */
...@@ -3990,12 +3990,11 @@ CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -3990,12 +3990,11 @@ CIFSSMBQFileInfo(const unsigned int xid, struct cifs_tcon *tcon,
int int
CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
const unsigned char *searchName, const char *search_name, FILE_ALL_INFO *data,
FILE_ALL_INFO *pFindData,
int legacy /* old style infolevel */, int legacy /* old style infolevel */,
const struct nls_table *nls_codepage, int remap) const struct nls_table *nls_codepage, int remap)
{ {
/* level 263 SMB_QUERY_FILE_ALL_INFO */ /* level 263 SMB_QUERY_FILE_ALL_INFO */
TRANSACTION2_QPI_REQ *pSMB = NULL; TRANSACTION2_QPI_REQ *pSMB = NULL;
TRANSACTION2_QPI_RSP *pSMBr = NULL; TRANSACTION2_QPI_RSP *pSMBr = NULL;
int rc = 0; int rc = 0;
...@@ -4003,7 +4002,7 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4003,7 +4002,7 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
int name_len; int name_len;
__u16 params, byte_count; __u16 params, byte_count;
/* cFYI(1, "In QPathInfo path %s", searchName); */ /* cFYI(1, "In QPathInfo path %s", search_name); */
QPathInfoRetry: QPathInfoRetry:
rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
(void **) &pSMBr); (void **) &pSMBr);
...@@ -4012,14 +4011,14 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4012,14 +4011,14 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len = name_len =
cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name,
PATH_MAX, nls_codepage, remap); PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */ name_len++; /* trailing null */
name_len *= 2; name_len *= 2;
} else { /* BB improve the check for buffer overruns BB */ } else { /* BB improve the check for buffer overruns BB */
name_len = strnlen(searchName, PATH_MAX); name_len = strnlen(search_name, PATH_MAX);
name_len++; /* trailing null */ name_len++; /* trailing null */
strncpy(pSMB->FileName, searchName, name_len); strncpy(pSMB->FileName, search_name, name_len);
} }
params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */;
...@@ -4064,20 +4063,21 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, ...@@ -4064,20 +4063,21 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon,
else if (legacy && get_bcc(&pSMBr->hdr) < 24) else if (legacy && get_bcc(&pSMBr->hdr) < 24)
rc = -EIO; /* 24 or 26 expected but we do not read rc = -EIO; /* 24 or 26 expected but we do not read
last field */ last field */
else if (pFindData) { else if (data) {
int size; int size;
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
/* On legacy responses we do not read the last field, /*
EAsize, fortunately since it varies by subdialect and * On legacy responses we do not read the last field,
also note it differs on Set vs. Get, ie two bytes or 4 * EAsize, fortunately since it varies by subdialect and
bytes depending but we don't care here */ * also note it differs on Set vs Get, ie two bytes or 4
* bytes depending but we don't care here.
*/
if (legacy) if (legacy)
size = sizeof(FILE_INFO_STANDARD); size = sizeof(FILE_INFO_STANDARD);
else else
size = sizeof(FILE_ALL_INFO); size = sizeof(FILE_ALL_INFO);
memcpy((char *) pFindData, memcpy((char *) data, (char *) &pSMBr->hdr.Protocol +
(char *) &pSMBr->hdr.Protocol +
data_offset, size); data_offset, size);
} else } else
rc = -ENOMEM; rc = -ENOMEM;
......
...@@ -3402,30 +3402,6 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) ...@@ -3402,30 +3402,6 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
return rsize; return rsize;
} }
static int
is_path_accessible(unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, const char *full_path)
{
int rc;
FILE_ALL_INFO *pfile_info;
pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (pfile_info == NULL)
return -ENOMEM;
rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
0 /* not legacy */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == -EOPNOTSUPP || rc == -EINVAL)
rc = SMBQueryInformation(xid, tcon, full_path, pfile_info,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(pfile_info);
return rc;
}
static void static void
cleanup_volume_info_contents(struct smb_vol *volume_info) cleanup_volume_info_contents(struct smb_vol *volume_info)
{ {
...@@ -3703,13 +3679,18 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) ...@@ -3703,13 +3679,18 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
/* check if a whole path is not remote */ /* check if a whole path is not remote */
if (!rc && tcon) { if (!rc && tcon) {
if (!server->ops->is_path_accessible) {
rc = -ENOSYS;
goto mount_fail_check;
}
/* build_path_to_root works only when we have a valid tcon */ /* build_path_to_root works only when we have a valid tcon */
full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon); full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
if (full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto mount_fail_check; goto mount_fail_check;
} }
rc = is_path_accessible(xid, tcon, cifs_sb, full_path); rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
full_path);
if (rc != 0 && rc != -EREMOTE) { if (rc != 0 && rc != -EREMOTE) {
kfree(full_path); kfree(full_path);
goto mount_fail_check; goto mount_fail_check;
......
...@@ -417,6 +417,30 @@ cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon) ...@@ -417,6 +417,30 @@ cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
CIFSSMBQFSAttributeInfo(xid, tcon); CIFSSMBQFSAttributeInfo(xid, tcon);
} }
static int
cifs_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, const char *full_path)
{
int rc;
FILE_ALL_INFO *file_info;
file_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (file_info == NULL)
return -ENOMEM;
rc = CIFSSMBQPathInfo(xid, tcon, full_path, file_info,
0 /* not legacy */, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc == -EOPNOTSUPP || rc == -EINVAL)
rc = SMBQueryInformation(xid, tcon, full_path, file_info,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
kfree(file_info);
return rc;
}
struct smb_version_operations smb1_operations = { struct smb_version_operations smb1_operations = {
.send_cancel = send_nt_cancel, .send_cancel = send_nt_cancel,
.compare_fids = cifs_compare_fids, .compare_fids = cifs_compare_fids,
...@@ -443,6 +467,7 @@ struct smb_version_operations smb1_operations = { ...@@ -443,6 +467,7 @@ struct smb_version_operations smb1_operations = {
.tree_disconnect = CIFSSMBTDis, .tree_disconnect = CIFSSMBTDis,
.get_dfs_refer = CIFSGetDFSRefer, .get_dfs_refer = CIFSGetDFSRefer,
.qfs_tcon = cifs_qfs_tcon, .qfs_tcon = cifs_qfs_tcon,
.is_path_accessible = cifs_is_path_accessible,
}; };
struct smb_version_values smb1_values = { struct smb_version_values smb1_values = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment