vserver 2.0 rc7
[linux-2.6.git] / fs / cifs / cifssmb.c
index 81a6c9e..3c628bf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifssmb.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   Contains the routines for constructing the SMB PDUs themselves
@@ -75,9 +75,11 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
                }
        }
        write_unlock(&GlobalSMBSeslock);
-       /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
+       /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
+          to this tcon */
 }
 
+/* If the return code is zero, this function must fill in request_buf pointer */
 static int
 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
         void **request_buf /* returned */)
@@ -88,11 +90,12 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
           check for tcp and smb session status done differently
           for those three - in the calling routine */
        if(tcon) {
-               if((tcon->ses) && (tcon->ses->server)){
+               if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
+                                 (tcon->ses->server)){
                        struct nls_table *nls_codepage;
                                /* Give Demultiplex thread up to 10 seconds to 
-                                       reconnect, should be greater than cifs socket
-                                       timeout which is 7 seconds */
+                                  reconnect, should be greater than cifs socket
+                                  timeout which is 7 seconds */
                        while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
                                wait_event_interruptible_timeout(tcon->ses->server->response_q,
                                        (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
@@ -102,8 +105,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                                           (tcon->ses->status == CifsExiting)) {
                                                cFYI(1,("gave up waiting on reconnect in smb_init"));
                                                return -EHOSTDOWN;
-                                       } /* else "hard" mount - keep retrying until 
-                                       process is killed or server comes back up */
+                                       } /* else "hard" mount - keep retrying
+                                            until process is killed or server
+                                            comes back on-line */
                                } else /* TCP session is reestablished now */
                                        break;
                                 
@@ -114,23 +118,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                simultaneously reconnect the same SMB session */
                        down(&tcon->ses->sesSem);
                        if(tcon->ses->status == CifsNeedReconnect)
-                               rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+                               rc = cifs_setup_session(0, tcon->ses, 
+                                                       nls_codepage);
                        if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
                                mark_open_files_invalid(tcon);
-                               rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
-                                       nls_codepage);
+                               rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
+                                       nls_codepage);
                                up(&tcon->ses->sesSem);
                                if(rc == 0)
                                        atomic_inc(&tconInfoReconnectCount);
 
                                cFYI(1, ("reconnect tcon rc = %d", rc));
                                /* Removed call to reopen open files here - 
-                                       it is safer (and faster) to reopen files
-                                       one at a time as needed in read and write */
+                                  it is safer (and faster) to reopen files
+                                  one at a time as needed in read and write */
 
                                /* Check if handle based operation so we 
-                                       know whether we can continue or not without
-                                       returning to caller to reset file handle */
+                                  know whether we can continue or not without
+                                  returning to caller to reset file handle */
                                switch(smb_command) {
                                        case SMB_COM_READ_ANDX:
                                        case SMB_COM_WRITE_ANDX:
@@ -154,7 +159,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                return rc;
 
        *request_buf = cifs_small_buf_get();
-       if (*request_buf == 0) {
+       if (*request_buf == NULL) {
                /* BB should we add a retry in here if not a writepage? */
                return -ENOMEM;
        }
@@ -169,6 +174,7 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
        return rc;
 }  
 
+/* If the return code is zero, this function must fill in request_buf pointer */
 static int
 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
         void **request_buf /* returned */ ,
@@ -180,22 +186,25 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
           check for tcp and smb session status done differently
           for those three - in the calling routine */
        if(tcon) {
-               if((tcon->ses) && (tcon->ses->server)){
+               if((tcon->ses) && (tcon->ses->status != CifsExiting) && 
+                                 (tcon->ses->server)){
                        struct nls_table *nls_codepage;
-                               /* Give Demultiplex thread up to 10 seconds to 
-                                       reconnect, should be greater than cifs socket
-                                       timeout which is 7 seconds */
+                               /* Give Demultiplex thread up to 10 seconds to
+                                  reconnect, should be greater than cifs socket
+                                  timeout which is 7 seconds */
                        while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
                                wait_event_interruptible_timeout(tcon->ses->server->response_q,
                                        (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
-                               if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
+                               if(tcon->ses->server->tcpStatus == 
+                                               CifsNeedReconnect) {
                                        /* on "soft" mounts we wait once */
                                        if((tcon->retry == FALSE) || 
                                           (tcon->ses->status == CifsExiting)) {
                                                cFYI(1,("gave up waiting on reconnect in smb_init"));
                                                return -EHOSTDOWN;
-                                       } /* else "hard" mount - keep retrying until 
-                                       process is killed or server comes back up */
+                                       } /* else "hard" mount - keep retrying
+                                            until process is killed or server
+                                            comes on-line */
                                } else /* TCP session is reestablished now */
                                        break;
                                 
@@ -206,23 +215,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                simultaneously reconnect the same SMB session */
                        down(&tcon->ses->sesSem);
                        if(tcon->ses->status == CifsNeedReconnect)
-                               rc = cifs_setup_session(0, tcon->ses, nls_codepage);
+                               rc = cifs_setup_session(0, tcon->ses, 
+                                                       nls_codepage);
                        if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
                                mark_open_files_invalid(tcon);
-                               rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
-                                       nls_codepage);
+                               rc = CIFSTCon(0, tcon->ses, tcon->treeName,
+                                             tcon, nls_codepage);
                                up(&tcon->ses->sesSem);
                                if(rc == 0)
                                        atomic_inc(&tconInfoReconnectCount);
 
                                cFYI(1, ("reconnect tcon rc = %d", rc));
                                /* Removed call to reopen open files here - 
-                                       it is safer (and faster) to reopen files
-                                       one at a time as needed in read and write */
+                                  it is safer (and faster) to reopen files
+                                  one at a time as needed in read and write */
 
                                /* Check if handle based operation so we 
-                                       know whether we can continue or not without
-                                       returning to caller to reset file handle */
+                                  know whether we can continue or not without
+                                  returning to caller to reset file handle */
                                switch(smb_command) {
                                        case SMB_COM_READ_ANDX:
                                        case SMB_COM_WRITE_ANDX:
@@ -246,7 +256,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
                return rc;
 
        *request_buf = cifs_buf_get();
-       if (*request_buf == 0) {
+       if (*request_buf == NULL) {
                /* BB should we add a retry in here if not a writepage? */
                return -ENOMEM;
        }
@@ -284,7 +294,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB)
                        if(total_size < 512) {
                                total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
                                /* BCC le converted in SendReceive */
-                               pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + 
+                               pBCC = (pSMB->hdr.WordCount * 2) + 
+                                       sizeof(struct smb_hdr) +
                                        (char *)pSMB;
                                if((total_size <= (*(u16 *)pBCC)) && 
                                   (total_size < 
@@ -335,8 +346,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc == 0) {
                server->secMode = pSMBr->SecurityMode;  
-               server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
-               /* one byte - no need to convert this or EncryptionKeyLen from le,*/
+               server->secType = NTLM; /* BB override default for 
+                                          NTLMv2 or kerberos v5 */
+               /* one byte - no need to convert this or EncryptionKeyLen
+                  from little endian */
                server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
                /* probably no need to store and check maxvcs */
                server->maxBuf =
@@ -372,7 +385,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
                                                pSMBr->u.extended_response.
                                                GUID, 16) != 0) {
                                                cFYI(1,
-                                                       ("UID of server does not match previous connection to same ip address"));
+                                                    ("UID of server does not match previous connection to same ip address"));
                                                memcpy(server->
                                                        server_GUID,
                                                        pSMBr->u.
@@ -448,21 +461,22 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
                return 0;  
        }
 
-       if((tcon->ses == 0) || (tcon->ses->server == 0)) {    
+       if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {    
                up(&tcon->tconSem);
                return -EIO;
        }
-       rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
+       rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, 
+                           (void **)&smb_buffer);
        if (rc) {
                up(&tcon->tconSem);
                return rc;
        } else {
                smb_buffer_response = smb_buffer; /* BB removeme BB */
-    }
+       }
        rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
                         &length, 0);
        if (rc)
-               cFYI(1, (" Tree disconnect failed %d", rc));
+               cFYI(1, ("Tree disconnect failed %d", rc));
 
        if (smb_buffer)
                cifs_small_buf_release(smb_buffer);
@@ -496,6 +510,11 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
                return -EBUSY;
        }
        rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
+       if (rc) {
+               up(&ses->sesSem);
+               return rc;
+       }
+
        smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
        
        if(ses->server) {
@@ -504,11 +523,6 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
                        pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
        }
 
-       if (rc) {
-               up(&ses->sesSem);
-               return rc;
-       }
-
        pSMB->hdr.Uid = ses->Suid;
 
        pSMB->AndXCommand = 0xFF;
@@ -536,8 +550,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
 }
 
 int
-CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
-              const char *fileName, const struct nls_table *nls_codepage)
+CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+              const struct nls_table *nls_codepage, int remap)
 {
        DELETE_FILE_REQ *pSMB = NULL;
        DELETE_FILE_RSP *pSMBr = NULL;
@@ -553,12 +567,11 @@ DelFileRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->fileName, fileName, 
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {                /* BB improve the check for buffer overruns BB */
+       } else {                /* BB improve check for buffer overruns BB */
                name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->fileName, fileName, name_len);
@@ -579,8 +592,7 @@ DelFileRetry:
         }
 #endif
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto DelFileRetry;
 
