summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-10-12 03:28:28 +0000
committerSteve French <sfrench@us.ibm.com>2006-10-12 03:28:28 +0000
commitacf1a1b1043327b2179ea529730358e58c7c277e (patch)
tree6753f8c0a8626e9159d4c9d5dbb2f3c4b5f87eba
parentddae957da48cc381c1472a8909905e1818e4afdd (diff)
downloadop-kernel-dev-acf1a1b1043327b2179ea529730358e58c7c277e.zip
op-kernel-dev-acf1a1b1043327b2179ea529730358e58c7c277e.tar.gz
[CIFS] Level 1 QPathInfo needed for proper OS2 support
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/cifsproto.h1
-rw-r--r--fs/cifs/cifssmb.c21
-rw-r--r--fs/cifs/inode.c5
3 files changed, 23 insertions, 4 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7dd2f48..4a4fd2d 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -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,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 79a01d3..6f50f2b 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -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 @@ QPathInfoRetry:
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 @@ QPathInfoRetry:
} 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;
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 06dbce3..fe6d21f 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -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
OpenPOWER on IntegriCloud