diff options
-rw-r--r-- | fs/cifs/cifsglob.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 12 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 60 | ||||
-rw-r--r-- | fs/cifs/connect.c | 31 | ||||
-rw-r--r-- | fs/cifs/smb1ops.c | 25 |
5 files changed, 69 insertions, 62 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index acfa68569f3..f711d666e3d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -215,6 +215,9 @@ struct smb_version_operations { unsigned int *, const struct nls_table *, int); /* informational QFS call */ 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 { diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 4857965b22d..b9967adeaa9 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -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, u16 netfid, FILE_ALL_INFO *pFindData); extern int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *findData, - int legacy /* whether to use old info level */, - const struct nls_table *nls_codepage, int remap); + const char *search_Name, FILE_ALL_INFO *data, + int legacy /* whether to use old info level */, + const struct nls_table *nls_codepage, int remap); extern int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *findData, - const struct nls_table *nls_codepage, int remap); + const char *search_name, FILE_ALL_INFO *data, + const struct nls_table *nls_codepage, int remap); extern int CIFSSMBUnixQFileInfo(const unsigned int xid, struct cifs_tcon *tcon, u16 netfid, FILE_UNIX_BASIC_INFO *pFindData); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index af859c325db..84a53380e12 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -3853,10 +3853,10 @@ setCifsAclRetry: /* Legacy Query Path Information call for lookup to old servers such as Win9x/WinME */ -int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *pFinfo, - const struct nls_table *nls_codepage, int remap) +int +SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, + const char *search_name, FILE_ALL_INFO *data, + const struct nls_table *nls_codepage, int remap) { QUERY_INFORMATION_REQ *pSMB; QUERY_INFORMATION_RSP *pSMBr; @@ -3864,7 +3864,7 @@ int SMBQueryInformation(const unsigned int xid, struct cifs_tcon *tcon, int bytes_returned; int name_len; - cFYI(1, "In SMBQPath path %s", searchName); + cFYI(1, "In SMBQPath path %s", search_name); QInfRetry: rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -3874,14 +3874,14 @@ QInfRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, - searchName, PATH_MAX, nls_codepage, + search_name, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { - name_len = strnlen(searchName, PATH_MAX); + name_len = strnlen(search_name, PATH_MAX); name_len++; /* trailing null */ - strncpy(pSMB->FileName, searchName, name_len); + strncpy(pSMB->FileName, search_name, name_len); } pSMB->BufferFormat = 0x04; name_len++; /* account for buffer type byte */ @@ -3892,23 +3892,23 @@ QInfRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, "Send error in QueryInfo = %d", rc); - } else if (pFinfo) { + } else if (data) { struct timespec ts; __u32 time = le32_to_cpu(pSMBr->last_write_time); /* decode response */ /* 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_sec = time; /* decode time fields */ - pFinfo->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts)); - pFinfo->LastWriteTime = pFinfo->ChangeTime; - pFinfo->LastAccessTime = 0; - pFinfo->AllocationSize = + data->ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(ts)); + data->LastWriteTime = data->ChangeTime; + data->LastAccessTime = 0; + data->AllocationSize = cpu_to_le64(le32_to_cpu(pSMBr->size)); - pFinfo->EndOfFile = pFinfo->AllocationSize; - pFinfo->Attributes = + data->EndOfFile = data->AllocationSize; + data->Attributes = cpu_to_le32(le16_to_cpu(pSMBr->attr)); } else rc = -EIO; /* bad buffer passed in */ @@ -3990,12 +3990,11 @@ QFileInfoRetry: int CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, - const unsigned char *searchName, - FILE_ALL_INFO *pFindData, + const char *search_name, FILE_ALL_INFO *data, int legacy /* old style infolevel */, 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_RSP *pSMBr = NULL; int rc = 0; @@ -4003,7 +4002,7 @@ CIFSSMBQPathInfo(const unsigned int xid, struct cifs_tcon *tcon, int name_len; __u16 params, byte_count; -/* cFYI(1, "In QPathInfo path %s", searchName); */ + /* cFYI(1, "In QPathInfo path %s", search_name); */ QPathInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4012,14 +4011,14 @@ QPathInfoRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, + cifsConvertToUTF16((__le16 *) pSMB->FileName, search_name, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } 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 */ - strncpy(pSMB->FileName, searchName, name_len); + strncpy(pSMB->FileName, search_name, name_len); } params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; @@ -4064,20 +4063,21 @@ QPathInfoRetry: else if (legacy && get_bcc(&pSMBr->hdr) < 24) rc = -EIO; /* 24 or 26 expected but we do not read last field */ - else if (pFindData) { + else if (data) { int size; __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 - also note it differs on Set vs. Get, ie two bytes or 4 - bytes depending but we don't care here */ + /* + * On legacy responses we do not read the last field, + * EAsize, fortunately since it varies by subdialect and + * also note it differs on Set vs Get, ie two bytes or 4 + * bytes depending but we don't care here. + */ if (legacy) size = sizeof(FILE_INFO_STANDARD); else size = sizeof(FILE_ALL_INFO); - memcpy((char *) pFindData, - (char *) &pSMBr->hdr.Protocol + + memcpy((char *) data, (char *) &pSMBr->hdr.Protocol + data_offset, size); } else rc = -ENOMEM; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 80807923a54..34588fe11c5 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3402,30 +3402,6 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) 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 cleanup_volume_info_contents(struct smb_vol *volume_info) { @@ -3703,13 +3679,18 @@ remote_path_check: /* check if a whole path is not remote */ 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 */ full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon); if (full_path == NULL) { rc = -ENOMEM; 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) { kfree(full_path); goto mount_fail_check; diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 96eb06ff9dd..43f3881ad3b 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -417,6 +417,30 @@ cifs_qfs_tcon(const unsigned int xid, struct cifs_tcon *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 = { .send_cancel = send_nt_cancel, .compare_fids = cifs_compare_fids, @@ -443,6 +467,7 @@ struct smb_version_operations smb1_operations = { .tree_disconnect = CIFSSMBTDis, .get_dfs_refer = CIFSGetDFSRefer, .qfs_tcon = cifs_qfs_tcon, + .is_path_accessible = cifs_is_path_accessible, }; struct smb_version_values smb1_values = { |