@@ -588,8 +600,8 @@ DelFileRetry:
 }
 
 int
-CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
-            const char *dirName, const struct nls_table *nls_codepage)
+CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, 
+            const struct nls_table *nls_codepage, int remap)
 {
        DELETE_DIRECTORY_REQ *pSMB = NULL;
        DELETE_DIRECTORY_RSP *pSMBr = NULL;
@@ -605,12 +617,11 @@ RmDirRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
-                               /* find define for this maxpathcomponent */
-                               , nls_codepage);
+               name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
+                                        PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {                /* BB improve the check for buffer overruns BB */
+       } else {                /* BB improve check for buffer overruns BB */
                name_len = strnlen(dirName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->DirName, dirName, name_len);
@@ -630,8 +641,7 @@ RmDirRetry:
         }
 #endif
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto RmDirRetry;
        return rc;
@@ -639,7 +649,7 @@ RmDirRetry:
 
 int
 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
-            const char *name, const struct nls_table *nls_codepage)
+            const char *name, const struct nls_table *nls_codepage, int remap)
 {
        int rc = 0;
        CREATE_DIRECTORY_REQ *pSMB = NULL;
@@ -655,12 +665,11 @@ MkDirRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
-                                        /* find define for this maxpathcomponent */
-                                        , nls_codepage);
+               name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name, 
+                                           PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
-       } else {                /* BB improve the check for buffer overruns BB */
+       } else {                /* BB improve check for buffer overruns BB */
                name_len = strnlen(name, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->DirName, name, name_len);
@@ -679,8 +688,7 @@ MkDirRetry:
                atomic_inc(&tcon->num_mkdirs);
         }
 #endif
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto MkDirRetry;
        return rc;
@@ -691,7 +699,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
            const char *fileName, const int openDisposition,
            const int access_flags, const int create_options, __u16 * netfid,
            int *pOplock, FILE_ALL_INFO * pfile_info, 
-           const struct nls_table *nls_codepage)
+           const struct nls_table *nls_codepage, int remap)
 {
        int rc = -EACCES;
        OPEN_REQ *pSMB = NULL;
@@ -711,14 +719,12 @@ openRetry:
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                count = 1;      /* account for one byte pad to word boundary */
                name_len =
-                   cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
-                                 fileName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
+                                    fileName, PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->NameLength = cpu_to_le16(name_len);
-       } else {                /* BB improve the check for buffer overruns BB */
+       } else {                /* BB improve check for buffer overruns BB */
                count = 0;      /* no pad */
                name_len = strnlen(fileName, PATH_MAX);
                name_len++;     /* trailing null */
@@ -747,7 +753,8 @@ openRetry:
        pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
        pSMB->CreateDisposition = cpu_to_le32(openDisposition);
        pSMB->CreateOptions = cpu_to_le32(create_options);
-       pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
+       /* BB Expirement with various impersonation levels and verify */
+       pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
        pSMB->SecurityFlags =
            SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
 
@@ -761,7 +768,7 @@ openRetry:
        if (rc) {
                cFYI(1, ("Error in Open = %d", rc));
        } else {
-               *pOplock = pSMBr->OplockLevel;  /* one byte no need to le_to_cpu */
+               *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
                *netfid = pSMBr->Fid;   /* cifs fid stays in le */
                /* Let caller know file was created so we can set the mode. */
                /* Do we care about the CreateAction in any other cases? */
@@ -780,8 +787,7 @@ openRetry:
                atomic_inc(&tcon->num_opens);
 #endif
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto openRetry;
        return rc;
@@ -802,6 +808,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
        char *pReadData = NULL;
        int bytes_returned;
 
+       cFYI(1,("Reading %d bytes on fid %d",count,netfid));
+
        *nbytes = 0;
        rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -817,8 +825,8 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
        pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
        pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
        pSMB->Remaining = 0;
-       pSMB->MaxCount = cpu_to_le16(count);
-       pSMB->MaxCountHigh = 0;
+       pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
+       pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
        pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
@@ -826,8 +834,11 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
        if (rc) {
                cERROR(1, ("Send error in read = %d", rc));
        } else {
-               __u16 data_length = le16_to_cpu(pSMBr->DataLength);
+               int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
+               data_length = data_length << 16;
+               data_length += le16_to_cpu(pSMBr->DataLength);
                *nbytes = data_length;
+
                /*check that DataLength would not go beyond end of SMB */
                if ((data_length > CIFSMaxBufSize) 
                                || (data_length > count)) {
@@ -846,12 +857,10 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
                            memcpy(*buf,pReadData,data_length);
                }
        }
-       if (pSMB) {
-               if(*buf)
-                       cifs_buf_release(pSMB);
-               else
-                       *buf = (char *)pSMB;
-       }
+       if(*buf)
+               cifs_buf_release(pSMB);
+       else
+               *buf = (char *)pSMB;
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls 
                since file handle passed in no longer valid */
@@ -868,9 +877,10 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        WRITE_REQ *pSMB = NULL;
        WRITE_RSP *pSMBr = NULL;
        int bytes_returned;
-       unsigned bytes_sent;
+       __u32 bytes_sent;
        __u16 byte_count;
 
+       /* cFYI(1,("write at %lld %d bytes",offset,count));*/
        rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
@@ -886,31 +896,39 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        pSMB->Reserved = 0xFFFFFFFF;
        pSMB->WriteMode = 0;
        pSMB->Remaining = 0;
-       /* BB can relax this if buffer is big enough in some cases - ie we can 
-       send more  if LARGE_WRITE_X capability returned by the server and if
+
+       /* Can increase buffer size if buffer is big enough in some cases - ie we 
+       can send more if LARGE_WRITE_X capability returned by the server and if
        our buffer is big enough or if we convert to iovecs on socket writes
        and eliminate the copy to the CIFS buffer */
-       bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
+       if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
+               bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
+       } else {
+               bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
+                        & ~0xFF;
+       }
+
        if (bytes_sent > count)
                bytes_sent = count;
-       pSMB->DataLengthHigh = 0;
        pSMB->DataOffset =
            cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
-    if(buf)
+       if(buf)
            memcpy(pSMB->Data,buf,bytes_sent);
-       else if(ubuf)
-               copy_from_user(pSMB->Data,ubuf,bytes_sent);
-    else {
-               /* No buffer */
-               if(pSMB)
+       else if(ubuf) {
+               if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
                        cifs_buf_release(pSMB);
+                       return -EFAULT;
+               }
+       } else {
+               /* No buffer */
+               cifs_buf_release(pSMB);
                return -EINVAL;
        }
 
-       byte_count = bytes_sent + 1 /* pad */ ;
-       pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
-       pSMB->DataLengthHigh = 0;
-       pSMB->hdr.smb_buf_length += byte_count;
+       byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
+       pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
+       pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
+       pSMB->hdr.smb_buf_length += bytes_sent+1;
        pSMB->ByteCount = cpu_to_le16(byte_count);
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
@@ -918,11 +936,13 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        if (rc) {
                cFYI(1, ("Send error in write = %d", rc));
                *nbytes = 0;
-       } else
-               *nbytes = le16_to_cpu(pSMBr->Count);
+       } else {
+               *nbytes = le16_to_cpu(pSMBr->CountHigh);
+               *nbytes = (*nbytes) << 16;
+               *nbytes += le16_to_cpu(pSMBr->Count);
+       }
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls 
                since file handle passed in no longer valid */
