[CIFS] Support for mounting to older servers part 2. Add support for
authorSteve French <sfrench@us.ibm.com>
Wed, 24 Aug 2005 03:26:03 +0000 (20:26 -0700)
committerSteve French <sfrench@us.ibm.com>
Wed, 24 Aug 2005 03:26:03 +0000 (20:26 -0700)
legacy getattr (lookup).

Signed-off-by: Steve French (sfrench@us.ibm.com)
fs/cifs/CHANGES
fs/cifs/cifspdu.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/inode.c

index 2137002aecc4aa1f99e2cbf99529b409da1c0a3f..299ed312cea560792fe0d06bd7dc2d48a0a46e82 100644 (file)
@@ -1,6 +1,8 @@
 Version 1.36
 ------------
 Add support for moounting to older pre-CIFS servers such as Windows9x and ME.
+For these older servers, add option for passing netbios name of server in
+on mount (servernetbiosname).
 Add mount option for disabling the default behavior of sending byte range lock
 requests to the server (necessary for certain applications which break with
 mandatory lock behavior such as Evolution), and also mount option for
index 49cc66825309eab46df4d0630e7730647a3417a1..42c16cf32284f8864df529bc340d5e8ae0d2b59c 100644 (file)
@@ -36,6 +36,7 @@
 #define SMB_COM_CLOSE                 0x04 /* triv req/rsp, timestamp ignored */
 #define SMB_COM_DELETE                0x06 /* trivial response */
 #define SMB_COM_RENAME                0x07 /* trivial response */
+#define SMB_COM_QUERY_INFORMATION     0x08 /* aka getattr */
 #define SMB_COM_SETATTR               0x09 /* trivial response */
 #define SMB_COM_LOCKING_ANDX          0x24 /* trivial response */
 #define SMB_COM_COPY                  0x29 /* trivial rsp, fail filename ignrd*/
@@ -885,6 +886,22 @@ typedef struct smb_com_create_directory_rsp {
        __u16 ByteCount;        /* bct = 0 */
 } CREATE_DIRECTORY_RSP;
 
+typedef struct smb_com_query_information_req {
+       struct smb_hdr hdr;     /* wct = 0 */
+       __le16 ByteCount;       /* 1 + namelen + 1 */
+       __u8 BufferFormat;      /* 4 = ASCII */
+       unsigned char FileName[1];
+} QUERY_INFORMATION_REQ;
+
+typedef struct smb_com_query_information_rsp {
+       struct smb_hdr hdr;     /* wct = 10 */
+       __le16 attr;
+       __le32  last_write_time;
+       __le32 size;
+       __u16  reserved[5];
+       __le16 ByteCount;       /* bcc = 0 */
+} QUERY_INFORMATION_RSP;
+
 typedef struct smb_com_setattr_req {
        struct smb_hdr hdr; /* wct = 8 */
        __le16 attr;
index b9b13e3fe79d1c4617244a41946db4a04f924acc..0cc0612eacb468ecc55005874be459a3adcde29e 100644 (file)
@@ -105,6 +105,10 @@ extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName,
                        FILE_ALL_INFO * findData,
                        const struct nls_table *nls_codepage, int remap);
+extern int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
+                        const unsigned char *searchName,
+                        FILE_ALL_INFO * findData,
+                        const struct nls_table *nls_codepage, int remap);
 
 extern int CIFSSMBUnixQPathInfo(const int xid,
                        struct cifsTconInfo *tcon,
index 1292db50fe65649e5d706416de654125a4bd46db..811ab3dffafa4e1cd118c3c7b761879a6ebb9107 100644 (file)
@@ -2200,6 +2200,65 @@ GetExtAttrOut:
 
 #endif /* CONFIG_POSIX */
 
+/* Legacy Query Path Information call for lookup to old servers such
+   as Win9x/WinME */
+int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
+                 const unsigned char *searchName,
+                 FILE_ALL_INFO * pFinfo,
+                 const struct nls_table *nls_codepage, int remap)
+{
+       QUERY_INFORMATION_REQ * pSMB;
+       QUERY_INFORMATION_RSP * pSMBr;
+       int rc = 0;
+       int bytes_returned;
+       int name_len;
+
+       cFYI(1, ("In SMBQPath path %s", searchName)); 
+QInfRetry:
+       rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                    cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
+                                     PATH_MAX, nls_codepage, remap);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+       } else {               
+               name_len = strnlen(searchName, PATH_MAX);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->FileName, searchName, name_len);
+       }
+       pSMB->BufferFormat = 0x04;
+       name_len++; /* account for buffer type byte */  
+       pSMB->hdr.smb_buf_length += (__u16) name_len;
+       pSMB->ByteCount = cpu_to_le16(name_len);
+
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("Send error in QueryInfo = %d", rc));
+       } else if (pFinfo) {            /* decode response */
+               memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
+               pFinfo->AllocationSize = (__le64) pSMBr->size;
+               pFinfo->EndOfFile = (__le64) pSMBr->size;
+               pFinfo->Attributes = (__le32) pSMBr->attr;
+       } else
+               rc = -EIO; /* bad buffer passed in */
+
+       cifs_buf_release(pSMB);
+
+       if (rc == -EAGAIN)
+               goto QInfRetry;
+
+       return rc;
+}
+
+
+
+
 int
 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
                 const unsigned char *searchName,
index 9d61844e89b6d854af3324277ae2d0322f7a2806..c75bae1242dcceaeb2873db3fc075ced44cf0c89 100644 (file)
@@ -1730,8 +1730,9 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
                else
                        cifs_sb->wsize = CIFSMaxBufSize; /* default */
                if(cifs_sb->rsize < PAGE_CACHE_SIZE) {
-                       cifs_sb->rsize = PAGE_CACHE_SIZE;
-                       cERROR(1,("Attempt to set readsize for mount to less than one page (4096)"));
+                       cifs_sb->rsize = PAGE_CACHE_SIZE; 
+                       /* Windows ME does this */
+                       cFYI(1,("Attempt to set readsize for mount to less than one page (4096)"));
                }
                cifs_sb->mnt_uid = volume_info.linux_uid;
                cifs_sb->mnt_gid = volume_info.linux_gid;
index 2d50b3507d13d20c85f57c70ecbb412d52b8600f..34f0168c4041ddc156068a44c366410172815794 100644 (file)
@@ -215,8 +215,18 @@ 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,
-                             cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 
+                             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
+               when server claims no NT SMB support and the above call
+               failed at least once - set flag in tcon or mount */
+               if((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
+                       rc = SMBQueryInformation(xid, pTcon, search_path,
+                                       pfindData, cifs_sb->local_nls, 
+                                       cifs_sb->mnt_cifs_flags &
+                                         CIFS_MOUNT_MAP_SPECIAL_CHR);
+               }
+               
        }
        /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
        if (rc) {