[CIFS] Level 1 QPathInfo needed for proper OS2 support
authorSteve French <sfrench@us.ibm.com>
Thu, 12 Oct 2006 03:28:28 +0000 (03:28 +0000)
committerSteve French <sfrench@us.ibm.com>
Thu, 12 Oct 2006 03:28:28 +0000 (03:28 +0000)
Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/inode.c

index 7dd2f48a4073f918f30fa7bfbb3fa5ab400ea3f6..4a4fd2dbca6318978af328abd36af2458e074a13 100644 (file)
@@ -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,
index 79a01d35a783d39f266ec963daf7b1270948d54f..6f50f2bc8870e418fb9df8b4bb70ba8027bfc3e9 100644 (file)
@@ -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;
        }
index 06dbce3a1815267fb9660d91992e19c6bf2631c3..fe6d21f99964428ce9a55a1c768d8a60b68197f5 100644 (file)
@@ -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