Commit acf1a1b1 authored by Steve French's avatar Steve French

[CIFS] Level 1 QPathInfo needed for proper OS2 support

Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent ddae957d
......@@ -119,6 +119,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,
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,
const unsigned char *searchName,
......
......@@ -2969,6 +2969,7 @@ int
CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
FILE_ALL_INFO * pFindData,
int legacy /* old style infolevel */,
const struct nls_table *nls_codepage, int remap)
{
/* level 263 SMB_QUERY_FILE_ALL_INFO */
......@@ -3017,7 +3018,10 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
byte_count = params + 1 /* pad */ ;
pSMB->TotalParameterCount = cpu_to_le16(params);
pSMB->ParameterCount = pSMB->TotalParameterCount;
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
if(legacy)
pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
else
pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
pSMB->Reserved4 = 0;
pSMB->hdr.smb_buf_length += byte_count;
pSMB->ByteCount = cpu_to_le16(byte_count);
......@@ -3029,13 +3033,24 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
if (rc || (pSMBr->ByteCount < 40))
if (rc) /* BB add auto retry on EOPNOTSUPP? */
rc = -EIO;
else if (!legacy && (pSMBr->ByteCount < 40))
rc = -EIO; /* bad smb */
else if(legacy && (pSMBr->ByteCount < 24))
rc = -EIO; /* 24 or 26 expected but we do not read last field */
else if (pFindData){
int size;
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
if(legacy) /* we do not read the last field, EAsize, fortunately
since it varies by subdialect and on Set vs. Get, is
two bytes or 4 bytes depending but we don't care here */
size = sizeof(FILE_INFO_STANDARD);
else
size = sizeof(FILE_ALL_INFO);
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
data_offset, sizeof (FILE_ALL_INFO));
data_offset, size);
} else
rc = -ENOMEM;
}
......
......@@ -338,6 +338,7 @@ int cifs_get_inode_info(struct inode **pinode,
pfindData = (FILE_ALL_INFO *)buf;
/* could do find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
0 /* not legacy */,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB optimize code so we do not make the above call
......@@ -385,8 +386,10 @@ int cifs_get_inode_info(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
if (*pinode == NULL)
if (*pinode == NULL) {
kfree(buf);
return -ENOMEM;
}
/* 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
......
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