@@ -944,10 +964,12 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
        __u16 byte_count;
 
        rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
-       pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
     
-    if (rc)
+       if (rc)
                return rc;
+       
+       pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
+
        /* tcon and ses pointer are checked in smb_init */
        if (tcon->ses->server == NULL)
                return -ECONNABORTED;
@@ -980,8 +1002,7 @@ int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
        } else
                *nbytes = le16_to_cpu(pSMBr->Count);
 
-       if (pSMB)
-               cifs_small_buf_release(pSMB);
+       cifs_small_buf_release(pSMB);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls 
                since file handle passed in no longer valid */
@@ -1004,11 +1025,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        __u16 count;
 
        cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
-       rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
+
        if (rc)
                return rc;
 
+       pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
+
        if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
                timeout = -1; /* no response expected */
                pSMB->Timeout = 0;
@@ -1046,8 +1069,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
        if (rc) {
                cFYI(1, ("Send error in Lock = %d", rc));
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_small_buf_release(pSMB);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls 
        since file handle passed in no longer valid */
@@ -1065,12 +1087,13 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
 
 /* do not retry on dead session on close */
        rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
-       pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
        if(rc == -EAGAIN)
                return 0;
        if (rc)
                return rc;
 
+       pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
+
        pSMB->FileID = (__u16) smb_file_id;
        pSMB->LastWriteTime = 0;
        pSMB->ByteCount = 0;
@@ -1083,8 +1106,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
                }
        }
 
-       if (pSMB)
-               cifs_small_buf_release(pSMB);
+       cifs_small_buf_release(pSMB);
 
        /* Since session is dead, file will be closed on server already */
        if(rc == -EAGAIN)
@@ -1096,7 +1118,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
 int
 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
              const char *fromName, const char *toName,
-             const struct nls_table *nls_codepage)
+             const struct nls_table *nls_codepage, int remap)
 {
        int rc = 0;
        RENAME_REQ *pSMB = NULL;
@@ -1119,18 +1141,16 @@ renameRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, 
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->OldFileName[name_len] = 0x04;     /* pad */
        /* protocol requires ASCII signature byte on Unicode string */
                pSMB->OldFileName[name_len + 1] = 0x00;
                name_len2 =
-                   cifs_strtoUCS((wchar_t *) & pSMB->
-                                 OldFileName[name_len + 2], toName, PATH_MAX,
-                                 nls_codepage);
+                   cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
+                                    toName, PATH_MAX, nls_codepage, remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {                /* BB improve the check for buffer overruns BB */
@@ -1161,8 +1181,7 @@ renameRetry:
        }
 #endif
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
                goto renameRetry;
@@ -1171,7 +1190,8 @@ renameRetry:
 }
 
 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 
-               int netfid, char * target_name, const struct nls_table * nls_codepage) 
+               int netfid, char * target_name, 
+               const struct nls_table * nls_codepage, int remap)
 {
        struct smb_com_transaction2_sfi_req *pSMB  = NULL;
        struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
@@ -1216,9 +1236,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
        /* unicode only call */
        if(target_name == NULL) {
                sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
-               len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
+               len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+                                       dummy_string, 24, nls_codepage, remap);
        } else {
-               len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
+               len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
+                                       target_name, PATH_MAX, nls_codepage, remap);
        }
        rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
        count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
@@ -1241,8 +1263,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
                atomic_inc(&pTcon->num_t2renames);
        }
 #endif
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls
                since file handle passed in no longer valid */
@@ -1253,7 +1274,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
 int
 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 
             const __u16 target_tid, const char *toName, const int flags,
-            const struct nls_table *nls_codepage)
+            const struct nls_table *nls_codepage, int remap)
 {
        int rc = 0;
        COPY_REQ *pSMB = NULL;
@@ -1275,18 +1296,16 @@ copyRetry:
        pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
-                               fromName, 
-                               PATH_MAX /* find define for this maxpathcomponent */,
-                               nls_codepage);
+               name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName, 
+                                           fromName, PATH_MAX, nls_codepage,
+                                           remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->OldFileName[name_len] = 0x04;     /* pad */
                /* protocol requires ASCII signature byte on Unicode string */
                pSMB->OldFileName[name_len + 1] = 0x00;
-               name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
-                               OldFileName[name_len + 2], toName, PATH_MAX,
-                               nls_codepage);
+               name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], 
+                               toName, PATH_MAX, nls_codepage, remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {                /* BB improve the check for buffer overruns BB */
@@ -1415,7 +1434,7 @@ createSymLinkRetry:
 int
 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
                       const char *fromName, const char *toName,
-                      const struct nls_table *nls_codepage)
+                      const struct nls_table *nls_codepage, int remap)
 {
        TRANSACTION2_SPI_REQ *pSMB = NULL;
        TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -1434,9 +1453,8 @@ createHardLinkRetry:
                return rc;
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
-                                        /* find define for this maxpathcomponent */
-                                        , nls_codepage);
+               name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
+                                           PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
 
@@ -1458,9 +1476,8 @@ createHardLinkRetry:
        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len_target =
-                   cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
+                                    nls_codepage, remap);
                name_len_target++;      /* trailing null */
                name_len_target *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -1492,8 +1509,7 @@ createHardLinkRetry:
                cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
        }
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto createHardLinkRetry;
 
@@ -1503,7 +1519,7 @@ createHardLinkRetry:
 int
 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
                   const char *fromName, const char *toName,
-                  const struct nls_table *nls_codepage)
+                  const struct nls_table *nls_codepage, int remap)
 {
        int rc = 0;
        NT_RENAME_REQ *pSMB = NULL;
@@ -1530,17 +1546,15 @@ winCreateHardLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->OldFileName[name_len] = 0;        /* pad */
                pSMB->OldFileName[name_len + 1] = 0x04; 
                name_len2 =
-                   cifs_strtoUCS((wchar_t *) & pSMB->
-                                 OldFileName[name_len + 2], toName, PATH_MAX,
-                                 nls_codepage);
+                   cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], 
+                                    toName, PATH_MAX, nls_codepage, remap);
                name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
                name_len2 *= 2; /* convert to bytes */
        } else {                /* BB improve the check for buffer overruns BB */
@@ -1564,8 +1578,7 @@ winCreateHardLinkRetry:
        if (rc) {
                cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto winCreateHardLinkRetry;
 
@@ -1651,6 +1664,7 @@ querySymLinkRetry:
                                name_len = UniStrnlen((wchar_t *) ((char *)
                                        &pSMBr->hdr.Protocol +data_offset),
                                        min_t(const int, buflen,count) / 2);
+                       /* BB FIXME investigate remapping reserved chars here */
                                cifs_strfromUCS_le(symlinkinfo,
                                        (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
                                                data_offset),
@@ -1665,15 +1679,12 @@ querySymLinkRetry:
        /* just in case so calling code does not go off the end of buffer */
                }
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto querySymLinkRetry;
        return rc;
 }
 
-
-
 int
 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName,
@@ -1723,9 +1734,23 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        rc = -EIO;      /* bad smb */
                else {
                        if(data_count && (data_count < 2048)) {
-               /* could also validate reparse tag && better check name length */
+                               char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
+
                                struct reparse_data * reparse_buf = (struct reparse_data *)
                                        ((char *)&pSMBr->hdr.Protocol + data_offset);
+                               if((char*)reparse_buf >= end_of_smb) {
+                                       rc = -EIO;
+                                       goto qreparse_out;
+                               }
+                               if((reparse_buf->LinkNamesBuf + 
+                                       reparse_buf->TargetNameOffset +
+                                       reparse_buf->TargetNameLen) >
+                                               end_of_smb) {
+                                       cFYI(1,("reparse buf extended beyond SMB"));
+                                       rc = -EIO;
+                                       goto qreparse_out;
+                               }
+                               
                                if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
                                        name_len = UniStrnlen((wchar_t *)
                                                        (reparse_buf->LinkNamesBuf + 
@@ -1749,6 +1774,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                        cFYI(1,("readlink result - %s ",symlinkinfo));
                }
        }
+qreparse_out:
        if (pSMB)
                cifs_buf_release(pSMB);
 
@@ -1773,7 +1799,8 @@ static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace
 }
 
 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
-static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
+static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
+                               const int acl_type,const int size_of_data_area)
 {
        int size =  0;
        int i;
@@ -1826,7 +1853,7 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const in
        return size;
 }
 
-__u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
+static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
                        const posix_acl_xattr_entry * local_ace)
 {
        __u16 rc = 0; /* 0 = ACL converted ok */
@@ -1844,7 +1871,7 @@ __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
 }
 
 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
-__u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
+static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
                const int acl_type)
 {
        __u16 rc = 0;
@@ -1892,7 +1919,7 @@ int
 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
                         const unsigned char *searchName,
                         char *acl_inf, const int buflen, const int acl_type,
-                        const struct nls_table *nls_codepage)
+                        const struct nls_table *nls_codepage, int remap)
 {
 /* SMB_QUERY_POSIX_ACL */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -1912,15 +1939,14 @@ queryAclRetry:
                                                                                                                                              
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                       cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-                               /* BB fixme find define for this maxpathcomponent */
-                               , nls_codepage);
+                       cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
+                                        PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
                pSMB->FileName[name_len] = 0;
                pSMB->FileName[name_len+1] = 0;
        } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX /* BB fixme */);
+               name_len = strnlen(searchName, PATH_MAX);
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, searchName, name_len);
        }
@@ -1969,8 +1995,7 @@ queryAclRetry:
                                buflen,acl_type,count);
                }
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto queryAclRetry;
        return rc;
@@ -1979,8 +2004,9 @@ queryAclRetry:
 int
 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
                         const unsigned char *fileName,
-                        const char *local_acl, const int buflen, const int acl_type,
-                        const struct nls_table *nls_codepage)
+                        const char *local_acl, const int buflen, 
+                       const int acl_type,
+                        const struct nls_table *nls_codepage, int remap)
 {
        struct smb_com_transaction2_spi_req *pSMB = NULL;
        struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -1996,11 +2022,10 @@ setAclRetry:
                       (void **) &pSMBr);
        if (rc)
                return rc;
-                                                                                                                       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                       cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-                               /* BB fixme find define for this maxpathcomponent */
-                               , nls_codepage);
+                       cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, 
+                                     PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -2049,20 +2074,102 @@ setAclRetry:
        }
 
 setACLerrorExit:
-       if (pSMB)
-               cifs_buf_release(pSMB);
-                                                                                                               if (rc == -EAGAIN)
+       cifs_buf_release(pSMB);
+       if (rc == -EAGAIN)
                goto setAclRetry;
-                                                                                                               return rc;
+       return rc;
+}
+
+/* BB fix tabs in this function FIXME BB */
+int
+CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
+                const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
+{
+        int rc = 0;
+        struct smb_t2_qfi_req *pSMB = NULL;
+        struct smb_t2_qfi_rsp *pSMBr = NULL;
+        int bytes_returned;
+        __u16 params, byte_count;
+
+        cFYI(1,("In GetExtAttr"));
+        if(tcon == NULL)
+                return -ENODEV;
+
+GetExtAttrRetry:
+        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                      (void **) &pSMBr);
+        if (rc)
+                return rc;
+
+        params = 2 /* level */ +2 /* fid */;
+        pSMB->t2.TotalDataCount = 0;
+        pSMB->t2.MaxParameterCount = cpu_to_le16(4);
+        /* BB find exact max data count below from sess structure BB */
+        pSMB->t2.MaxDataCount = cpu_to_le16(4000);
+        pSMB->t2.MaxSetupCount = 0;
+        pSMB->t2.Reserved = 0;
+        pSMB->t2.Flags = 0;
+        pSMB->t2.Timeout = 0;
+        pSMB->t2.Reserved2 = 0;
+        pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
+                       Fid) - 4);
+        pSMB->t2.DataCount = 0;
+        pSMB->t2.DataOffset = 0;
+        pSMB->t2.SetupCount = 1;
+        pSMB->t2.Reserved3 = 0;
+        pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
+        byte_count = params + 1 /* pad */ ;
+        pSMB->t2.TotalParameterCount = cpu_to_le16(params);
+        pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
+        pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
+        pSMB->Pad = 0;
+       pSMB->Fid = netfid;
+        pSMB->hdr.smb_buf_length += byte_count;
+        pSMB->t2.ByteCount = cpu_to_le16(byte_count);
+
+        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+        if (rc) {
+                cFYI(1, ("error %d in GetExtAttr", rc));
+        } else {
+                /* decode response */
+                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+                if (rc || (pSMBr->ByteCount < 2))
+                /* BB also check enough total bytes returned */
+                        /* If rc should we check for EOPNOSUPP and
+                        disable the srvino flag? or in caller? */
+                        rc = -EIO;      /* bad smb */
+                else {
+                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                        __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+                        struct file_chattr_info * pfinfo;
+                        /* BB Do we need a cast or hash here ? */
+                        if(count != 16) {
+                                cFYI(1, ("Illegal size ret in GetExtAttr"));
+                                rc = -EIO;
+                                goto GetExtAttrOut;
+                        }
+                        pfinfo = (struct file_chattr_info *)
+                                (data_offset + (char *) &pSMBr->hdr.Protocol);
+                        *pExtAttrBits = le64_to_cpu(pfinfo->mode);
+                       *pMask = le64_to_cpu(pfinfo->mask);
+                }
+        }
+GetExtAttrOut:
+        cifs_buf_release(pSMB);
+        if (rc == -EAGAIN)
+                goto GetExtAttrRetry;
+        return rc;
 }
 
-#endif
+
+#endif /* CONFIG_POSIX */
 
 int
 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
                 const unsigned char *searchName,
                 FILE_ALL_INFO * pFindData,
-                const struct nls_table *nls_codepage)
+                const struct nls_table *nls_codepage, int remap)
 {
 /* level 263 SMB_QUERY_FILE_ALL_INFO */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2072,7 +2179,7 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
        int name_len;
        __u16 params, byte_count;
 
-/* cFYI(1, ("In QPathInfo path %s", searchName)); */ /* BB fixme BB */
+/* cFYI(1, ("In QPathInfo path %s", searchName)); */
 QPathInfoRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
@@ -2081,9 +2188,8 @@ QPathInfoRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -2133,8 +2239,7 @@ QPathInfoRetry:
                } else
                    rc = -ENOMEM;
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto QPathInfoRetry;
 
@@ -2145,7 +2250,7 @@ int
 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
                     const unsigned char *searchName,
                     FILE_UNIX_BASIC_INFO * pFindData,
-                    const struct nls_table *nls_codepage)
+                    const struct nls_table *nls_codepage, int remap)
 {
 /* SMB_QUERY_FILE_UNIX_BASIC */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -2164,9 +2269,8 @@ UnixQPathInfoRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
+                                 PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -2217,17 +2321,15 @@ UnixQPathInfoRetry:
                               sizeof (FILE_UNIX_BASIC_INFO));
                }
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto UnixQPathInfoRetry;
 
        return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL  /* function unused at present */
-int
-CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
+#if 0  /* function unused at present */
+int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
               const char *searchName, FILE_ALL_INFO * findData,
               const struct nls_table *nls_codepage)
 {
@@ -2248,7 +2350,7 @@ findUniqueRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
@@ -2297,131 +2399,22 @@ findUniqueRetry:
 
                /* BB fill in */
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
-       if (rc == -EAGAIN)
-               goto findUniqueRetry;
-
-       return rc;
-}
-#endif /* CIFS_EXPERIMENTAL */
-
-int
-CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
-             const char *searchName, FILE_DIRECTORY_INFO * findData,
-             T2_FFIRST_RSP_PARMS * findParms,
-             const struct nls_table *nls_codepage, int *pUnicodeFlag,
-             int *pUnixFlag)
-{
-/* level 257 SMB_ */
-       TRANSACTION2_FFIRST_REQ *pSMB = NULL;
-       TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
-       char *response_data;
-       int rc = 0;
-       int bytes_returned;
-       int name_len;
-       __u16 params, byte_count;
-
-       cFYI(1, ("In FindFirst"));
-findFirstRetry:
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
-       if (rc)
-               return rc;
-
-       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
-               name_len++;     /* trailing null */
-               name_len *= 2;
-       } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, searchName, name_len);
-       }
-
-       params = 12 + name_len /* includes null */ ;
-       pSMB->TotalDataCount = 0;       /* no EAs */
-       pSMB->MaxParameterCount = cpu_to_le16(10);
-       pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
-                                         MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
-       pSMB->MaxSetupCount = 0;
-       pSMB->Reserved = 0;
-       pSMB->Flags = 0;
-       pSMB->Timeout = 0;
-       pSMB->Reserved2 = 0;
-       byte_count = params + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(params);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       pSMB->ParameterOffset = cpu_to_le16(
-               offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
-       pSMB->DataCount = 0;
-       pSMB->DataOffset = 0;
-       pSMB->SetupCount = 1;   /* one byte no need to make endian neutral */
-       pSMB->Reserved3 = 0;
-       pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
-       pSMB->SearchAttributes =
-           cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
-                       ATTR_DIRECTORY);
-       pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
-       pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
-
-       /* test for Unix extensions */
-       if (tcon->ses->capabilities & CAP_UNIX) {
-               pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
-               *pUnixFlag = TRUE;
-       } else {
-               pSMB->InformationLevel =
-                   cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
-               *pUnixFlag = FALSE;
-       }
-       pSMB->SearchStorageType = 0;    /* BB what should we set this to? It is not clear if it matters BB */
-       pSMB->hdr.smb_buf_length += byte_count;
-       pSMB->ByteCount = cpu_to_le16(byte_count);
-
-       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-
-       if (rc) {               /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
-               cFYI(1, ("Error in FindFirst = %d", rc));
-       } else {
-               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-               if(!rc) {
-               /* decode response */
-               /* BB add safety checks for these memcpys */
-                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
-                               *pUnicodeFlag = TRUE;
-                       else
-                               *pUnicodeFlag = FALSE;
-                       memcpy(findParms,
-                              (char *) &pSMBr->hdr.Protocol +
-                              le16_to_cpu(pSMBr->t2.ParameterOffset),
-                              sizeof (T2_FFIRST_RSP_PARMS));
-                       response_data =
-                           (char *) &pSMBr->hdr.Protocol +
-                           le16_to_cpu(pSMBr->t2.DataOffset);
-                       memcpy(findData, response_data, 
-                               le16_to_cpu(pSMBr->t2.DataCount));
-               }
-       }
-       if (pSMB)
-               cifs_buf_release(pSMB);
 
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
-               goto findFirstRetry;
+               goto findUniqueRetry;
 
        return rc;
 }
+#endif /* end unused (temporarily) function */
 
 /* xid, tcon, searchName and codepage are input parms, rest are returned */
 int
-CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
+CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
              const char *searchName, 
              const struct nls_table *nls_codepage,
              __u16 *   pnetfid,
-             struct cifs_search_info * psrch_inf)
+             struct cifs_search_info * psrch_inf, int remap)
 {
 /* level 257 SMB_ */
        TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@ -2432,9 +2425,9 @@ CIFSFindFirst2(const int xid, struct cifsTconInfo *tcon,
        int name_len;
        __u16 params, byte_count;
 
-       cFYI(1, ("In FindFirst2"));
+       cFYI(1, ("In FindFirst for %s",searchName));
 
-findFirst2Retry:
+findFirstRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
@@ -2442,20 +2435,30 @@ findFirst2Retry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
-                                PATH_MAX, nls_codepage);
-               name_len++;     /* trailing null */
+                   cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
+                                PATH_MAX, nls_codepage, remap);
+               /* We can not add the asterik earlier in case
+               it got remapped to 0xF03A as if it were part of the
+               directory name instead of a wildcard */
                name_len *= 2;
+               pSMB->FileName[name_len] = '\\';
+               pSMB->FileName[name_len+1] = 0;
+               pSMB->FileName[name_len+2] = '*';
+               pSMB->FileName[name_len+3] = 0;
+               name_len += 4; /* now the trailing null */
                pSMB->FileName[name_len] = 0; /* null terminate just in case */
                pSMB->FileName[name_len+1] = 0;
+               name_len += 2;
        } else {        /* BB add check for overrun of SMB buf BB */
                name_len = strnlen(searchName, PATH_MAX);
-               name_len++;     /* trailing null */
 /* BB fix here and in unicode clause above ie
                if(name_len > buffersize-header)
                        free buffer exit; BB */
                strncpy(pSMB->FileName, searchName, name_len);
-               pSMB->FileName[name_len] = 0; /* just in case */
+               pSMB->FileName[name_len] = '\\';
+               pSMB->FileName[name_len+1] = '*';
+               pSMB->FileName[name_len+2] = 0;
+               name_len += 3;
        }
 
        params = 12 + name_len /* includes null */ ;
@@ -2504,7 +2507,7 @@ findFirst2Retry:
                /* BB eventually could optimize out free and realloc of buf */
                /*    for this case */
                if (rc == -EAGAIN)
-                       goto findFirst2Retry;
+                       goto findFirstRetry;
        } else { /* decode response */
                /* BB remember to free buffer if error BB */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
@@ -2518,7 +2521,6 @@ findFirst2Retry:
                        psrch_inf->srch_entries_start = 
                                (char *) &pSMBr->hdr.Protocol + 
                                        le16_to_cpu(pSMBr->t2.DataOffset);
-
                        parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
                               le16_to_cpu(pSMBr->t2.ParameterOffset));
 
@@ -2530,18 +2532,16 @@ findFirst2Retry:
                        psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
                        psrch_inf->index_of_last_entry = 
                                psrch_inf->entries_in_buffer;
-/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry));  */
                        *pnetfid = parms->SearchHandle;
                } else {
-                       if(pSMB)
-                               cifs_buf_release(pSMB);
+                       cifs_buf_release(pSMB);
                }
        }
 
        return rc;
 }
 
-int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
+int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
             __u16 searchHandle, struct cifs_search_info * psrch_inf)
 {
        TRANSACTION2_FNEXT_REQ *pSMB = NULL;
@@ -2552,7 +2552,7 @@ int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
        int bytes_returned, name_len;
        __u16 params, byte_count;
 
-       cFYI(1, ("In FindNext2"));
+       cFYI(1, ("In FindNext"));
 
        if(psrch_inf->endOfSearch == TRUE)
                return -ENOENT;
@@ -2659,137 +2659,31 @@ int CIFSFindNext2(const int xid, struct cifsTconInfo *tcon,
        /* Note: On -EAGAIN error only caller can retry on handle based calls
        since file handle passed in no longer valid */
 FNext2_err_exit:
-       if ((rc != 0) && pSMB)
+       if (rc != 0)
                cifs_buf_release(pSMB);
                                                                                               
        return rc;
 }
 
 int
-CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
-               FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
-               const __u16 searchHandle, char * resume_file_name, int name_len,
-               __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
+CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
 {
-/* level 257 SMB_ */
-       TRANSACTION2_FNEXT_REQ *pSMB = NULL;
-       TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
-       char *response_data;
        int rc = 0;
+       FINDCLOSE_REQ *pSMB = NULL;
+       CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
        int bytes_returned;
-       __u16 params, byte_count;
 
-       cFYI(1, ("In FindNext"));
+       cFYI(1, ("In CIFSSMBFindClose"));
+       rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
 
-       if(resume_file_name == NULL) {
-               return -EIO;
-       }
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       /* no sense returning error if session restarted
+               as file handle has been closed */
+       if(rc == -EAGAIN)
+               return 0;
        if (rc)
                return rc;
 
-       params = 14;    /* includes 2 bytes of null string, converted to LE below */
-       byte_count = 0;
-       pSMB->TotalDataCount = 0;       /* no EAs */
-       pSMB->MaxParameterCount = cpu_to_le16(8);
-       pSMB->MaxDataCount =
-           cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
-       pSMB->MaxSetupCount = 0;
-       pSMB->Reserved = 0;
-       pSMB->Flags = 0;
-       pSMB->Timeout = 0;
-       pSMB->Reserved2 = 0;
-       pSMB->ParameterOffset =  cpu_to_le16(
-           offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
-       pSMB->DataCount = 0;
-       pSMB->DataOffset = 0;
-       pSMB->SetupCount = 1;
-       pSMB->Reserved3 = 0;
-       pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
-       pSMB->SearchHandle = searchHandle;      /* always kept as le */
-       findParms->SearchCount = 0;     /* set to zero in case of error */
-       pSMB->SearchCount =
-           cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
-       /* test for Unix extensions */
-       if (tcon->ses->capabilities & CAP_UNIX) {
-               pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
-               *pUnixFlag = TRUE;
-       } else {
-               pSMB->InformationLevel =
-                   cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
-               *pUnixFlag = FALSE;
-       }
-       pSMB->ResumeKey = resume_key;
-       pSMB->SearchFlags =
-           cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
-       /* BB add check to make sure we do not cross end of smb */
-       if(name_len < PATH_MAX) {
-               memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
-               byte_count += name_len;
-       }
-       params += name_len;
-       byte_count = params + 1 /* pad */ ;
-       pSMB->TotalParameterCount = cpu_to_le16(params);
-       pSMB->ParameterCount = pSMB->TotalParameterCount;
-       /* BB improve error handling here */
-       pSMB->hdr.smb_buf_length += byte_count;
-       pSMB->ByteCount = cpu_to_le16(byte_count);
-
-       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-
-       if (rc) {
-               if (rc == -EBADF)
-                       rc = 0; /* search probably was closed at end of search above */
-               else
-                       cFYI(1, ("FindNext returned = %d", rc));
-       } else {                /* decode response */
-               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
-
-               /* BB add safety checks for these memcpys */
-               if(rc == 0) {
-                       if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
-                               *pUnicodeFlag = TRUE;
-                       else
-                               *pUnicodeFlag = FALSE;
-                       memcpy(findParms,
-                              (char *) &pSMBr->hdr.Protocol +
-                              le16_to_cpu(pSMBr->t2.ParameterOffset),
-                              sizeof (T2_FNEXT_RSP_PARMS));
-                       response_data =
-                           (char *) &pSMBr->hdr.Protocol +
-                           le16_to_cpu(pSMBr->t2.DataOffset);
-                       memcpy(findData,response_data,le16_to_cpu(pSMBr->t2.DataCount));
-               }
-       }
-       if (pSMB)
-               cifs_buf_release(pSMB);
-
-       /* Note: On -EAGAIN error only caller can retry on handle based calls
-               since file handle passed in no longer valid */
-
-       return rc;
-}
-
-int
-CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
-{
-       int rc = 0;
-       FINDCLOSE_REQ *pSMB = NULL;
-       CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
-       int bytes_returned;
-
-       cFYI(1, ("In CIFSSMBFindClose"));
-       rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
        pSMBr = (CLOSE_RSP *)pSMB;  /* BB removeme BB */
-       /* no sense returning error if session restarted
-               file handle has been closed */
-       if(rc == -EAGAIN)
-               return 0;
-       if (rc)
-               return rc;
-
        pSMB->FileID = searchHandle;
        pSMB->ByteCount = 0;
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
@@ -2797,8 +2691,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
        if (rc) {
                cERROR(1, ("Send error in FindClose = %d", rc));
        }
-       if (pSMB)
-               cifs_small_buf_release(pSMB);
+       cifs_small_buf_release(pSMB);
 
        /* Since session is dead, search handle closed on server already */
        if (rc == -EAGAIN)
@@ -2812,28 +2705,91 @@ int
 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
                 const unsigned char *searchName,
                 __u64 * inode_number,
-                const struct nls_table *nls_codepage)
+                const struct nls_table *nls_codepage, int remap)
 {
        int rc = 0;
        TRANSACTION2_QPI_REQ *pSMB = NULL;
        TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       int name_len, bytes_returned;
+       __u16 params, byte_count;
 
-       cFYI(1,("In GetSrvInodeNumber for %s",searchName));
+       cFYI(1,("In GetSrvInodeNum for %s",searchName));
        if(tcon == NULL)
                return -ENODEV; 
 
-        cFYI(1, ("In QPathInfo path %s", searchName));
 GetInodeNumberRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                       (void **) &pSMBr);
        if (rc)
                return rc;
 
-/* BB add missing code here */
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
-                                                                                                                         
+       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 {                /* BB improve the check for buffer overruns BB */
+               name_len = strnlen(searchName, PATH_MAX);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->FileName, searchName, name_len);
+       }
+
+       params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+       pSMB->TotalDataCount = 0;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       /* BB find exact max data count below from sess structure BB */
+       pSMB->MaxDataCount = cpu_to_le16(4000);
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       pSMB->ParameterOffset = cpu_to_le16(offsetof(
+               struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+       pSMB->DataCount = 0;
+       pSMB->DataOffset = 0;
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
+       pSMB->Reserved4 = 0;
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+               (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("error %d in QueryInternalInfo", rc));
+       } else {
+               /* decode response */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               if (rc || (pSMBr->ByteCount < 2))
+               /* BB also check enough total bytes returned */
+                       /* If rc should we check for EOPNOSUPP and
+                       disable the srvino flag? or in caller? */
+                       rc = -EIO;      /* bad smb */
+                else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                       __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+                       struct file_internal_info * pfinfo;
+                       /* BB Do we need a cast or hash here ? */
+                       if(count < 8) {
+                               cFYI(1, ("Illegal size ret in QryIntrnlInf"));
+                               rc = -EIO;
+                               goto GetInodeNumOut;
+                       }
+                       pfinfo = (struct file_internal_info *)
+                               (data_offset + (char *) &pSMBr->hdr.Protocol);
+                       *inode_number = pfinfo->UniqueId;
+               }
+       }
+GetInodeNumOut:
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto GetInodeNumberRetry;
        return rc;
@@ -2845,7 +2801,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
                const unsigned char *searchName,
                unsigned char **targetUNCs,
                unsigned int *number_of_UNC_in_array,
-               const struct nls_table *nls_codepage)
+               const struct nls_table *nls_codepage, int remap)
 {
 /* TRANS2_GET_DFS_REFERRAL */
        TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
@@ -2881,10 +2837,8 @@ getDFSRetry:
        if (ses->capabilities & CAP_UNICODE) {
                pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
-                                 searchName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
+                                    searchName, PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -3012,8 +2966,7 @@ GetDFSRefExit:
 }
 
 int
-CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
-              struct kstatfs *FSData, const struct nls_table *nls_codepage)
+CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
 {
 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
        TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3087,8 +3040,7 @@ QFSInfoRetry:
                              FSData->f_bsize));
                }
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
                goto QFSInfoRetry;
@@ -3097,8 +3049,7 @@ QFSInfoRetry:
 }
 
 int
-CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
-                       const struct nls_table *nls_codepage)
+CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
 {
 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
        TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3157,8 +3108,7 @@ QFSAttributeRetry:
                               sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
                }
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
                goto QFSAttributeRetry;
@@ -3167,8 +3117,7 @@ QFSAttributeRetry:
 }
 
 int
-CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
-                    const struct nls_table *nls_codepage)
+CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
 {
 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
        TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3221,15 +3170,14 @@ QFSDeviceRetry:
                else {
                        __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
                        response_data =
-                           (FILE_SYSTEM_DEVICE_INFO
-                            *) (((char *) &pSMBr->hdr.Protocol) +
+                           (FILE_SYSTEM_DEVICE_INFO *)
+                               (((char *) &pSMBr->hdr.Protocol) +
                                 data_offset);
                        memcpy(&tcon->fsDevInfo, response_data,
                               sizeof (FILE_SYSTEM_DEVICE_INFO));
                }
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
                goto QFSDeviceRetry;
@@ -3238,8 +3186,7 @@ QFSDeviceRetry:
 }
 
 int
-CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
-                  const struct nls_table *nls_codepage)
+CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
 {
 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
        TRANSACTION2_QFSI_REQ *pSMB = NULL;
@@ -3298,8 +3245,7 @@ QFSUnixRetry:
                               sizeof (FILE_SYSTEM_UNIX_INFO));
                }
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
                goto QFSUnixRetry;
@@ -3308,6 +3254,93 @@ QFSUnixRetry:
        return rc;
 }
 
+
+int
+CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
+                  struct kstatfs *FSData)
+{
+/* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
+       TRANSACTION2_QFSI_REQ *pSMB = NULL;
+       TRANSACTION2_QFSI_RSP *pSMBr = NULL;
+       FILE_SYSTEM_POSIX_INFO *response_data;
+       int rc = 0;
+       int bytes_returned = 0;
+       __u16 params, byte_count;
+
+       cFYI(1, ("In QFSPosixInfo"));
+QFSPosixRetry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       params = 2;     /* level */
+       pSMB->TotalDataCount = 0;
+       pSMB->DataCount = 0;
+       pSMB->DataOffset = 0;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       byte_count = params + 1 /* pad */ ;
+       pSMB->ParameterCount = cpu_to_le16(params);
+       pSMB->TotalParameterCount = pSMB->ParameterCount;
+       pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
+        smb_com_transaction2_qfsi_req, InformationLevel) - 4);
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
+       pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
+       } else {                /* decode response */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+
+               if (rc || (pSMBr->ByteCount < 13)) {
+                       rc = -EIO;      /* bad smb */
+               } else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                       response_data =
+                           (FILE_SYSTEM_POSIX_INFO
+                            *) (((char *) &pSMBr->hdr.Protocol) +
+                                data_offset);
+                       FSData->f_bsize =
+                                       le32_to_cpu(response_data->BlockSize);
+                       FSData->f_blocks =
+                                       le64_to_cpu(response_data->TotalBlocks);
+                       FSData->f_bfree =
+                           le64_to_cpu(response_data->BlocksAvail);
+                       if(response_data->UserBlocksAvail == -1) {
+                               FSData->f_bavail = FSData->f_bfree;
+                       } else {
+                               FSData->f_bavail =
+                                       le64_to_cpu(response_data->UserBlocksAvail);
+                       }
+                       if(response_data->TotalFileNodes != -1)
+                               FSData->f_files =
+                                       le64_to_cpu(response_data->TotalFileNodes);
+                       if(response_data->FreeFileNodes != -1)
+                               FSData->f_ffree =
+                                       le64_to_cpu(response_data->FreeFileNodes);
+               }
+       }
+       cifs_buf_release(pSMB);
+
+       if (rc == -EAGAIN)
+               goto QFSPosixRetry;
+
+       return rc;
+}
+
+
 /* We can not use write of zero bytes trick to 
    set file size due to need for large file support.  Also note that 
    this SetPathInfo is preferred to SetFileInfo based method in next 
@@ -3316,7 +3349,8 @@ QFSUnixRetry:
 
 int
 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
-             __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
+             __u64 size, int SetAllocation, 
+             const struct nls_table *nls_codepage, int remap)
 {
        struct smb_com_transaction2_spi_req *pSMB = NULL;
        struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -3335,9 +3369,8 @@ SetEOFRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -3396,8 +3429,7 @@ SetEOFRetry:
                cFYI(1, ("SetPathInfo (file size) returned %d", rc));
        }
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
                goto SetEOFRetry;
@@ -3419,11 +3451,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
 
        cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
                        (long long)size));
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
+       rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
+
        if (rc)
                return rc;
 
+       pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
+
        pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
        pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
     
@@ -3483,7 +3517,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
        }
 
        if (pSMB)
-               cifs_buf_release(pSMB);
+               cifs_small_buf_release(pSMB);
 
        /* Note: On -EAGAIN error only caller can retry on handle based calls 
                since file handle passed in no longer valid */
@@ -3491,90 +3525,89 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
        return rc;
 }
 
+/* Some legacy servers such as NT4 require that the file times be set on 
+   an open handle, rather than by pathname - this is awkward due to
+   potential access conflicts on the open, but it is unavoidable for these
+   old servers since the only other choice is to go from 100 nanosecond DCE
+   time and resort to the original setpathinfo level which takes the ancient
+   DOS time format with 2 second granularity */
 int
-CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
-               const FILE_BASIC_INFO * data, 
-               const struct nls_table *nls_codepage)
+CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data, 
+                   __u16 fid)
 {
-       TRANSACTION2_SPI_REQ *pSMB = NULL;
-       TRANSACTION2_SPI_RSP *pSMBr = NULL;
-       int name_len;
+       struct smb_com_transaction2_sfi_req *pSMB  = NULL;
+       struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
+       char *data_offset;
        int rc = 0;
        int bytes_returned = 0;
-       char *data_offset;
        __u16 params, param_offset, offset, byte_count, count;
 
-       cFYI(1, ("In SetTimes"));
+       cFYI(1, ("Set Times (via SetFileInfo)"));
+       rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
 
-SetTimesRetry:
-       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
        if (rc)
                return rc;
 
-       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
-               name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
-               name_len++;     /* trailing null */
-               name_len *= 2;
-       } else {                /* BB improve the check for buffer overruns BB */
-               name_len = strnlen(fileName, PATH_MAX);
-               name_len++;     /* trailing null */
-               strncpy(pSMB->FileName, fileName, name_len);
-       }
+       pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
 
-       params = 6 + name_len;
-       count = sizeof (FILE_BASIC_INFO);
-       pSMB->MaxParameterCount = cpu_to_le16(2);
-       pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
+       /* At this point there is no need to override the current pid
+       with the pid of the opener, but that could change if we someday
+       use an existing handle (rather than opening one on the fly) */
+       /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
+       pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
+    
+       params = 6;
        pSMB->MaxSetupCount = 0;
        pSMB->Reserved = 0;
        pSMB->Flags = 0;
        pSMB->Timeout = 0;
        pSMB->Reserved2 = 0;
-       param_offset = offsetof(struct smb_com_transaction2_spi_req,
-                                     InformationLevel) - 4;
+       param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
        offset = param_offset + params;
-       data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
-       pSMB->ParameterOffset = cpu_to_le16(param_offset);
-       pSMB->DataOffset = cpu_to_le16(offset);
+
+       data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 
+
+       count = sizeof (FILE_BASIC_INFO);
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
        pSMB->SetupCount = 1;
        pSMB->Reserved3 = 0;
-       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
        byte_count = 3 /* pad */  + params + count;
-
        pSMB->DataCount = cpu_to_le16(count);
        pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->TotalParameterCount = pSMB->ParameterCount;
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       pSMB->Fid = fid;
        if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
                pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
        else
                pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
        pSMB->Reserved4 = 0;
        pSMB->hdr.smb_buf_length += byte_count;
-       memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
        pSMB->ByteCount = cpu_to_le16(byte_count);
+       memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("SetPathInfo (times) returned %d", rc));
+               cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
        }
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_small_buf_release(pSMB);
 
-       if (rc == -EAGAIN)
-               goto SetTimesRetry;
+       /* Note: On -EAGAIN error only caller can retry on handle based calls 
+               since file handle passed in no longer valid */
 
        return rc;
 }
 
+
 int
-CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
-               FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
+CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
+               const FILE_BASIC_INFO * data, 
+               const struct nls_table *nls_codepage, int remap)
 {
        TRANSACTION2_SPI_REQ *pSMB = NULL;
        TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3582,11 +3615,11 @@ CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
        int rc = 0;
        int bytes_returned = 0;
        char *data_offset;
-       __u16 params, param_offset, count, offset, byte_count;
+       __u16 params, param_offset, offset, byte_count, count;
 
-       cFYI(1, ("In SetTimesLegacy"));
+       cFYI(1, ("In SetTimes"));
 
-SetTimesRetryLegacy:
+SetTimesRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
@@ -3594,9 +3627,8 @@ SetTimesRetryLegacy:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -3604,10 +3636,9 @@ SetTimesRetryLegacy:
                name_len++;     /* trailing null */
                strncpy(pSMB->FileName, fileName, name_len);
        }
-/* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
-       in parent function, from the better and ususal FILE_BASIC_INFO */
+
        params = 6 + name_len;
-       count = sizeof (FILE_INFO_STANDARD);
+       count = sizeof (FILE_BASIC_INFO);
        pSMB->MaxParameterCount = cpu_to_le16(2);
        pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
        pSMB->MaxSetupCount = 0;
@@ -3630,30 +3661,86 @@ SetTimesRetryLegacy:
        pSMB->ParameterCount = cpu_to_le16(params);
        pSMB->TotalDataCount = pSMB->DataCount;
        pSMB->TotalParameterCount = pSMB->ParameterCount;
-       pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
+       if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
+               pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
+       else
+               pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
        pSMB->Reserved4 = 0;
        pSMB->hdr.smb_buf_length += byte_count;
-       memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
+       memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
        pSMB->ByteCount = cpu_to_le16(byte_count);
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        if (rc) {
-               cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
+               cFYI(1, ("SetPathInfo (times) returned %d", rc));
        }
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
-               goto SetTimesRetryLegacy;
+               goto SetTimesRetry;
 
        return rc;
 }
 
+/* Can not be used to set time stamps yet (due to old DOS time format) */
+/* Can be used to set attributes */
+#if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
+         handling it anyway and NT4 was what we thought it would be needed for
+         Do not delete it until we prove whether needed for Win9x though */
+int
+CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
+               __u16 dos_attrs, const struct nls_table *nls_codepage)
+{
+       SETATTR_REQ *pSMB = NULL;
+       SETATTR_RSP *pSMBr = NULL;
+       int rc = 0;
+       int bytes_returned;
+       int name_len;
+
+       cFYI(1, ("In SetAttrLegacy"));
+
+SetAttrLgcyRetry:
+       rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                       ConvertToUCS((__le16 *) pSMB->fileName, fileName, 
+                               PATH_MAX, nls_codepage);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+       } else {                /* BB improve the check for buffer overruns BB */
+               name_len = strnlen(fileName, PATH_MAX);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->fileName, fileName, name_len);
+       }
+       pSMB->attr = cpu_to_le16(dos_attrs);
+       pSMB->BufferFormat = 0x04;
+       pSMB->hdr.smb_buf_length += name_len + 1;
+       pSMB->ByteCount = cpu_to_le16(name_len + 1);
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cFYI(1, ("Error in LegacySetAttr = %d", rc));
+       }
+
+       cifs_buf_release(pSMB);
+
+       if (rc == -EAGAIN)
+               goto SetAttrLgcyRetry;
+
+       return rc;
+}
+#endif /* temporarily unneeded SetAttr legacy function */
+
 int
 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
-                   char *fileName, __u64 mode, __u64 uid, __u64 gid,
-                   dev_t device, const struct nls_table *nls_codepage)
+                   char *fileName, __u64 mode, __u64 uid, __u64 gid, 
+                   dev_t device, const struct nls_table *nls_codepage, 
+                   int remap)
 {
        TRANSACTION2_SPI_REQ *pSMB = NULL;
        TRANSACTION2_SPI_RSP *pSMBr = NULL;
@@ -3672,9 +3759,8 @@ setPermsRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, 
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -3789,10 +3875,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
        if (rc) {
                cFYI(1, ("Error in Notify = %d", rc));
        }
-       if (pSMB)
-               cifs_buf_release(pSMB);
-/*             if (rc == -EAGAIN)
-                       goto NotifyRetry; */
+       cifs_buf_release(pSMB);
        return rc;      
 }
 #ifdef CONFIG_CIFS_XATTR
@@ -3800,7 +3883,7 @@ ssize_t
 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
                 const unsigned char *searchName,
                 char * EAData, size_t buf_size,
-                const struct nls_table *nls_codepage)
+                const struct nls_table *nls_codepage, int remap)
 {
                /* BB assumes one setup word */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
@@ -3821,9 +3904,8 @@ QAllEAsRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -3945,7 +4027,7 @@ QAllEAsRetry:
 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
                const unsigned char * searchName,const unsigned char * ea_name,
                unsigned char * ea_value, size_t buf_size, 
-               const struct nls_table *nls_codepage)
+               const struct nls_table *nls_codepage, int remap)
 {
        TRANSACTION2_QPI_REQ *pSMB = NULL;
        TRANSACTION2_QPI_RSP *pSMBr = NULL;
@@ -3965,9 +4047,8 @@ QEARetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {        /* BB improve the check for buffer overruns BB */
@@ -4093,7 +4174,8 @@ QEARetry:
 int
 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
                const char * ea_name, const void * ea_value, 
-               const __u16 ea_value_len, const struct nls_table *nls_codepage)
+               const __u16 ea_value_len, const struct nls_table *nls_codepage,
+               int remap)
 {
        struct smb_com_transaction2_spi_req *pSMB = NULL;
        struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -4112,9 +4194,8 @@ SetEARetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
-                                 /* find define for this maxpathcomponent */
-                                 , nls_codepage);
+                   cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, 
+                                    PATH_MAX, nls_codepage, remap);
                name_len++;     /* trailing null */
                name_len *= 2;
        } else {                /* BB improve the check for buffer overruns BB */
@@ -4162,7 +4243,8 @@ SetEARetry:
        /* we checked above that name len is less than 255 */
        parm_data->list[0].name_len = (__u8)name_len;;
        /* EA names are always ASCII */
-       strncpy(parm_data->list[0].name,ea_name,name_len);
+       if(ea_name)
+               strncpy(parm_data->list[0].name,ea_name,name_len);
        parm_data->list[0].name[name_len] = 0;
        parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
        /* caller ensures that ea_value_len is less than 64K but
@@ -4185,8 +4267,7 @@ SetEARetry:
                cFYI(1, ("SetPathInfo (EA) returned %d", rc));
        }
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
+       cifs_buf_release(pSMB);
 
        if (rc == -EAGAIN)
                goto SetEARetry;