]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/cifs/cifssmb.c
[CIFS] Add support for legacy servers part nine. statfs (df and du) is now
[karo-tx-linux.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2005
5  *   Author(s): Steve French (sfrench@us.ibm.com)
6  *
7  *   Contains the routines for constructing the SMB PDUs themselves
8  *
9  *   This library is free software; you can redistribute it and/or modify
10  *   it under the terms of the GNU Lesser General Public License as published
11  *   by the Free Software Foundation; either version 2.1 of the License, or
12  *   (at your option) any later version.
13  *
14  *   This library is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
17  *   the GNU Lesser General Public License for more details.
18  *
19  *   You should have received a copy of the GNU Lesser General Public License
20  *   along with this library; if not, write to the Free Software
21  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24  /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c   */
25  /* These are mostly routines that operate on a pathname, or on a tree id     */
26  /* (mounted volume), but there are eight handle based routines which must be */
27  /* treated slightly different for reconnection purposes since we never want  */
28  /* to reuse a stale file handle and the caller knows the file handle */
29
30 #include <linux/fs.h>
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
35 #include "cifspdu.h"
36 #include "cifsglob.h"
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
40
41 #ifdef CONFIG_CIFS_POSIX
42 static struct {
43         int index;
44         char *name;
45 } protocols[] = {
46         {CIFS_PROT, "\2NT LM 0.12"}, 
47         {CIFS_PROT, "\2POSIX 2"},
48         {BAD_PROT, "\2"}
49 };
50 #else
51 static struct {
52         int index;
53         char *name;
54 } protocols[] = {
55         {CIFS_PROT, "\2NT LM 0.12"}, 
56         {BAD_PROT, "\2"}
57 };
58 #endif
59
60
61 /* Mark as invalid, all open files on tree connections since they
62    were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
64 {
65         struct cifsFileInfo *open_file = NULL;
66         struct list_head * tmp;
67         struct list_head * tmp1;
68
69 /* list all files open on tree connection and mark them invalid */
70         write_lock(&GlobalSMBSeslock);
71         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72                 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
73                 if(open_file) {
74                         open_file->invalidHandle = TRUE;
75                 }
76         }
77         write_unlock(&GlobalSMBSeslock);
78         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
79            to this tcon */
80 }
81
82 /* If the return code is zero, this function must fill in request_buf pointer */
83 static int
84 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
85          void **request_buf /* returned */)
86 {
87         int rc = 0;
88
89         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90            check for tcp and smb session status done differently
91            for those three - in the calling routine */
92         if(tcon) {
93                 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
94                                   (tcon->ses->server)){
95                         struct nls_table *nls_codepage;
96                                 /* Give Demultiplex thread up to 10 seconds to 
97                                    reconnect, should be greater than cifs socket
98                                    timeout which is 7 seconds */
99                         while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
101                                         (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
102                                 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
103                                         /* on "soft" mounts we wait once */
104                                         if((tcon->retry == FALSE) || 
105                                            (tcon->ses->status == CifsExiting)) {
106                                                 cFYI(1,("gave up waiting on reconnect in smb_init"));
107                                                 return -EHOSTDOWN;
108                                         } /* else "hard" mount - keep retrying
109                                              until process is killed or server
110                                              comes back on-line */
111                                 } else /* TCP session is reestablished now */
112                                         break;
113                                  
114                         }
115                         
116                         nls_codepage = load_nls_default();
117                 /* need to prevent multiple threads trying to
118                 simultaneously reconnect the same SMB session */
119                         down(&tcon->ses->sesSem);
120                         if(tcon->ses->status == CifsNeedReconnect)
121                                 rc = cifs_setup_session(0, tcon->ses, 
122                                                         nls_codepage);
123                         if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
124                                 mark_open_files_invalid(tcon);
125                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
126                                         , nls_codepage);
127                                 up(&tcon->ses->sesSem);
128                                 if(rc == 0)
129                                         atomic_inc(&tconInfoReconnectCount);
130
131                                 cFYI(1, ("reconnect tcon rc = %d", rc));
132                                 /* Removed call to reopen open files here - 
133                                    it is safer (and faster) to reopen files
134                                    one at a time as needed in read and write */
135
136                                 /* Check if handle based operation so we 
137                                    know whether we can continue or not without
138                                    returning to caller to reset file handle */
139                                 switch(smb_command) {
140                                         case SMB_COM_READ_ANDX:
141                                         case SMB_COM_WRITE_ANDX:
142                                         case SMB_COM_CLOSE:
143                                         case SMB_COM_FIND_CLOSE2:
144                                         case SMB_COM_LOCKING_ANDX: {
145                                                 unload_nls(nls_codepage);
146                                                 return -EAGAIN;
147                                         }
148                                 }
149                         } else {
150                                 up(&tcon->ses->sesSem);
151                         }
152                         unload_nls(nls_codepage);
153
154                 } else {
155                         return -EIO;
156                 }
157         }
158         if(rc)
159                 return rc;
160
161         *request_buf = cifs_small_buf_get();
162         if (*request_buf == NULL) {
163                 /* BB should we add a retry in here if not a writepage? */
164                 return -ENOMEM;
165         }
166
167         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
168
169         if(tcon != NULL)
170                 cifs_stats_inc(&tcon->num_smbs_sent);
171
172         return rc;
173 }  
174
175 /* If the return code is zero, this function must fill in request_buf pointer */
176 static int
177 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
178          void **request_buf /* returned */ ,
179          void **response_buf /* returned */ )
180 {
181         int rc = 0;
182
183         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
184            check for tcp and smb session status done differently
185            for those three - in the calling routine */
186         if(tcon) {
187                 if((tcon->ses) && (tcon->ses->status != CifsExiting) && 
188                                   (tcon->ses->server)){
189                         struct nls_table *nls_codepage;
190                                 /* Give Demultiplex thread up to 10 seconds to
191                                    reconnect, should be greater than cifs socket
192                                    timeout which is 7 seconds */
193                         while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
194                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
195                                         (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
196                                 if(tcon->ses->server->tcpStatus == 
197                                                 CifsNeedReconnect) {
198                                         /* on "soft" mounts we wait once */
199                                         if((tcon->retry == FALSE) || 
200                                            (tcon->ses->status == CifsExiting)) {
201                                                 cFYI(1,("gave up waiting on reconnect in smb_init"));
202                                                 return -EHOSTDOWN;
203                                         } /* else "hard" mount - keep retrying
204                                              until process is killed or server
205                                              comes on-line */
206                                 } else /* TCP session is reestablished now */
207                                         break;
208                                  
209                         }
210                         
211                         nls_codepage = load_nls_default();
212                 /* need to prevent multiple threads trying to
213                 simultaneously reconnect the same SMB session */
214                         down(&tcon->ses->sesSem);
215                         if(tcon->ses->status == CifsNeedReconnect)
216                                 rc = cifs_setup_session(0, tcon->ses, 
217                                                         nls_codepage);
218                         if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
219                                 mark_open_files_invalid(tcon);
220                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
221                                               tcon, nls_codepage);
222                                 up(&tcon->ses->sesSem);
223                                 if(rc == 0)
224                                         atomic_inc(&tconInfoReconnectCount);
225
226                                 cFYI(1, ("reconnect tcon rc = %d", rc));
227                                 /* Removed call to reopen open files here - 
228                                    it is safer (and faster) to reopen files
229                                    one at a time as needed in read and write */
230
231                                 /* Check if handle based operation so we 
232                                    know whether we can continue or not without
233                                    returning to caller to reset file handle */
234                                 switch(smb_command) {
235                                         case SMB_COM_READ_ANDX:
236                                         case SMB_COM_WRITE_ANDX:
237                                         case SMB_COM_CLOSE:
238                                         case SMB_COM_FIND_CLOSE2:
239                                         case SMB_COM_LOCKING_ANDX: {
240                                                 unload_nls(nls_codepage);
241                                                 return -EAGAIN;
242                                         }
243                                 }
244                         } else {
245                                 up(&tcon->ses->sesSem);
246                         }
247                         unload_nls(nls_codepage);
248
249                 } else {
250                         return -EIO;
251                 }
252         }
253         if(rc)
254                 return rc;
255
256         *request_buf = cifs_buf_get();
257         if (*request_buf == NULL) {
258                 /* BB should we add a retry in here if not a writepage? */
259                 return -ENOMEM;
260         }
261     /* Although the original thought was we needed the response buf for  */
262     /* potential retries of smb operations it turns out we can determine */
263     /* from the mid flags when the request buffer can be resent without  */
264     /* having to use a second distinct buffer for the response */
265         *response_buf = *request_buf; 
266
267         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
268                         wct /*wct */ );
269
270         if(tcon != NULL)
271                 cifs_stats_inc(&tcon->num_smbs_sent);
272
273         return rc;
274 }
275
276 static int validate_t2(struct smb_t2_rsp * pSMB) 
277 {
278         int rc = -EINVAL;
279         int total_size;
280         char * pBCC;
281
282         /* check for plausible wct, bcc and t2 data and parm sizes */
283         /* check for parm and data offset going beyond end of smb */
284         if(pSMB->hdr.WordCount >= 10) {
285                 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
286                    (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
287                         /* check that bcc is at least as big as parms + data */
288                         /* check that bcc is less than negotiated smb buffer */
289                         total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
290                         if(total_size < 512) {
291                                 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
292                                 /* BCC le converted in SendReceive */
293                                 pBCC = (pSMB->hdr.WordCount * 2) + 
294                                         sizeof(struct smb_hdr) +
295                                         (char *)pSMB;
296                                 if((total_size <= (*(u16 *)pBCC)) && 
297                                    (total_size < 
298                                         CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
299                                         return 0;
300                                 }
301                                 
302                         }
303                 }
304         }
305         cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
306                 sizeof(struct smb_t2_rsp) + 16);
307         return rc;
308 }
309 int
310 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
311 {
312         NEGOTIATE_REQ *pSMB;
313         NEGOTIATE_RSP *pSMBr;
314         int rc = 0;
315         int bytes_returned;
316         struct TCP_Server_Info * server;
317         u16 count;
318
319         if(ses->server)
320                 server = ses->server;
321         else {
322                 rc = -EIO;
323                 return rc;
324         }
325         rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
326                       (void **) &pSMB, (void **) &pSMBr);
327         if (rc)
328                 return rc;
329         pSMB->hdr.Mid = GetNextMid(server);
330         pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
331         if (extended_security)
332                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
333
334         count = strlen(protocols[0].name) + 1;
335         strncpy(pSMB->DialectsArray, protocols[0].name, 30);    
336     /* null guaranteed to be at end of source and target buffers anyway */
337
338         pSMB->hdr.smb_buf_length += count;
339         pSMB->ByteCount = cpu_to_le16(count);
340
341         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
342                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
343         if (rc == 0) {
344                 server->secMode = pSMBr->SecurityMode;  
345                 server->secType = NTLM; /* BB override default for 
346                                            NTLMv2 or kerberos v5 */
347                 /* one byte - no need to convert this or EncryptionKeyLen
348                    from little endian */
349                 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
350                 /* probably no need to store and check maxvcs */
351                 server->maxBuf =
352                         min(le32_to_cpu(pSMBr->MaxBufferSize),
353                         (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
354                 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
355                 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
356                 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
357                 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
358                 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);  
359         /* BB with UTC do we ever need to be using srvr timezone? */
360                 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
361                         memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
362                                CIFS_CRYPTO_KEY_SIZE);
363                 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
364                            && (pSMBr->EncryptionKeyLength == 0)) {
365                         /* decode security blob */
366                 } else
367                         rc = -EIO;
368
369                 /* BB might be helpful to save off the domain of server here */
370
371                 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
372                         (server->capabilities & CAP_EXTENDED_SECURITY)) {
373                         count = pSMBr->ByteCount;
374                         if (count < 16)
375                                 rc = -EIO;
376                         else if (count == 16) {
377                                 server->secType = RawNTLMSSP;
378                                 if (server->socketUseCount.counter > 1) {
379                                         if (memcmp
380                                                 (server->server_GUID,
381                                                 pSMBr->u.extended_response.
382                                                 GUID, 16) != 0) {
383                                                 cFYI(1,
384                                                      ("UID of server does not match previous connection to same ip address"));
385                                                 memcpy(server->
386                                                         server_GUID,
387                                                         pSMBr->u.
388                                                         extended_response.
389                                                         GUID, 16);
390                                         }
391                                 } else
392                                         memcpy(server->server_GUID,
393                                                pSMBr->u.extended_response.
394                                                GUID, 16);
395                         } else {
396                                 rc = decode_negTokenInit(pSMBr->u.
397                                                          extended_response.
398                                                          SecurityBlob,
399                                                          count - 16,
400                                                          &server->secType);
401                                 if(rc == 1) {
402                                 /* BB Need to fill struct for sessetup here */
403                                         rc = -EOPNOTSUPP;
404                                 } else {
405                                         rc = -EINVAL;
406                                 }
407                         }
408                 } else
409                         server->capabilities &= ~CAP_EXTENDED_SECURITY;
410                 if(sign_CIFS_PDUs == FALSE) {        
411                         if(server->secMode & SECMODE_SIGN_REQUIRED)
412                                 cERROR(1,
413                                  ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
414                         server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
415                 } else if(sign_CIFS_PDUs == 1) {
416                         if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
417                                 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
418                 }
419                                 
420         }
421         
422         cifs_buf_release(pSMB);
423         return rc;
424 }
425
426 int
427 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
428 {
429         struct smb_hdr *smb_buffer;
430         struct smb_hdr *smb_buffer_response; /* BB removeme BB */
431         int rc = 0;
432         int length;
433
434         cFYI(1, ("In tree disconnect"));
435         /*
436          *  If last user of the connection and
437          *  connection alive - disconnect it
438          *  If this is the last connection on the server session disconnect it
439          *  (and inside session disconnect we should check if tcp socket needs 
440          *  to be freed and kernel thread woken up).
441          */
442         if (tcon)
443                 down(&tcon->tconSem);
444         else
445                 return -EIO;
446
447         atomic_dec(&tcon->useCount);
448         if (atomic_read(&tcon->useCount) > 0) {
449                 up(&tcon->tconSem);
450                 return -EBUSY;
451         }
452
453         /* No need to return error on this operation if tid invalidated and 
454         closed on server already e.g. due to tcp session crashing */
455         if(tcon->tidStatus == CifsNeedReconnect) {
456                 up(&tcon->tconSem);
457                 return 0;  
458         }
459
460         if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {    
461                 up(&tcon->tconSem);
462                 return -EIO;
463         }
464         rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, 
465                             (void **)&smb_buffer);
466         if (rc) {
467                 up(&tcon->tconSem);
468                 return rc;
469         } else {
470                 smb_buffer_response = smb_buffer; /* BB removeme BB */
471         }
472         rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
473                          &length, 0);
474         if (rc)
475                 cFYI(1, ("Tree disconnect failed %d", rc));
476
477         if (smb_buffer)
478                 cifs_small_buf_release(smb_buffer);
479         up(&tcon->tconSem);
480
481         /* No need to return error on this operation if tid invalidated and 
482         closed on server already e.g. due to tcp session crashing */
483         if (rc == -EAGAIN)
484                 rc = 0;
485
486         return rc;
487 }
488
489 int
490 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
491 {
492         struct smb_hdr *smb_buffer_response;
493         LOGOFF_ANDX_REQ *pSMB;
494         int rc = 0;
495         int length;
496
497         cFYI(1, ("In SMBLogoff for session disconnect"));
498         if (ses)
499                 down(&ses->sesSem);
500         else
501                 return -EIO;
502
503         atomic_dec(&ses->inUse);
504         if (atomic_read(&ses->inUse) > 0) {
505                 up(&ses->sesSem);
506                 return -EBUSY;
507         }
508         rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
509         if (rc) {
510                 up(&ses->sesSem);
511                 return rc;
512         }
513
514         smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
515         
516         if(ses->server) {
517                 pSMB->hdr.Mid = GetNextMid(ses->server);
518
519                 if(ses->server->secMode & 
520                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
521                         pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
522         }
523
524         pSMB->hdr.Uid = ses->Suid;
525
526         pSMB->AndXCommand = 0xFF;
527         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
528                          smb_buffer_response, &length, 0);
529         if (ses->server) {
530                 atomic_dec(&ses->server->socketUseCount);
531                 if (atomic_read(&ses->server->socketUseCount) == 0) {
532                         spin_lock(&GlobalMid_Lock);
533                         ses->server->tcpStatus = CifsExiting;
534                         spin_unlock(&GlobalMid_Lock);
535                         rc = -ESHUTDOWN;
536                 }
537         }
538         up(&ses->sesSem);
539         cifs_small_buf_release(pSMB);
540
541         /* if session dead then we do not need to do ulogoff,
542                 since server closed smb session, no sense reporting 
543                 error */
544         if (rc == -EAGAIN)
545                 rc = 0;
546         return rc;
547 }
548
549 int
550 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
551                const struct nls_table *nls_codepage, int remap)
552 {
553         DELETE_FILE_REQ *pSMB = NULL;
554         DELETE_FILE_RSP *pSMBr = NULL;
555         int rc = 0;
556         int bytes_returned;
557         int name_len;
558
559 DelFileRetry:
560         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
561                       (void **) &pSMBr);
562         if (rc)
563                 return rc;
564
565         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
566                 name_len =
567                     cifsConvertToUCS((__le16 *) pSMB->fileName, fileName, 
568                                      PATH_MAX, nls_codepage, remap);
569                 name_len++;     /* trailing null */
570                 name_len *= 2;
571         } else {                /* BB improve check for buffer overruns BB */
572                 name_len = strnlen(fileName, PATH_MAX);
573                 name_len++;     /* trailing null */
574                 strncpy(pSMB->fileName, fileName, name_len);
575         }
576         pSMB->SearchAttributes =
577             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
578         pSMB->BufferFormat = 0x04;
579         pSMB->hdr.smb_buf_length += name_len + 1;
580         pSMB->ByteCount = cpu_to_le16(name_len + 1);
581         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
582                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
583         cifs_stats_inc(&tcon->num_deletes);
584         if (rc) {
585                 cFYI(1, ("Error in RMFile = %d", rc));
586         } 
587
588         cifs_buf_release(pSMB);
589         if (rc == -EAGAIN)
590                 goto DelFileRetry;
591
592         return rc;
593 }
594
595 int
596 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, 
597              const struct nls_table *nls_codepage, int remap)
598 {
599         DELETE_DIRECTORY_REQ *pSMB = NULL;
600         DELETE_DIRECTORY_RSP *pSMBr = NULL;
601         int rc = 0;
602         int bytes_returned;
603         int name_len;
604
605         cFYI(1, ("In CIFSSMBRmDir"));
606 RmDirRetry:
607         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
608                       (void **) &pSMBr);
609         if (rc)
610                 return rc;
611
612         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
613                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
614                                          PATH_MAX, nls_codepage, remap);
615                 name_len++;     /* trailing null */
616                 name_len *= 2;
617         } else {                /* BB improve check for buffer overruns BB */
618                 name_len = strnlen(dirName, PATH_MAX);
619                 name_len++;     /* trailing null */
620                 strncpy(pSMB->DirName, dirName, name_len);
621         }
622
623         pSMB->BufferFormat = 0x04;
624         pSMB->hdr.smb_buf_length += name_len + 1;
625         pSMB->ByteCount = cpu_to_le16(name_len + 1);
626         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
627                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
628         cifs_stats_inc(&tcon->num_rmdirs);
629         if (rc) {
630                 cFYI(1, ("Error in RMDir = %d", rc));
631         }
632
633         cifs_buf_release(pSMB);
634         if (rc == -EAGAIN)
635                 goto RmDirRetry;
636         return rc;
637 }
638
639 int
640 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
641              const char *name, const struct nls_table *nls_codepage, int remap)
642 {
643         int rc = 0;
644         CREATE_DIRECTORY_REQ *pSMB = NULL;
645         CREATE_DIRECTORY_RSP *pSMBr = NULL;
646         int bytes_returned;
647         int name_len;
648
649         cFYI(1, ("In CIFSSMBMkDir"));
650 MkDirRetry:
651         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
652                       (void **) &pSMBr);
653         if (rc)
654                 return rc;
655
656         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
657                 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name, 
658                                             PATH_MAX, nls_codepage, remap);
659                 name_len++;     /* trailing null */
660                 name_len *= 2;
661         } else {                /* BB improve check for buffer overruns BB */
662                 name_len = strnlen(name, PATH_MAX);
663                 name_len++;     /* trailing null */
664                 strncpy(pSMB->DirName, name, name_len);
665         }
666
667         pSMB->BufferFormat = 0x04;
668         pSMB->hdr.smb_buf_length += name_len + 1;
669         pSMB->ByteCount = cpu_to_le16(name_len + 1);
670         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
671                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
672         cifs_stats_inc(&tcon->num_mkdirs);
673         if (rc) {
674                 cFYI(1, ("Error in Mkdir = %d", rc));
675         }
676
677         cifs_buf_release(pSMB);
678         if (rc == -EAGAIN)
679                 goto MkDirRetry;
680         return rc;
681 }
682
683 static __u16 convert_disposition(int disposition)
684 {
685         __u16 ofun = 0;
686
687         switch (disposition) {
688                 case FILE_SUPERSEDE:
689                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
690                         break;
691                 case FILE_OPEN:
692                         ofun = SMBOPEN_OAPPEND;
693                         break;
694                 case FILE_CREATE:
695                         ofun = SMBOPEN_OCREATE;
696                         break;
697                 case FILE_OPEN_IF:
698                         ofun = SMBOPEN_OCREATE | SMBOPEN_OAPPEND;
699                         break;
700                 case FILE_OVERWRITE:
701                         ofun = SMBOPEN_OTRUNC;
702                         break;
703                 case FILE_OVERWRITE_IF:
704                         ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC;
705                         break;
706                 default:
707                         cFYI(1,("unknown disposition %d",disposition));
708                         ofun =  SMBOPEN_OAPPEND; /* regular open */
709         }
710         return ofun;
711 }
712
713 int
714 SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
715             const char *fileName, const int openDisposition,
716             const int access_flags, const int create_options, __u16 * netfid,
717             int *pOplock, FILE_ALL_INFO * pfile_info,
718             const struct nls_table *nls_codepage, int remap)
719 {
720         int rc = -EACCES;
721         OPENX_REQ *pSMB = NULL;
722         OPENX_RSP *pSMBr = NULL;
723         int bytes_returned;
724         int name_len;
725         __u16 count;
726
727 OldOpenRetry:
728         rc = smb_init(SMB_COM_OPEN_ANDX, 15, tcon, (void **) &pSMB,
729                       (void **) &pSMBr);
730         if (rc)
731                 return rc;
732
733         pSMB->AndXCommand = 0xFF;       /* none */
734
735         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
736                 count = 1;      /* account for one byte pad to word boundary */
737                 name_len =
738                    cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
739                                     fileName, PATH_MAX, nls_codepage, remap);
740                 name_len++;     /* trailing null */
741                 name_len *= 2;
742         } else {                /* BB improve check for buffer overruns BB */
743                 count = 0;      /* no pad */
744                 name_len = strnlen(fileName, PATH_MAX);
745                 name_len++;     /* trailing null */
746                 strncpy(pSMB->fileName, fileName, name_len);
747         }
748         if (*pOplock & REQ_OPLOCK)
749                 pSMB->OpenFlags = cpu_to_le16(REQ_OPLOCK);
750         else if (*pOplock & REQ_BATCHOPLOCK) {
751                 pSMB->OpenFlags = cpu_to_le16(REQ_BATCHOPLOCK);
752         }
753         pSMB->OpenFlags |= cpu_to_le16(REQ_MORE_INFO);
754         /* BB fixme add conversion for access_flags to bits 0 - 2 of mode */
755         /* 0 = read
756            1 = write
757            2 = rw
758            3 = execute
759         */
760         pSMB->Mode = cpu_to_le16(2);
761         pSMB->Mode |= cpu_to_le16(0x40); /* deny none */
762         /* set file as system file if special file such
763            as fifo and server expecting SFU style and
764            no Unix extensions */
765
766         if(create_options & CREATE_OPTION_SPECIAL)
767                 pSMB->FileAttributes = cpu_to_le16(ATTR_SYSTEM);
768         else
769                 pSMB->FileAttributes = cpu_to_le16(0/*ATTR_NORMAL*/); /* BB FIXME */
770
771         /* if ((omode & S_IWUGO) == 0)
772                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
773         /*  Above line causes problems due to vfs splitting create into two
774             pieces - need to set mode after file created not while it is
775             being created */
776
777         /* BB FIXME BB */
778 /*      pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK); */
779         /* BB FIXME END BB */
780
781         pSMB->Sattr = cpu_to_le16(ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY);
782         pSMB->OpenFunction = convert_disposition(openDisposition);
783         count += name_len;
784         pSMB->hdr.smb_buf_length += count;
785
786         pSMB->ByteCount = cpu_to_le16(count);
787         /* long_op set to 1 to allow for oplock break timeouts */
788         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
789                          (struct smb_hdr *) pSMBr, &bytes_returned, 1);
790         cifs_stats_inc(&tcon->num_opens);
791         if (rc) {
792                 cFYI(1, ("Error in Open = %d", rc));
793         } else {
794         /* BB verify if wct == 15 */
795
796 /*              *pOplock = pSMBr->OplockLevel; */  /* BB take from action field BB */
797
798                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
799                 /* Let caller know file was created so we can set the mode. */
800                 /* Do we care about the CreateAction in any other cases? */
801         /* BB FIXME BB */
802 /*              if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
803                         *pOplock |= CIFS_CREATE_ACTION; */
804         /* BB FIXME END */
805
806                 if(pfile_info) {
807                         pfile_info->CreationTime = 0; /* BB convert CreateTime*/
808                         pfile_info->LastAccessTime = 0; /* BB fixme */
809                         pfile_info->LastWriteTime = 0; /* BB fixme */
810                         pfile_info->ChangeTime = 0;  /* BB fixme */
811                         pfile_info->Attributes = pSMBr->FileAttributes; 
812                         /* the file_info buf is endian converted by caller */
813                         pfile_info->AllocationSize = pSMBr->EndOfFile;
814                         pfile_info->EndOfFile = pSMBr->EndOfFile;
815                         pfile_info->NumberOfLinks = cpu_to_le32(1);
816                 }
817         }
818
819         cifs_buf_release(pSMB);
820         if (rc == -EAGAIN)
821                 goto OldOpenRetry;
822         return rc;
823 }
824
825 int
826 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
827             const char *fileName, const int openDisposition,
828             const int access_flags, const int create_options, __u16 * netfid,
829             int *pOplock, FILE_ALL_INFO * pfile_info, 
830             const struct nls_table *nls_codepage, int remap)
831 {
832         int rc = -EACCES;
833         OPEN_REQ *pSMB = NULL;
834         OPEN_RSP *pSMBr = NULL;
835         int bytes_returned;
836         int name_len;
837         __u16 count;
838
839 openRetry:
840         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
841                       (void **) &pSMBr);
842         if (rc)
843                 return rc;
844
845         pSMB->AndXCommand = 0xFF;       /* none */
846
847         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
848                 count = 1;      /* account for one byte pad to word boundary */
849                 name_len =
850                     cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
851                                      fileName, PATH_MAX, nls_codepage, remap);
852                 name_len++;     /* trailing null */
853                 name_len *= 2;
854                 pSMB->NameLength = cpu_to_le16(name_len);
855         } else {                /* BB improve check for buffer overruns BB */
856                 count = 0;      /* no pad */
857                 name_len = strnlen(fileName, PATH_MAX);
858                 name_len++;     /* trailing null */
859                 pSMB->NameLength = cpu_to_le16(name_len);
860                 strncpy(pSMB->fileName, fileName, name_len);
861         }
862         if (*pOplock & REQ_OPLOCK)
863                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
864         else if (*pOplock & REQ_BATCHOPLOCK) {
865                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
866         }
867         pSMB->DesiredAccess = cpu_to_le32(access_flags);
868         pSMB->AllocationSize = 0;
869         /* set file as system file if special file such
870            as fifo and server expecting SFU style and
871            no Unix extensions */
872         if(create_options & CREATE_OPTION_SPECIAL)
873                 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
874         else
875                 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
876         /* XP does not handle ATTR_POSIX_SEMANTICS */
877         /* but it helps speed up case sensitive checks for other
878         servers such as Samba */
879         if (tcon->ses->capabilities & CAP_UNIX)
880                 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
881
882         /* if ((omode & S_IWUGO) == 0)
883                 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
884         /*  Above line causes problems due to vfs splitting create into two
885                 pieces - need to set mode after file created not while it is
886                 being created */
887         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
888         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
889         pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
890         /* BB Expirement with various impersonation levels and verify */
891         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
892         pSMB->SecurityFlags =
893             SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
894
895         count += name_len;
896         pSMB->hdr.smb_buf_length += count;
897
898         pSMB->ByteCount = cpu_to_le16(count);
899         /* long_op set to 1 to allow for oplock break timeouts */
900         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
901                          (struct smb_hdr *) pSMBr, &bytes_returned, 1);
902         cifs_stats_inc(&tcon->num_opens);
903         if (rc) {
904                 cFYI(1, ("Error in Open = %d", rc));
905         } else {
906                 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
907                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
908                 /* Let caller know file was created so we can set the mode. */
909                 /* Do we care about the CreateAction in any other cases? */
910                 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
911                         *pOplock |= CIFS_CREATE_ACTION; 
912                 if(pfile_info) {
913                     memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
914                         36 /* CreationTime to Attributes */);
915                     /* the file_info buf is endian converted by caller */
916                     pfile_info->AllocationSize = pSMBr->AllocationSize;
917                     pfile_info->EndOfFile = pSMBr->EndOfFile;
918                     pfile_info->NumberOfLinks = cpu_to_le32(1);
919                 }
920         }
921
922         cifs_buf_release(pSMB);
923         if (rc == -EAGAIN)
924                 goto openRetry;
925         return rc;
926 }
927
928 /* If no buffer passed in, then caller wants to do the copy
929         as in the case of readpages so the SMB buffer must be
930         freed by the caller */
931
932 int
933 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
934             const int netfid, const unsigned int count,
935             const __u64 lseek, unsigned int *nbytes, char **buf)
936 {
937         int rc = -EACCES;
938         READ_REQ *pSMB = NULL;
939         READ_RSP *pSMBr = NULL;
940         char *pReadData = NULL;
941         int bytes_returned;
942         int wct;
943
944         cFYI(1,("Reading %d bytes on fid %d",count,netfid));
945         if(tcon->ses->capabilities & CAP_LARGE_FILES)
946                 wct = 12;
947         else
948                 wct = 10; /* old style read */
949
950         *nbytes = 0;
951         rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
952                       (void **) &pSMBr);
953         if (rc)
954                 return rc;
955
956         /* tcon and ses pointer are checked in smb_init */
957         if (tcon->ses->server == NULL)
958                 return -ECONNABORTED;
959
960         pSMB->AndXCommand = 0xFF;       /* none */
961         pSMB->Fid = netfid;
962         pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
963         if(wct == 12)
964                 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
965         else if((lseek >> 32) > 0) /* can not handle this big offset for old */
966                 return -EIO;
967
968         pSMB->Remaining = 0;
969         pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
970         pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
971         if(wct == 12)
972                 pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
973         else {
974                 /* old style read */
975                 struct smb_com_readx_req * pSMBW = 
976                         (struct smb_com_readx_req *)pSMB;
977                 pSMBW->ByteCount = 0;   
978         }
979         
980         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
981                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
982         cifs_stats_inc(&tcon->num_reads);
983         if (rc) {
984                 cERROR(1, ("Send error in read = %d", rc));
985         } else {
986                 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
987                 data_length = data_length << 16;
988                 data_length += le16_to_cpu(pSMBr->DataLength);
989                 *nbytes = data_length;
990
991                 /*check that DataLength would not go beyond end of SMB */
992                 if ((data_length > CIFSMaxBufSize) 
993                                 || (data_length > count)) {
994                         cFYI(1,("bad length %d for count %d",data_length,count));
995                         rc = -EIO;
996                         *nbytes = 0;
997                 } else {
998                         pReadData =
999                             (char *) (&pSMBr->hdr.Protocol) +
1000                             le16_to_cpu(pSMBr->DataOffset);
1001 /*                      if(rc = copy_to_user(buf, pReadData, data_length)) {
1002                                 cERROR(1,("Faulting on read rc = %d",rc));
1003                                 rc = -EFAULT;
1004                         }*/ /* can not use copy_to_user when using page cache*/
1005                         if(*buf)
1006                             memcpy(*buf,pReadData,data_length);
1007                 }
1008         }
1009         if(*buf)
1010                 cifs_buf_release(pSMB);
1011         else
1012                 *buf = (char *)pSMB;
1013
1014         /* Note: On -EAGAIN error only caller can retry on handle based calls 
1015                 since file handle passed in no longer valid */
1016         return rc;
1017 }
1018
1019 int
1020 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
1021              const int netfid, const unsigned int count,
1022              const __u64 offset, unsigned int *nbytes, const char *buf,
1023              const char __user * ubuf, const int long_op)
1024 {
1025         int rc = -EACCES;
1026         WRITE_REQ *pSMB = NULL;
1027         WRITE_RSP *pSMBr = NULL;
1028         int bytes_returned, wct;
1029         __u32 bytes_sent;
1030         __u16 byte_count;
1031
1032         /* cFYI(1,("write at %lld %d bytes",offset,count));*/
1033         if(tcon->ses == NULL)
1034                 return -ECONNABORTED;
1035
1036         if(tcon->ses->capabilities & CAP_LARGE_FILES)
1037                 wct = 14;
1038         else
1039                 wct = 12;
1040
1041         rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
1042                       (void **) &pSMBr);
1043         if (rc)
1044                 return rc;
1045         /* tcon and ses pointer are checked in smb_init */
1046         if (tcon->ses->server == NULL)
1047                 return -ECONNABORTED;
1048
1049         pSMB->AndXCommand = 0xFF;       /* none */
1050         pSMB->Fid = netfid;
1051         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1052         if(wct == 14) 
1053                 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1054         else if((offset >> 32) > 0) /* can not handle this big offset for old */
1055                 return -EIO;
1056         
1057         pSMB->Reserved = 0xFFFFFFFF;
1058         pSMB->WriteMode = 0;
1059         pSMB->Remaining = 0;
1060
1061         /* Can increase buffer size if buffer is big enough in some cases - ie we 
1062         can send more if LARGE_WRITE_X capability returned by the server and if
1063         our buffer is big enough or if we convert to iovecs on socket writes
1064         and eliminate the copy to the CIFS buffer */
1065         if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1066                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1067         } else {
1068                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1069                          & ~0xFF;
1070         }
1071
1072         if (bytes_sent > count)
1073                 bytes_sent = count;
1074         pSMB->DataOffset =
1075                 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1076         if(buf)
1077             memcpy(pSMB->Data,buf,bytes_sent);
1078         else if(ubuf) {
1079                 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
1080                         cifs_buf_release(pSMB);
1081                         return -EFAULT;
1082                 }
1083         } else if (count != 0) {
1084                 /* No buffer */
1085                 cifs_buf_release(pSMB);
1086                 return -EINVAL;
1087         } /* else setting file size with write of zero bytes */
1088         if(wct == 14)
1089                 byte_count = bytes_sent + 1; /* pad */
1090         else /* wct == 12 */ {
1091                 byte_count = bytes_sent + 5; /* bigger pad, smaller smb hdr */
1092         }
1093         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1094         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1095         pSMB->hdr.smb_buf_length += byte_count;
1096
1097         if(wct == 14)
1098                 pSMB->ByteCount = cpu_to_le16(byte_count);
1099         else { /* old style write has byte count 4 bytes earlier so 4 bytes pad  */
1100                 struct smb_com_writex_req * pSMBW = 
1101                         (struct smb_com_writex_req *)pSMB;
1102                 pSMBW->ByteCount = cpu_to_le16(byte_count);
1103         }
1104
1105         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1106                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
1107         cifs_stats_inc(&tcon->num_writes);
1108         if (rc) {
1109                 cFYI(1, ("Send error in write = %d", rc));
1110                 *nbytes = 0;
1111         } else {
1112                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1113                 *nbytes = (*nbytes) << 16;
1114                 *nbytes += le16_to_cpu(pSMBr->Count);
1115         }
1116
1117         cifs_buf_release(pSMB);
1118
1119         /* Note: On -EAGAIN error only caller can retry on handle based calls 
1120                 since file handle passed in no longer valid */
1121
1122         return rc;
1123 }
1124
1125 #ifdef CONFIG_CIFS_EXPERIMENTAL
1126 int
1127 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
1128              const int netfid, const unsigned int count,
1129              const __u64 offset, unsigned int *nbytes, const char *buf,
1130              const int long_op)
1131 {
1132         int rc = -EACCES;
1133         WRITE_REQ *pSMB = NULL;
1134         int bytes_returned;
1135         int smb_hdr_len;
1136         __u32 bytes_sent;
1137         __u16 byte_count;
1138
1139         cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
1140         rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
1141         if (rc)
1142                 return rc;
1143         /* tcon and ses pointer are checked in smb_init */
1144         if (tcon->ses->server == NULL)
1145                 return -ECONNABORTED;
1146
1147         pSMB->AndXCommand = 0xFF;       /* none */
1148         pSMB->Fid = netfid;
1149         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
1150         pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
1151         pSMB->Reserved = 0xFFFFFFFF;
1152         pSMB->WriteMode = 0;
1153         pSMB->Remaining = 0;
1154
1155         /* Can increase buffer size if buffer is big enough in some cases - ie 
1156         can send more if LARGE_WRITE_X capability returned by the server and if
1157         our buffer is big enough or if we convert to iovecs on socket writes
1158         and eliminate the copy to the CIFS buffer */
1159         if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
1160                 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
1161         } else {
1162                 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1163                          & ~0xFF;
1164         }
1165
1166         if (bytes_sent > count)
1167                 bytes_sent = count;
1168         pSMB->DataOffset =
1169             cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1170
1171         byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1172         pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1173         pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1174         smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1175         pSMB->hdr.smb_buf_length += bytes_sent+1;
1176         pSMB->ByteCount = cpu_to_le16(byte_count);
1177
1178         rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1179                           buf, bytes_sent, &bytes_returned, long_op);
1180         cifs_stats_inc(&tcon->num_writes);
1181         if (rc) {
1182                 cFYI(1, ("Send error in write = %d", rc));
1183                 *nbytes = 0;
1184         } else {
1185                 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1186                 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1187                 *nbytes = (*nbytes) << 16;
1188                 *nbytes += le16_to_cpu(pSMBr->Count);
1189         }
1190
1191         cifs_small_buf_release(pSMB);
1192
1193         /* Note: On -EAGAIN error only caller can retry on handle based calls 
1194                 since file handle passed in no longer valid */
1195
1196         return rc;
1197 }
1198
1199
1200 #endif /* CIFS_EXPERIMENTAL */
1201
1202 int
1203 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1204             const __u16 smb_file_id, const __u64 len,
1205             const __u64 offset, const __u32 numUnlock,
1206             const __u32 numLock, const __u8 lockType, const int waitFlag)
1207 {
1208         int rc = 0;
1209         LOCK_REQ *pSMB = NULL;
1210         LOCK_RSP *pSMBr = NULL;
1211         int bytes_returned;
1212         int timeout = 0;
1213         __u16 count;
1214
1215         cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1216         rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1217
1218         if (rc)
1219                 return rc;
1220
1221         pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1222
1223         if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1224                 timeout = -1; /* no response expected */
1225                 pSMB->Timeout = 0;
1226         } else if (waitFlag == TRUE) {
1227                 timeout = 3;  /* blocking operation, no timeout */
1228                 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1229         } else {
1230                 pSMB->Timeout = 0;
1231         }
1232
1233         pSMB->NumberOfLocks = cpu_to_le16(numLock);
1234         pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1235         pSMB->LockType = lockType;
1236         pSMB->AndXCommand = 0xFF;       /* none */
1237         pSMB->Fid = smb_file_id; /* netfid stays le */
1238
1239         if((numLock != 0) || (numUnlock != 0)) {
1240                 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1241                 /* BB where to store pid high? */
1242                 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1243                 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1244                 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1245                 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1246                 count = sizeof(LOCKING_ANDX_RANGE);
1247         } else {
1248                 /* oplock break */
1249                 count = 0;
1250         }
1251         pSMB->hdr.smb_buf_length += count;
1252         pSMB->ByteCount = cpu_to_le16(count);
1253
1254         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1255                          (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1256         cifs_stats_inc(&tcon->num_locks);
1257         if (rc) {
1258                 cFYI(1, ("Send error in Lock = %d", rc));
1259         }
1260         cifs_small_buf_release(pSMB);
1261
1262         /* Note: On -EAGAIN error only caller can retry on handle based calls 
1263         since file handle passed in no longer valid */
1264         return rc;
1265 }
1266
1267 int
1268 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1269 {
1270         int rc = 0;
1271         CLOSE_REQ *pSMB = NULL;
1272         CLOSE_RSP *pSMBr = NULL;
1273         int bytes_returned;
1274         cFYI(1, ("In CIFSSMBClose"));
1275
1276 /* do not retry on dead session on close */
1277         rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1278         if(rc == -EAGAIN)
1279                 return 0;
1280         if (rc)
1281                 return rc;
1282
1283         pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1284
1285         pSMB->FileID = (__u16) smb_file_id;
1286         pSMB->LastWriteTime = 0;
1287         pSMB->ByteCount = 0;
1288         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1289                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1290         cifs_stats_inc(&tcon->num_closes);
1291         if (rc) {
1292                 if(rc!=-EINTR) {
1293                         /* EINTR is expected when user ctl-c to kill app */
1294                         cERROR(1, ("Send error in Close = %d", rc));
1295                 }
1296         }
1297
1298         cifs_small_buf_release(pSMB);
1299
1300         /* Since session is dead, file will be closed on server already */
1301         if(rc == -EAGAIN)
1302                 rc = 0;
1303
1304         return rc;
1305 }
1306
1307 int
1308 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1309               const char *fromName, const char *toName,
1310               const struct nls_table *nls_codepage, int remap)
1311 {
1312         int rc = 0;
1313         RENAME_REQ *pSMB = NULL;
1314         RENAME_RSP *pSMBr = NULL;
1315         int bytes_returned;
1316         int name_len, name_len2;
1317         __u16 count;
1318
1319         cFYI(1, ("In CIFSSMBRename"));
1320 renameRetry:
1321         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1322                       (void **) &pSMBr);
1323         if (rc)
1324                 return rc;
1325
1326         pSMB->BufferFormat = 0x04;
1327         pSMB->SearchAttributes =
1328             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1329                         ATTR_DIRECTORY);
1330
1331         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1332                 name_len =
1333                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, 
1334                                      PATH_MAX, nls_codepage, remap);
1335                 name_len++;     /* trailing null */
1336                 name_len *= 2;
1337                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
1338         /* protocol requires ASCII signature byte on Unicode string */
1339                 pSMB->OldFileName[name_len + 1] = 0x00;
1340                 name_len2 =
1341                     cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1342                                      toName, PATH_MAX, nls_codepage, remap);
1343                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1344                 name_len2 *= 2; /* convert to bytes */
1345         } else {                /* BB improve the check for buffer overruns BB */
1346                 name_len = strnlen(fromName, PATH_MAX);
1347                 name_len++;     /* trailing null */
1348                 strncpy(pSMB->OldFileName, fromName, name_len);
1349                 name_len2 = strnlen(toName, PATH_MAX);
1350                 name_len2++;    /* trailing null */
1351                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
1352                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1353                 name_len2++;    /* trailing null */
1354                 name_len2++;    /* signature byte */
1355         }
1356
1357         count = 1 /* 1st signature byte */  + name_len + name_len2;
1358         pSMB->hdr.smb_buf_length += count;
1359         pSMB->ByteCount = cpu_to_le16(count);
1360
1361         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1362                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1363         cifs_stats_inc(&tcon->num_renames);
1364         if (rc) {
1365                 cFYI(1, ("Send error in rename = %d", rc));
1366         } 
1367
1368         cifs_buf_release(pSMB);
1369
1370         if (rc == -EAGAIN)
1371                 goto renameRetry;
1372
1373         return rc;
1374 }
1375
1376 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 
1377                 int netfid, char * target_name, 
1378                 const struct nls_table * nls_codepage, int remap)
1379 {
1380         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
1381         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1382         struct set_file_rename * rename_info;
1383         char *data_offset;
1384         char dummy_string[30];
1385         int rc = 0;
1386         int bytes_returned = 0;
1387         int len_of_str;
1388         __u16 params, param_offset, offset, count, byte_count;
1389
1390         cFYI(1, ("Rename to File by handle"));
1391         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1392                         (void **) &pSMBr);
1393         if (rc)
1394                 return rc;
1395
1396         params = 6;
1397         pSMB->MaxSetupCount = 0;
1398         pSMB->Reserved = 0;
1399         pSMB->Flags = 0;
1400         pSMB->Timeout = 0;
1401         pSMB->Reserved2 = 0;
1402         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1403         offset = param_offset + params;
1404
1405         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1406         rename_info = (struct set_file_rename *) data_offset;
1407         pSMB->MaxParameterCount = cpu_to_le16(2);
1408         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1409         pSMB->SetupCount = 1;
1410         pSMB->Reserved3 = 0;
1411         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1412         byte_count = 3 /* pad */  + params;
1413         pSMB->ParameterCount = cpu_to_le16(params);
1414         pSMB->TotalParameterCount = pSMB->ParameterCount;
1415         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1416         pSMB->DataOffset = cpu_to_le16(offset);
1417         /* construct random name ".cifs_tmp<inodenum><mid>" */
1418         rename_info->overwrite = cpu_to_le32(1);
1419         rename_info->root_fid  = 0;
1420         /* unicode only call */
1421         if(target_name == NULL) {
1422                 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1423                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1424                                         dummy_string, 24, nls_codepage, remap);
1425         } else {
1426                 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1427                                         target_name, PATH_MAX, nls_codepage, remap);
1428         }
1429         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1430         count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1431         byte_count += count;
1432         pSMB->DataCount = cpu_to_le16(count);
1433         pSMB->TotalDataCount = pSMB->DataCount;
1434         pSMB->Fid = netfid;
1435         pSMB->InformationLevel =
1436                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1437         pSMB->Reserved4 = 0;
1438         pSMB->hdr.smb_buf_length += byte_count;
1439         pSMB->ByteCount = cpu_to_le16(byte_count);
1440         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1441                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1442         cifs_stats_inc(&pTcon->num_t2renames);
1443         if (rc) {
1444                 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1445         }
1446
1447         cifs_buf_release(pSMB);
1448
1449         /* Note: On -EAGAIN error only caller can retry on handle based calls
1450                 since file handle passed in no longer valid */
1451
1452         return rc;
1453 }
1454
1455 int
1456 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 
1457             const __u16 target_tid, const char *toName, const int flags,
1458             const struct nls_table *nls_codepage, int remap)
1459 {
1460         int rc = 0;
1461         COPY_REQ *pSMB = NULL;
1462         COPY_RSP *pSMBr = NULL;
1463         int bytes_returned;
1464         int name_len, name_len2;
1465         __u16 count;
1466
1467         cFYI(1, ("In CIFSSMBCopy"));
1468 copyRetry:
1469         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1470                         (void **) &pSMBr);
1471         if (rc)
1472                 return rc;
1473
1474         pSMB->BufferFormat = 0x04;
1475         pSMB->Tid2 = target_tid;
1476
1477         pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1478
1479         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1480                 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName, 
1481                                             fromName, PATH_MAX, nls_codepage,
1482                                             remap);
1483                 name_len++;     /* trailing null */
1484                 name_len *= 2;
1485                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
1486                 /* protocol requires ASCII signature byte on Unicode string */
1487                 pSMB->OldFileName[name_len + 1] = 0x00;
1488                 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], 
1489                                 toName, PATH_MAX, nls_codepage, remap);
1490                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1491                 name_len2 *= 2; /* convert to bytes */
1492         } else {                /* BB improve the check for buffer overruns BB */
1493                 name_len = strnlen(fromName, PATH_MAX);
1494                 name_len++;     /* trailing null */
1495                 strncpy(pSMB->OldFileName, fromName, name_len);
1496                 name_len2 = strnlen(toName, PATH_MAX);
1497                 name_len2++;    /* trailing null */
1498                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
1499                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1500                 name_len2++;    /* trailing null */
1501                 name_len2++;    /* signature byte */
1502         }
1503
1504         count = 1 /* 1st signature byte */  + name_len + name_len2;
1505         pSMB->hdr.smb_buf_length += count;
1506         pSMB->ByteCount = cpu_to_le16(count);
1507
1508         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1509                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1510         if (rc) {
1511                 cFYI(1, ("Send error in copy = %d with %d files copied",
1512                         rc, le16_to_cpu(pSMBr->CopyCount)));
1513         }
1514         if (pSMB)
1515                 cifs_buf_release(pSMB);
1516
1517         if (rc == -EAGAIN)
1518                 goto copyRetry;
1519
1520         return rc;
1521 }
1522
1523 int
1524 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1525                       const char *fromName, const char *toName,
1526                       const struct nls_table *nls_codepage)
1527 {
1528         TRANSACTION2_SPI_REQ *pSMB = NULL;
1529         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1530         char *data_offset;
1531         int name_len;
1532         int name_len_target;
1533         int rc = 0;
1534         int bytes_returned = 0;
1535         __u16 params, param_offset, offset, byte_count;
1536
1537         cFYI(1, ("In Symlink Unix style"));
1538 createSymLinkRetry:
1539         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1540                       (void **) &pSMBr);
1541         if (rc)
1542                 return rc;
1543
1544         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1545                 name_len =
1546                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1547                                   /* find define for this maxpathcomponent */
1548                                   , nls_codepage);
1549                 name_len++;     /* trailing null */
1550                 name_len *= 2;
1551
1552         } else {                /* BB improve the check for buffer overruns BB */
1553                 name_len = strnlen(fromName, PATH_MAX);
1554                 name_len++;     /* trailing null */
1555                 strncpy(pSMB->FileName, fromName, name_len);
1556         }
1557         params = 6 + name_len;
1558         pSMB->MaxSetupCount = 0;
1559         pSMB->Reserved = 0;
1560         pSMB->Flags = 0;
1561         pSMB->Timeout = 0;
1562         pSMB->Reserved2 = 0;
1563         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1564                                      InformationLevel) - 4;
1565         offset = param_offset + params;
1566
1567         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1568         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1569                 name_len_target =
1570                     cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1571                                   /* find define for this maxpathcomponent */
1572                                   , nls_codepage);
1573                 name_len_target++;      /* trailing null */
1574                 name_len_target *= 2;
1575         } else {                /* BB improve the check for buffer overruns BB */
1576                 name_len_target = strnlen(toName, PATH_MAX);
1577                 name_len_target++;      /* trailing null */
1578                 strncpy(data_offset, toName, name_len_target);
1579         }
1580
1581         pSMB->MaxParameterCount = cpu_to_le16(2);
1582         /* BB find exact max on data count below from sess */
1583         pSMB->MaxDataCount = cpu_to_le16(1000);
1584         pSMB->SetupCount = 1;
1585         pSMB->Reserved3 = 0;
1586         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1587         byte_count = 3 /* pad */  + params + name_len_target;
1588         pSMB->DataCount = cpu_to_le16(name_len_target);
1589         pSMB->ParameterCount = cpu_to_le16(params);
1590         pSMB->TotalDataCount = pSMB->DataCount;
1591         pSMB->TotalParameterCount = pSMB->ParameterCount;
1592         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1593         pSMB->DataOffset = cpu_to_le16(offset);
1594         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1595         pSMB->Reserved4 = 0;
1596         pSMB->hdr.smb_buf_length += byte_count;
1597         pSMB->ByteCount = cpu_to_le16(byte_count);
1598         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1599                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1600         cifs_stats_inc(&tcon->num_symlinks);
1601         if (rc) {
1602                 cFYI(1,
1603                      ("Send error in SetPathInfo (create symlink) = %d",
1604                       rc));
1605         }
1606
1607         if (pSMB)
1608                 cifs_buf_release(pSMB);
1609
1610         if (rc == -EAGAIN)
1611                 goto createSymLinkRetry;
1612
1613         return rc;
1614 }
1615
1616 int
1617 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1618                        const char *fromName, const char *toName,
1619                        const struct nls_table *nls_codepage, int remap)
1620 {
1621         TRANSACTION2_SPI_REQ *pSMB = NULL;
1622         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1623         char *data_offset;
1624         int name_len;
1625         int name_len_target;
1626         int rc = 0;
1627         int bytes_returned = 0;
1628         __u16 params, param_offset, offset, byte_count;
1629
1630         cFYI(1, ("In Create Hard link Unix style"));
1631 createHardLinkRetry:
1632         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1633                       (void **) &pSMBr);
1634         if (rc)
1635                 return rc;
1636
1637         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1638                 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1639                                             PATH_MAX, nls_codepage, remap);
1640                 name_len++;     /* trailing null */
1641                 name_len *= 2;
1642
1643         } else {                /* BB improve the check for buffer overruns BB */
1644                 name_len = strnlen(toName, PATH_MAX);
1645                 name_len++;     /* trailing null */
1646                 strncpy(pSMB->FileName, toName, name_len);
1647         }
1648         params = 6 + name_len;
1649         pSMB->MaxSetupCount = 0;
1650         pSMB->Reserved = 0;
1651         pSMB->Flags = 0;
1652         pSMB->Timeout = 0;
1653         pSMB->Reserved2 = 0;
1654         param_offset = offsetof(struct smb_com_transaction2_spi_req,
1655                                      InformationLevel) - 4;
1656         offset = param_offset + params;
1657
1658         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1659         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1660                 name_len_target =
1661                     cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1662                                      nls_codepage, remap);
1663                 name_len_target++;      /* trailing null */
1664                 name_len_target *= 2;
1665         } else {                /* BB improve the check for buffer overruns BB */
1666                 name_len_target = strnlen(fromName, PATH_MAX);
1667                 name_len_target++;      /* trailing null */
1668                 strncpy(data_offset, fromName, name_len_target);
1669         }
1670
1671         pSMB->MaxParameterCount = cpu_to_le16(2);
1672         /* BB find exact max on data count below from sess*/
1673         pSMB->MaxDataCount = cpu_to_le16(1000);
1674         pSMB->SetupCount = 1;
1675         pSMB->Reserved3 = 0;
1676         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1677         byte_count = 3 /* pad */  + params + name_len_target;
1678         pSMB->ParameterCount = cpu_to_le16(params);
1679         pSMB->TotalParameterCount = pSMB->ParameterCount;
1680         pSMB->DataCount = cpu_to_le16(name_len_target);
1681         pSMB->TotalDataCount = pSMB->DataCount;
1682         pSMB->ParameterOffset = cpu_to_le16(param_offset);
1683         pSMB->DataOffset = cpu_to_le16(offset);
1684         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1685         pSMB->Reserved4 = 0;
1686         pSMB->hdr.smb_buf_length += byte_count;
1687         pSMB->ByteCount = cpu_to_le16(byte_count);
1688         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1689                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1690         cifs_stats_inc(&tcon->num_hardlinks);
1691         if (rc) {
1692                 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1693         }
1694
1695         cifs_buf_release(pSMB);
1696         if (rc == -EAGAIN)
1697                 goto createHardLinkRetry;
1698
1699         return rc;
1700 }
1701
1702 int
1703 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1704                    const char *fromName, const char *toName,
1705                    const struct nls_table *nls_codepage, int remap)
1706 {
1707         int rc = 0;
1708         NT_RENAME_REQ *pSMB = NULL;
1709         RENAME_RSP *pSMBr = NULL;
1710         int bytes_returned;
1711         int name_len, name_len2;
1712         __u16 count;
1713
1714         cFYI(1, ("In CIFSCreateHardLink"));
1715 winCreateHardLinkRetry:
1716
1717         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1718                       (void **) &pSMBr);
1719         if (rc)
1720                 return rc;
1721
1722         pSMB->SearchAttributes =
1723             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1724                         ATTR_DIRECTORY);
1725         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1726         pSMB->ClusterCount = 0;
1727
1728         pSMB->BufferFormat = 0x04;
1729
1730         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1731                 name_len =
1732                     cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1733                                      PATH_MAX, nls_codepage, remap);
1734                 name_len++;     /* trailing null */
1735                 name_len *= 2;
1736                 pSMB->OldFileName[name_len] = 0;        /* pad */
1737                 pSMB->OldFileName[name_len + 1] = 0x04; 
1738                 name_len2 =
1739                     cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], 
1740                                      toName, PATH_MAX, nls_codepage, remap);
1741                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1742                 name_len2 *= 2; /* convert to bytes */
1743         } else {                /* BB improve the check for buffer overruns BB */
1744                 name_len = strnlen(fromName, PATH_MAX);
1745                 name_len++;     /* trailing null */
1746                 strncpy(pSMB->OldFileName, fromName, name_len);
1747                 name_len2 = strnlen(toName, PATH_MAX);
1748                 name_len2++;    /* trailing null */
1749                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
1750                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1751                 name_len2++;    /* trailing null */
1752                 name_len2++;    /* signature byte */
1753         }
1754
1755         count = 1 /* string type byte */  + name_len + name_len2;
1756         pSMB->hdr.smb_buf_length += count;
1757         pSMB->ByteCount = cpu_to_le16(count);
1758
1759         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1760                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1761         cifs_stats_inc(&tcon->num_hardlinks);
1762         if (rc) {
1763                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1764         }
1765         cifs_buf_release(pSMB);
1766         if (rc == -EAGAIN)
1767                 goto winCreateHardLinkRetry;
1768
1769         return rc;
1770 }
1771
1772 int
1773 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1774                         const unsigned char *searchName,
1775                         char *symlinkinfo, const int buflen,
1776                         const struct nls_table *nls_codepage)
1777 {
1778 /* SMB_QUERY_FILE_UNIX_LINK */
1779         TRANSACTION2_QPI_REQ *pSMB = NULL;
1780         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1781         int rc = 0;
1782         int bytes_returned;
1783         int name_len;
1784         __u16 params, byte_count;
1785
1786         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1787
1788 querySymLinkRetry:
1789         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1790                       (void **) &pSMBr);
1791         if (rc)
1792                 return rc;
1793
1794         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1795                 name_len =
1796                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1797                                   /* find define for this maxpathcomponent */
1798                                   , nls_codepage);
1799                 name_len++;     /* trailing null */
1800                 name_len *= 2;
1801         } else {                /* BB improve the check for buffer overruns BB */
1802                 name_len = strnlen(searchName, PATH_MAX);
1803                 name_len++;     /* trailing null */
1804                 strncpy(pSMB->FileName, searchName, name_len);
1805         }
1806
1807         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
1808         pSMB->TotalDataCount = 0;
1809         pSMB->MaxParameterCount = cpu_to_le16(2);
1810         /* BB find exact max data count below from sess structure BB */
1811         pSMB->MaxDataCount = cpu_to_le16(4000);
1812         pSMB->MaxSetupCount = 0;
1813         pSMB->Reserved = 0;
1814         pSMB->Flags = 0;
1815         pSMB->Timeout = 0;
1816         pSMB->Reserved2 = 0;
1817         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1818         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1819         pSMB->DataCount = 0;
1820         pSMB->DataOffset = 0;
1821         pSMB->SetupCount = 1;
1822         pSMB->Reserved3 = 0;
1823         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1824         byte_count = params + 1 /* pad */ ;
1825         pSMB->TotalParameterCount = cpu_to_le16(params);
1826         pSMB->ParameterCount = pSMB->TotalParameterCount;
1827         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1828         pSMB->Reserved4 = 0;
1829         pSMB->hdr.smb_buf_length += byte_count;
1830         pSMB->ByteCount = cpu_to_le16(byte_count);
1831
1832         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1833                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1834         if (rc) {
1835                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1836         } else {
1837                 /* decode response */
1838
1839                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1840                 if (rc || (pSMBr->ByteCount < 2))
1841                 /* BB also check enough total bytes returned */
1842                         rc = -EIO;      /* bad smb */
1843                 else {
1844                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1845                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1846
1847                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1848                                 name_len = UniStrnlen((wchar_t *) ((char *)
1849                                         &pSMBr->hdr.Protocol +data_offset),
1850                                         min_t(const int, buflen,count) / 2);
1851                         /* BB FIXME investigate remapping reserved chars here */
1852                                 cifs_strfromUCS_le(symlinkinfo,
1853                                         (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1854                                                 data_offset),
1855                                         name_len, nls_codepage);
1856                         } else {
1857                                 strncpy(symlinkinfo,
1858                                         (char *) &pSMBr->hdr.Protocol + 
1859                                                 data_offset,
1860                                         min_t(const int, buflen, count));
1861                         }
1862                         symlinkinfo[buflen] = 0;
1863         /* just in case so calling code does not go off the end of buffer */
1864                 }
1865         }
1866         cifs_buf_release(pSMB);
1867         if (rc == -EAGAIN)
1868                 goto querySymLinkRetry;
1869         return rc;
1870 }
1871
1872 int
1873 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1874                         const unsigned char *searchName,
1875                         char *symlinkinfo, const int buflen,__u16 fid,
1876                         const struct nls_table *nls_codepage)
1877 {
1878         int rc = 0;
1879         int bytes_returned;
1880         int name_len;
1881         struct smb_com_transaction_ioctl_req * pSMB;
1882         struct smb_com_transaction_ioctl_rsp * pSMBr;
1883
1884         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1885         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1886                       (void **) &pSMBr);
1887         if (rc)
1888                 return rc;
1889
1890         pSMB->TotalParameterCount = 0 ;
1891         pSMB->TotalDataCount = 0;
1892         pSMB->MaxParameterCount = cpu_to_le32(2);
1893         /* BB find exact data count max from sess structure BB */
1894         pSMB->MaxDataCount = cpu_to_le32(4000);
1895         pSMB->MaxSetupCount = 4;
1896         pSMB->Reserved = 0;
1897         pSMB->ParameterOffset = 0;
1898         pSMB->DataCount = 0;
1899         pSMB->DataOffset = 0;
1900         pSMB->SetupCount = 4;
1901         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1902         pSMB->ParameterCount = pSMB->TotalParameterCount;
1903         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1904         pSMB->IsFsctl = 1; /* FSCTL */
1905         pSMB->IsRootFlag = 0;
1906         pSMB->Fid = fid; /* file handle always le */
1907         pSMB->ByteCount = 0;
1908
1909         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1910                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1911         if (rc) {
1912                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1913         } else {                /* decode response */
1914                 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1915                 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1916                 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1917                 /* BB also check enough total bytes returned */
1918                         rc = -EIO;      /* bad smb */
1919                 else {
1920                         if(data_count && (data_count < 2048)) {
1921                                 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1922
1923                                 struct reparse_data * reparse_buf = (struct reparse_data *)
1924                                         ((char *)&pSMBr->hdr.Protocol + data_offset);
1925                                 if((char*)reparse_buf >= end_of_smb) {
1926                                         rc = -EIO;
1927                                         goto qreparse_out;
1928                                 }
1929                                 if((reparse_buf->LinkNamesBuf + 
1930                                         reparse_buf->TargetNameOffset +
1931                                         reparse_buf->TargetNameLen) >
1932                                                 end_of_smb) {
1933                                         cFYI(1,("reparse buf extended beyond SMB"));
1934                                         rc = -EIO;
1935                                         goto qreparse_out;
1936                                 }
1937                                 
1938                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1939                                         name_len = UniStrnlen((wchar_t *)
1940                                                         (reparse_buf->LinkNamesBuf + 
1941                                                         reparse_buf->TargetNameOffset),
1942                                                         min(buflen/2, reparse_buf->TargetNameLen / 2)); 
1943                                         cifs_strfromUCS_le(symlinkinfo,
1944                                                 (wchar_t *) (reparse_buf->LinkNamesBuf + 
1945                                                 reparse_buf->TargetNameOffset),
1946                                                 name_len, nls_codepage);
1947                                 } else { /* ASCII names */
1948                                         strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + 
1949                                                 reparse_buf->TargetNameOffset, 
1950                                                 min_t(const int, buflen, reparse_buf->TargetNameLen));
1951                                 }
1952                         } else {
1953                                 rc = -EIO;
1954                                 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1955                         }
1956                         symlinkinfo[buflen] = 0; /* just in case so the caller
1957                                         does not go off the end of the buffer */
1958                         cFYI(1,("readlink result - %s ",symlinkinfo));
1959                 }
1960         }
1961 qreparse_out:
1962         cifs_buf_release(pSMB);
1963
1964         /* Note: On -EAGAIN error only caller can retry on handle based calls
1965                 since file handle passed in no longer valid */
1966
1967         return rc;
1968 }
1969
1970 #ifdef CONFIG_CIFS_POSIX
1971
1972 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1973 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1974 {
1975         /* u8 cifs fields do not need le conversion */
1976         ace->e_perm = (__u16)cifs_ace->cifs_e_perm; 
1977         ace->e_tag  = (__u16)cifs_ace->cifs_e_tag;
1978         ace->e_id   = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1979         /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1980
1981         return;
1982 }
1983
1984 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1985 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1986                                 const int acl_type,const int size_of_data_area)
1987 {
1988         int size =  0;
1989         int i;
1990         __u16 count;
1991         struct cifs_posix_ace * pACE;
1992         struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1993         posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1994
1995         if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1996                 return -EOPNOTSUPP;
1997
1998         if(acl_type & ACL_TYPE_ACCESS) {
1999                 count = le16_to_cpu(cifs_acl->access_entry_count);
2000                 pACE = &cifs_acl->ace_array[0];
2001                 size = sizeof(struct cifs_posix_acl);
2002                 size += sizeof(struct cifs_posix_ace) * count;
2003                 /* check if we would go beyond end of SMB */
2004                 if(size_of_data_area < size) {
2005                         cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
2006                         return -EINVAL;
2007                 }
2008         } else if(acl_type & ACL_TYPE_DEFAULT) {
2009                 count = le16_to_cpu(cifs_acl->access_entry_count);
2010                 size = sizeof(struct cifs_posix_acl);
2011                 size += sizeof(struct cifs_posix_ace) * count;
2012 /* skip past access ACEs to get to default ACEs */
2013                 pACE = &cifs_acl->ace_array[count];
2014                 count = le16_to_cpu(cifs_acl->default_entry_count);
2015                 size += sizeof(struct cifs_posix_ace) * count;
2016                 /* check if we would go beyond end of SMB */
2017                 if(size_of_data_area < size)
2018                         return -EINVAL;
2019         } else {
2020                 /* illegal type */
2021                 return -EINVAL;
2022         }
2023
2024         size = posix_acl_xattr_size(count);
2025         if((buflen == 0) || (local_acl == NULL)) {
2026                 /* used to query ACL EA size */                         
2027         } else if(size > buflen) {
2028                 return -ERANGE;
2029         } else /* buffer big enough */ {
2030                 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
2031                 for(i = 0;i < count ;i++) {
2032                         cifs_convert_ace(&local_acl->a_entries[i],pACE);
2033                         pACE ++;
2034                 }
2035         }
2036         return size;
2037 }
2038
2039 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
2040                         const posix_acl_xattr_entry * local_ace)
2041 {
2042         __u16 rc = 0; /* 0 = ACL converted ok */
2043
2044         cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
2045         cifs_ace->cifs_e_tag =  (__u8)cpu_to_le16(local_ace->e_tag);
2046         /* BB is there a better way to handle the large uid? */
2047         if(local_ace->e_id == -1) {
2048         /* Probably no need to le convert -1 on any arch but can not hurt */
2049                 cifs_ace->cifs_uid = cpu_to_le64(-1);
2050         } else 
2051                 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
2052         /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
2053         return rc;
2054 }
2055
2056 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
2057 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
2058                 const int acl_type)
2059 {
2060         __u16 rc = 0;
2061         struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
2062         posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
2063         int count;
2064         int i;
2065
2066         if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
2067                 return 0;
2068
2069         count = posix_acl_xattr_count((size_t)buflen);
2070         cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
2071                 count,buflen,local_acl->a_version));
2072         if(local_acl->a_version != 2) {
2073                 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
2074                 return 0;
2075         }
2076         cifs_acl->version = cpu_to_le16(1);
2077         if(acl_type == ACL_TYPE_ACCESS) 
2078                 cifs_acl->access_entry_count = count;
2079         else if(acl_type == ACL_TYPE_DEFAULT)
2080                 cifs_acl->default_entry_count = count;
2081         else {
2082                 cFYI(1,("unknown ACL type %d",acl_type));
2083                 return 0;
2084         }
2085         for(i=0;i<count;i++) {
2086                 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
2087                                         &local_acl->a_entries[i]);
2088                 if(rc != 0) {
2089                         /* ACE not converted */
2090                         break;
2091                 }
2092         }
2093         if(rc == 0) {
2094                 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
2095                 rc += sizeof(struct cifs_posix_acl);
2096                 /* BB add check to make sure ACL does not overflow SMB */
2097         }
2098         return rc;
2099 }
2100
2101 int
2102 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
2103                         const unsigned char *searchName,
2104                         char *acl_inf, const int buflen, const int acl_type,
2105                         const struct nls_table *nls_codepage, int remap)
2106 {
2107 /* SMB_QUERY_POSIX_ACL */
2108         TRANSACTION2_QPI_REQ *pSMB = NULL;
2109         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2110         int rc = 0;
2111         int bytes_returned;
2112         int name_len;
2113         __u16 params, byte_count;
2114                                                                                                                                              
2115         cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
2116
2117 queryAclRetry:
2118         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2119                 (void **) &pSMBr);
2120         if (rc)
2121                 return rc;
2122                                                                                                                                              
2123         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2124                 name_len =
2125                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
2126                                          PATH_MAX, nls_codepage, remap);
2127                 name_len++;     /* trailing null */
2128                 name_len *= 2;
2129                 pSMB->FileName[name_len] = 0;
2130                 pSMB->FileName[name_len+1] = 0;
2131         } else {                /* BB improve the check for buffer overruns BB */
2132                 name_len = strnlen(searchName, PATH_MAX);
2133                 name_len++;     /* trailing null */
2134                 strncpy(pSMB->FileName, searchName, name_len);
2135         }
2136
2137         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2138         pSMB->TotalDataCount = 0;
2139         pSMB->MaxParameterCount = cpu_to_le16(2);
2140         /* BB find exact max data count below from sess structure BB */
2141         pSMB->MaxDataCount = cpu_to_le16(4000);
2142         pSMB->MaxSetupCount = 0;
2143         pSMB->Reserved = 0;
2144         pSMB->Flags = 0;
2145         pSMB->Timeout = 0;
2146         pSMB->Reserved2 = 0;
2147         pSMB->ParameterOffset = cpu_to_le16(
2148                 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2149         pSMB->DataCount = 0;
2150         pSMB->DataOffset = 0;
2151         pSMB->SetupCount = 1;
2152         pSMB->Reserved3 = 0;
2153         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2154         byte_count = params + 1 /* pad */ ;
2155         pSMB->TotalParameterCount = cpu_to_le16(params);
2156         pSMB->ParameterCount = pSMB->TotalParameterCount;
2157         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2158         pSMB->Reserved4 = 0;
2159         pSMB->hdr.smb_buf_length += byte_count;
2160         pSMB->ByteCount = cpu_to_le16(byte_count);
2161
2162         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2163                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2164         if (rc) {
2165                 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2166         } else {
2167                 /* decode response */
2168  
2169                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2170                 if (rc || (pSMBr->ByteCount < 2))
2171                 /* BB also check enough total bytes returned */
2172                         rc = -EIO;      /* bad smb */
2173                 else {
2174                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2175                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2176                         rc = cifs_copy_posix_acl(acl_inf,
2177                                 (char *)&pSMBr->hdr.Protocol+data_offset,
2178                                 buflen,acl_type,count);
2179                 }
2180         }
2181         cifs_buf_release(pSMB);
2182         if (rc == -EAGAIN)
2183                 goto queryAclRetry;
2184         return rc;
2185 }
2186
2187 int
2188 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2189                         const unsigned char *fileName,
2190                         const char *local_acl, const int buflen, 
2191                         const int acl_type,
2192                         const struct nls_table *nls_codepage, int remap)
2193 {
2194         struct smb_com_transaction2_spi_req *pSMB = NULL;
2195         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2196         char *parm_data;
2197         int name_len;
2198         int rc = 0;
2199         int bytes_returned = 0;
2200         __u16 params, byte_count, data_count, param_offset, offset;
2201
2202         cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2203 setAclRetry:
2204         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2205                       (void **) &pSMBr);
2206         if (rc)
2207                 return rc;
2208         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2209                 name_len =
2210                         cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, 
2211                                       PATH_MAX, nls_codepage, remap);
2212                 name_len++;     /* trailing null */
2213                 name_len *= 2;
2214         } else {                /* BB improve the check for buffer overruns BB */
2215                 name_len = strnlen(fileName, PATH_MAX);
2216                 name_len++;     /* trailing null */
2217                 strncpy(pSMB->FileName, fileName, name_len);
2218         }
2219         params = 6 + name_len;
2220         pSMB->MaxParameterCount = cpu_to_le16(2);
2221         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2222         pSMB->MaxSetupCount = 0;
2223         pSMB->Reserved = 0;
2224         pSMB->Flags = 0;
2225         pSMB->Timeout = 0;
2226         pSMB->Reserved2 = 0;
2227         param_offset = offsetof(struct smb_com_transaction2_spi_req,
2228                                      InformationLevel) - 4;
2229         offset = param_offset + params;
2230         parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2231         pSMB->ParameterOffset = cpu_to_le16(param_offset);
2232
2233         /* convert to on the wire format for POSIX ACL */
2234         data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2235
2236         if(data_count == 0) {
2237                 rc = -EOPNOTSUPP;
2238                 goto setACLerrorExit;
2239         }
2240         pSMB->DataOffset = cpu_to_le16(offset);
2241         pSMB->SetupCount = 1;
2242         pSMB->Reserved3 = 0;
2243         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2244         pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2245         byte_count = 3 /* pad */  + params + data_count;
2246         pSMB->DataCount = cpu_to_le16(data_count);
2247         pSMB->TotalDataCount = pSMB->DataCount;
2248         pSMB->ParameterCount = cpu_to_le16(params);
2249         pSMB->TotalParameterCount = pSMB->ParameterCount;
2250         pSMB->Reserved4 = 0;
2251         pSMB->hdr.smb_buf_length += byte_count;
2252         pSMB->ByteCount = cpu_to_le16(byte_count);
2253         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2254                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2255         if (rc) {
2256                 cFYI(1, ("Set POSIX ACL returned %d", rc));
2257         }
2258
2259 setACLerrorExit:
2260         cifs_buf_release(pSMB);
2261         if (rc == -EAGAIN)
2262                 goto setAclRetry;
2263         return rc;
2264 }
2265
2266 /* BB fix tabs in this function FIXME BB */
2267 int
2268 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2269                 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2270 {
2271         int rc = 0;
2272         struct smb_t2_qfi_req *pSMB = NULL;
2273         struct smb_t2_qfi_rsp *pSMBr = NULL;
2274         int bytes_returned;
2275         __u16 params, byte_count;
2276
2277         cFYI(1,("In GetExtAttr"));
2278         if(tcon == NULL)
2279                 return -ENODEV;
2280
2281 GetExtAttrRetry:
2282         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2283                       (void **) &pSMBr);
2284         if (rc)
2285                 return rc;
2286
2287         params = 2 /* level */ +2 /* fid */;
2288         pSMB->t2.TotalDataCount = 0;
2289         pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2290         /* BB find exact max data count below from sess structure BB */
2291         pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2292         pSMB->t2.MaxSetupCount = 0;
2293         pSMB->t2.Reserved = 0;
2294         pSMB->t2.Flags = 0;
2295         pSMB->t2.Timeout = 0;
2296         pSMB->t2.Reserved2 = 0;
2297         pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2298                         Fid) - 4);
2299         pSMB->t2.DataCount = 0;
2300         pSMB->t2.DataOffset = 0;
2301         pSMB->t2.SetupCount = 1;
2302         pSMB->t2.Reserved3 = 0;
2303         pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2304         byte_count = params + 1 /* pad */ ;
2305         pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2306         pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2307         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2308         pSMB->Pad = 0;
2309         pSMB->Fid = netfid;
2310         pSMB->hdr.smb_buf_length += byte_count;
2311         pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2312
2313         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2314                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2315         if (rc) {
2316                 cFYI(1, ("error %d in GetExtAttr", rc));
2317         } else {
2318                 /* decode response */
2319                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2320                 if (rc || (pSMBr->ByteCount < 2))
2321                 /* BB also check enough total bytes returned */
2322                         /* If rc should we check for EOPNOSUPP and
2323                         disable the srvino flag? or in caller? */
2324                         rc = -EIO;      /* bad smb */
2325                 else {
2326                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2327                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2328                         struct file_chattr_info * pfinfo;
2329                         /* BB Do we need a cast or hash here ? */
2330                         if(count != 16) {
2331                                 cFYI(1, ("Illegal size ret in GetExtAttr"));
2332                                 rc = -EIO;
2333                                 goto GetExtAttrOut;
2334                         }
2335                         pfinfo = (struct file_chattr_info *)
2336                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
2337                         *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2338                         *pMask = le64_to_cpu(pfinfo->mask);
2339                 }
2340         }
2341 GetExtAttrOut:
2342         cifs_buf_release(pSMB);
2343         if (rc == -EAGAIN)
2344                 goto GetExtAttrRetry;
2345         return rc;
2346 }
2347
2348
2349 #endif /* CONFIG_POSIX */
2350
2351 /* Legacy Query Path Information call for lookup to old servers such
2352    as Win9x/WinME */
2353 int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon,
2354                  const unsigned char *searchName,
2355                  FILE_ALL_INFO * pFinfo,
2356                  const struct nls_table *nls_codepage, int remap)
2357 {
2358         QUERY_INFORMATION_REQ * pSMB;
2359         QUERY_INFORMATION_RSP * pSMBr;
2360         int rc = 0;
2361         int bytes_returned;
2362         int name_len;
2363
2364         cFYI(1, ("In SMBQPath path %s", searchName)); 
2365 QInfRetry:
2366         rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB,
2367                       (void **) &pSMBr);
2368         if (rc)
2369                 return rc;
2370
2371         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2372                 name_len =
2373                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2374                                      PATH_MAX, nls_codepage, remap);
2375                 name_len++;     /* trailing null */
2376                 name_len *= 2;
2377         } else {               
2378                 name_len = strnlen(searchName, PATH_MAX);
2379                 name_len++;     /* trailing null */
2380                 strncpy(pSMB->FileName, searchName, name_len);
2381         }
2382         pSMB->BufferFormat = 0x04;
2383         name_len++; /* account for buffer type byte */  
2384         pSMB->hdr.smb_buf_length += (__u16) name_len;
2385         pSMB->ByteCount = cpu_to_le16(name_len);
2386
2387         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2388                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2389         if (rc) {
2390                 cFYI(1, ("Send error in QueryInfo = %d", rc));
2391         } else if (pFinfo) {            /* decode response */
2392                 memset(pFinfo, 0, sizeof(FILE_ALL_INFO));
2393                 pFinfo->AllocationSize = (__le64) pSMBr->size;
2394                 pFinfo->EndOfFile = (__le64) pSMBr->size;
2395                 pFinfo->Attributes = (__le32) pSMBr->attr;
2396         } else
2397                 rc = -EIO; /* bad buffer passed in */
2398
2399         cifs_buf_release(pSMB);
2400
2401         if (rc == -EAGAIN)
2402                 goto QInfRetry;
2403
2404         return rc;
2405 }
2406
2407
2408
2409
2410 int
2411 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2412                  const unsigned char *searchName,
2413                  FILE_ALL_INFO * pFindData,
2414                  const struct nls_table *nls_codepage, int remap)
2415 {
2416 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2417         TRANSACTION2_QPI_REQ *pSMB = NULL;
2418         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2419         int rc = 0;
2420         int bytes_returned;
2421         int name_len;
2422         __u16 params, byte_count;
2423
2424 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2425 QPathInfoRetry:
2426         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2427                       (void **) &pSMBr);
2428         if (rc)
2429                 return rc;
2430
2431         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2432                 name_len =
2433                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
2434                                      PATH_MAX, nls_codepage, remap);
2435                 name_len++;     /* trailing null */
2436                 name_len *= 2;
2437         } else {                /* BB improve the check for buffer overruns BB */
2438                 name_len = strnlen(searchName, PATH_MAX);
2439                 name_len++;     /* trailing null */
2440                 strncpy(pSMB->FileName, searchName, name_len);
2441         }
2442
2443         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2444         pSMB->TotalDataCount = 0;
2445         pSMB->MaxParameterCount = cpu_to_le16(2);
2446         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2447         pSMB->MaxSetupCount = 0;
2448         pSMB->Reserved = 0;
2449         pSMB->Flags = 0;
2450         pSMB->Timeout = 0;
2451         pSMB->Reserved2 = 0;
2452         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2453         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2454         pSMB->DataCount = 0;
2455         pSMB->DataOffset = 0;
2456         pSMB->SetupCount = 1;
2457         pSMB->Reserved3 = 0;
2458         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2459         byte_count = params + 1 /* pad */ ;
2460         pSMB->TotalParameterCount = cpu_to_le16(params);
2461         pSMB->ParameterCount = pSMB->TotalParameterCount;
2462         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2463         pSMB->Reserved4 = 0;
2464         pSMB->hdr.smb_buf_length += byte_count;
2465         pSMB->ByteCount = cpu_to_le16(byte_count);
2466
2467         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2468                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2469         if (rc) {
2470                 cFYI(1, ("Send error in QPathInfo = %d", rc));
2471         } else {                /* decode response */
2472                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2473
2474                 if (rc || (pSMBr->ByteCount < 40)) 
2475                         rc = -EIO;      /* bad smb */
2476                 else if (pFindData){
2477                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2478                         memcpy((char *) pFindData,
2479                                (char *) &pSMBr->hdr.Protocol +
2480                                data_offset, sizeof (FILE_ALL_INFO));
2481                 } else
2482                     rc = -ENOMEM;
2483         }
2484         cifs_buf_release(pSMB);
2485         if (rc == -EAGAIN)
2486                 goto QPathInfoRetry;
2487
2488         return rc;
2489 }
2490
2491 int
2492 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2493                      const unsigned char *searchName,
2494                      FILE_UNIX_BASIC_INFO * pFindData,
2495                      const struct nls_table *nls_codepage, int remap)
2496 {
2497 /* SMB_QUERY_FILE_UNIX_BASIC */
2498         TRANSACTION2_QPI_REQ *pSMB = NULL;
2499         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2500         int rc = 0;
2501         int bytes_returned = 0;
2502         int name_len;
2503         __u16 params, byte_count;
2504
2505         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2506 UnixQPathInfoRetry:
2507         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2508                       (void **) &pSMBr);
2509         if (rc)
2510                 return rc;
2511
2512         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2513                 name_len =
2514                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2515                                   PATH_MAX, nls_codepage, remap);
2516                 name_len++;     /* trailing null */
2517                 name_len *= 2;
2518         } else {                /* BB improve the check for buffer overruns BB */
2519                 name_len = strnlen(searchName, PATH_MAX);
2520                 name_len++;     /* trailing null */
2521                 strncpy(pSMB->FileName, searchName, name_len);
2522         }
2523
2524         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2525         pSMB->TotalDataCount = 0;
2526         pSMB->MaxParameterCount = cpu_to_le16(2);
2527         /* BB find exact max SMB PDU from sess structure BB */
2528         pSMB->MaxDataCount = cpu_to_le16(4000); 
2529         pSMB->MaxSetupCount = 0;
2530         pSMB->Reserved = 0;
2531         pSMB->Flags = 0;
2532         pSMB->Timeout = 0;
2533         pSMB->Reserved2 = 0;
2534         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2535         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2536         pSMB->DataCount = 0;
2537         pSMB->DataOffset = 0;
2538         pSMB->SetupCount = 1;
2539         pSMB->Reserved3 = 0;
2540         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2541         byte_count = params + 1 /* pad */ ;
2542         pSMB->TotalParameterCount = cpu_to_le16(params);
2543         pSMB->ParameterCount = pSMB->TotalParameterCount;
2544         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2545         pSMB->Reserved4 = 0;
2546         pSMB->hdr.smb_buf_length += byte_count;
2547         pSMB->ByteCount = cpu_to_le16(byte_count);
2548
2549         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2550                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2551         if (rc) {
2552                 cFYI(1, ("Send error in QPathInfo = %d", rc));
2553         } else {                /* decode response */
2554                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2555
2556                 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2557                         rc = -EIO;      /* bad smb */
2558                 } else {
2559                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2560                         memcpy((char *) pFindData,
2561                                (char *) &pSMBr->hdr.Protocol +
2562                                data_offset,
2563                                sizeof (FILE_UNIX_BASIC_INFO));
2564                 }
2565         }
2566         cifs_buf_release(pSMB);
2567         if (rc == -EAGAIN)
2568                 goto UnixQPathInfoRetry;
2569
2570         return rc;
2571 }
2572
2573 #if 0  /* function unused at present */
2574 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2575                const char *searchName, FILE_ALL_INFO * findData,
2576                const struct nls_table *nls_codepage)
2577 {
2578 /* level 257 SMB_ */
2579         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2580         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2581         int rc = 0;
2582         int bytes_returned;
2583         int name_len;
2584         __u16 params, byte_count;
2585
2586         cFYI(1, ("In FindUnique"));
2587 findUniqueRetry:
2588         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2589                       (void **) &pSMBr);
2590         if (rc)
2591                 return rc;
2592
2593         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2594                 name_len =
2595                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2596                                   /* find define for this maxpathcomponent */
2597                                   , nls_codepage);
2598                 name_len++;     /* trailing null */
2599                 name_len *= 2;
2600         } else {                /* BB improve the check for buffer overruns BB */
2601                 name_len = strnlen(searchName, PATH_MAX);
2602                 name_len++;     /* trailing null */
2603                 strncpy(pSMB->FileName, searchName, name_len);
2604         }
2605
2606         params = 12 + name_len /* includes null */ ;
2607         pSMB->TotalDataCount = 0;       /* no EAs */
2608         pSMB->MaxParameterCount = cpu_to_le16(2);
2609         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2610         pSMB->MaxSetupCount = 0;
2611         pSMB->Reserved = 0;
2612         pSMB->Flags = 0;
2613         pSMB->Timeout = 0;
2614         pSMB->Reserved2 = 0;
2615         pSMB->ParameterOffset = cpu_to_le16(
2616          offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2617         pSMB->DataCount = 0;
2618         pSMB->DataOffset = 0;
2619         pSMB->SetupCount = 1;   /* one byte, no need to le convert */
2620         pSMB->Reserved3 = 0;
2621         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2622         byte_count = params + 1 /* pad */ ;
2623         pSMB->TotalParameterCount = cpu_to_le16(params);
2624         pSMB->ParameterCount = pSMB->TotalParameterCount;
2625         pSMB->SearchAttributes =
2626             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2627                         ATTR_DIRECTORY);
2628         pSMB->SearchCount = cpu_to_le16(16);    /* BB increase */
2629         pSMB->SearchFlags = cpu_to_le16(1);
2630         pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2631         pSMB->SearchStorageType = 0;    /* BB what should we set this to? BB */
2632         pSMB->hdr.smb_buf_length += byte_count;
2633         pSMB->ByteCount = cpu_to_le16(byte_count);
2634
2635         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2636                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2637
2638         if (rc) {
2639                 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2640         } else {                /* decode response */
2641                 cifs_stats_inc(&tcon->num_ffirst);
2642                 /* BB fill in */
2643         }
2644
2645         cifs_buf_release(pSMB);
2646         if (rc == -EAGAIN)
2647                 goto findUniqueRetry;
2648
2649         return rc;
2650 }
2651 #endif /* end unused (temporarily) function */
2652
2653 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2654 int
2655 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2656               const char *searchName, 
2657               const struct nls_table *nls_codepage,
2658               __u16 *   pnetfid,
2659               struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2660 {
2661 /* level 257 SMB_ */
2662         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2663         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2664         T2_FFIRST_RSP_PARMS * parms;
2665         int rc = 0;
2666         int bytes_returned = 0;
2667         int name_len;
2668         __u16 params, byte_count;
2669
2670         cFYI(1, ("In FindFirst for %s",searchName));
2671
2672 findFirstRetry:
2673         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2674                       (void **) &pSMBr);
2675         if (rc)
2676                 return rc;
2677
2678         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2679                 name_len =
2680                     cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2681                                  PATH_MAX, nls_codepage, remap);
2682                 /* We can not add the asterik earlier in case
2683                 it got remapped to 0xF03A as if it were part of the
2684                 directory name instead of a wildcard */
2685                 name_len *= 2;
2686                 pSMB->FileName[name_len] = dirsep;
2687                 pSMB->FileName[name_len+1] = 0;
2688                 pSMB->FileName[name_len+2] = '*';
2689                 pSMB->FileName[name_len+3] = 0;
2690                 name_len += 4; /* now the trailing null */
2691                 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2692                 pSMB->FileName[name_len+1] = 0;
2693                 name_len += 2;
2694         } else {        /* BB add check for overrun of SMB buf BB */
2695                 name_len = strnlen(searchName, PATH_MAX);
2696 /* BB fix here and in unicode clause above ie
2697                 if(name_len > buffersize-header)
2698                         free buffer exit; BB */
2699                 strncpy(pSMB->FileName, searchName, name_len);
2700                 pSMB->FileName[name_len] = dirsep;
2701                 pSMB->FileName[name_len+1] = '*';
2702                 pSMB->FileName[name_len+2] = 0;
2703                 name_len += 3;
2704         }
2705
2706         params = 12 + name_len /* includes null */ ;
2707         pSMB->TotalDataCount = 0;       /* no EAs */
2708         pSMB->MaxParameterCount = cpu_to_le16(10);
2709         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2710                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2711         pSMB->MaxSetupCount = 0;
2712         pSMB->Reserved = 0;
2713         pSMB->Flags = 0;
2714         pSMB->Timeout = 0;
2715         pSMB->Reserved2 = 0;
2716         byte_count = params + 1 /* pad */ ;
2717         pSMB->TotalParameterCount = cpu_to_le16(params);
2718         pSMB->ParameterCount = pSMB->TotalParameterCount;
2719         pSMB->ParameterOffset = cpu_to_le16(
2720           offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2721         pSMB->DataCount = 0;
2722         pSMB->DataOffset = 0;
2723         pSMB->SetupCount = 1;   /* one byte, no need to make endian neutral */
2724         pSMB->Reserved3 = 0;
2725         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2726         pSMB->SearchAttributes =
2727             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2728                         ATTR_DIRECTORY);
2729         pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2730         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | 
2731                 CIFS_SEARCH_RETURN_RESUME);
2732         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2733
2734         /* BB what should we set StorageType to? Does it matter? BB */
2735         pSMB->SearchStorageType = 0;
2736         pSMB->hdr.smb_buf_length += byte_count;
2737         pSMB->ByteCount = cpu_to_le16(byte_count);
2738
2739         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2740                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2741         cifs_stats_inc(&tcon->num_ffirst);
2742
2743         if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2744                 /* BB Add code to handle unsupported level rc */
2745                 cFYI(1, ("Error in FindFirst = %d", rc));
2746
2747                 if (pSMB)
2748                         cifs_buf_release(pSMB);
2749
2750                 /* BB eventually could optimize out free and realloc of buf */
2751                 /*    for this case */
2752                 if (rc == -EAGAIN)
2753                         goto findFirstRetry;
2754         } else { /* decode response */
2755                 /* BB remember to free buffer if error BB */
2756                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2757                 if(rc == 0) {
2758                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2759                                 psrch_inf->unicode = TRUE;
2760                         else
2761                                 psrch_inf->unicode = FALSE;
2762
2763                         psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2764                         psrch_inf->srch_entries_start = 
2765                                 (char *) &pSMBr->hdr.Protocol + 
2766                                         le16_to_cpu(pSMBr->t2.DataOffset);
2767                         parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2768                                le16_to_cpu(pSMBr->t2.ParameterOffset));
2769
2770                         if(parms->EndofSearch)
2771                                 psrch_inf->endOfSearch = TRUE;
2772                         else
2773                                 psrch_inf->endOfSearch = FALSE;
2774
2775                         psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
2776                         psrch_inf->index_of_last_entry = 
2777                                 psrch_inf->entries_in_buffer;
2778                         *pnetfid = parms->SearchHandle;
2779                 } else {
2780                         cifs_buf_release(pSMB);
2781                 }
2782         }
2783
2784         return rc;
2785 }
2786
2787 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2788             __u16 searchHandle, struct cifs_search_info * psrch_inf)
2789 {
2790         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2791         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2792         T2_FNEXT_RSP_PARMS * parms;
2793         char *response_data;
2794         int rc = 0;
2795         int bytes_returned, name_len;
2796         __u16 params, byte_count;
2797
2798         cFYI(1, ("In FindNext"));
2799
2800         if(psrch_inf->endOfSearch == TRUE)
2801                 return -ENOENT;
2802
2803         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2804                 (void **) &pSMBr);
2805         if (rc)
2806                 return rc;
2807
2808         params = 14;    /* includes 2 bytes of null string, converted to LE below */
2809         byte_count = 0;
2810         pSMB->TotalDataCount = 0;       /* no EAs */
2811         pSMB->MaxParameterCount = cpu_to_le16(8);
2812         pSMB->MaxDataCount =
2813             cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2814         pSMB->MaxSetupCount = 0;
2815         pSMB->Reserved = 0;
2816         pSMB->Flags = 0;
2817         pSMB->Timeout = 0;
2818         pSMB->Reserved2 = 0;
2819         pSMB->ParameterOffset =  cpu_to_le16(
2820               offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2821         pSMB->DataCount = 0;
2822         pSMB->DataOffset = 0;
2823         pSMB->SetupCount = 1;
2824         pSMB->Reserved3 = 0;
2825         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2826         pSMB->SearchHandle = searchHandle;      /* always kept as le */
2827         pSMB->SearchCount =
2828                 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2829         /* test for Unix extensions */
2830 /*      if (tcon->ses->capabilities & CAP_UNIX) {
2831                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2832                 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2833         } else {
2834                 pSMB->InformationLevel =
2835                    cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2836                 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2837         } */
2838         pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2839         pSMB->ResumeKey = psrch_inf->resume_key;
2840         pSMB->SearchFlags =
2841               cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2842
2843         name_len = psrch_inf->resume_name_len;
2844         params += name_len;
2845         if(name_len < PATH_MAX) {
2846                 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2847                 byte_count += name_len;
2848                 /* 14 byte parm len above enough for 2 byte null terminator */
2849                 pSMB->ResumeFileName[name_len] = 0;
2850                 pSMB->ResumeFileName[name_len+1] = 0;
2851         } else {
2852                 rc = -EINVAL;
2853                 goto FNext2_err_exit;
2854         }
2855         byte_count = params + 1 /* pad */ ;
2856         pSMB->TotalParameterCount = cpu_to_le16(params);
2857         pSMB->ParameterCount = pSMB->TotalParameterCount;
2858         pSMB->hdr.smb_buf_length += byte_count;
2859         pSMB->ByteCount = cpu_to_le16(byte_count);
2860                                                                                               
2861         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2862                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2863         cifs_stats_inc(&tcon->num_fnext);
2864         if (rc) {
2865                 if (rc == -EBADF) {
2866                         psrch_inf->endOfSearch = TRUE;
2867                         rc = 0; /* search probably was closed at end of search above */
2868                 } else
2869                         cFYI(1, ("FindNext returned = %d", rc));
2870         } else {                /* decode response */
2871                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2872                 
2873                 if(rc == 0) {
2874                         /* BB fixme add lock for file (srch_info) struct here */
2875                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2876                                 psrch_inf->unicode = TRUE;
2877                         else
2878                                 psrch_inf->unicode = FALSE;
2879                         response_data = (char *) &pSMBr->hdr.Protocol +
2880                                le16_to_cpu(pSMBr->t2.ParameterOffset);
2881                         parms = (T2_FNEXT_RSP_PARMS *)response_data;
2882                         response_data = (char *)&pSMBr->hdr.Protocol +
2883                                 le16_to_cpu(pSMBr->t2.DataOffset);
2884                         cifs_buf_release(psrch_inf->ntwrk_buf_start);
2885                         psrch_inf->srch_entries_start = response_data;
2886                         psrch_inf->ntwrk_buf_start = (char *)pSMB;
2887                         if(parms->EndofSearch)
2888                                 psrch_inf->endOfSearch = TRUE;
2889                         else
2890                                 psrch_inf->endOfSearch = FALSE;
2891                                                                                               
2892                         psrch_inf->entries_in_buffer  = le16_to_cpu(parms->SearchCount);
2893                         psrch_inf->index_of_last_entry +=
2894                                 psrch_inf->entries_in_buffer;
2895 /*  cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2896
2897                         /* BB fixme add unlock here */
2898                 }
2899
2900         }
2901
2902         /* BB On error, should we leave previous search buf (and count and
2903         last entry fields) intact or free the previous one? */
2904
2905         /* Note: On -EAGAIN error only caller can retry on handle based calls
2906         since file handle passed in no longer valid */
2907 FNext2_err_exit:
2908         if (rc != 0)
2909                 cifs_buf_release(pSMB);
2910                                                                                               
2911         return rc;
2912 }
2913
2914 int
2915 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2916 {
2917         int rc = 0;
2918         FINDCLOSE_REQ *pSMB = NULL;
2919         CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2920         int bytes_returned;
2921
2922         cFYI(1, ("In CIFSSMBFindClose"));
2923         rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2924
2925         /* no sense returning error if session restarted
2926                 as file handle has been closed */
2927         if(rc == -EAGAIN)
2928                 return 0;
2929         if (rc)
2930                 return rc;
2931
2932         pSMBr = (CLOSE_RSP *)pSMB;  /* BB removeme BB */
2933         pSMB->FileID = searchHandle;
2934         pSMB->ByteCount = 0;
2935         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2936                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2937         if (rc) {
2938                 cERROR(1, ("Send error in FindClose = %d", rc));
2939         }
2940         cifs_stats_inc(&tcon->num_fclose);
2941         cifs_small_buf_release(pSMB);
2942
2943         /* Since session is dead, search handle closed on server already */
2944         if (rc == -EAGAIN)
2945                 rc = 0;
2946
2947         return rc;
2948 }
2949
2950 #ifdef CONFIG_CIFS_EXPERIMENTAL
2951 int
2952 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2953                 const unsigned char *searchName,
2954                 __u64 * inode_number,
2955                 const struct nls_table *nls_codepage, int remap)
2956 {
2957         int rc = 0;
2958         TRANSACTION2_QPI_REQ *pSMB = NULL;
2959         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2960         int name_len, bytes_returned;
2961         __u16 params, byte_count;
2962
2963         cFYI(1,("In GetSrvInodeNum for %s",searchName));
2964         if(tcon == NULL)
2965                 return -ENODEV; 
2966
2967 GetInodeNumberRetry:
2968         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2969                       (void **) &pSMBr);
2970         if (rc)
2971                 return rc;
2972
2973
2974         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2975                 name_len =
2976                         cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2977                                 PATH_MAX,nls_codepage, remap);
2978                 name_len++;     /* trailing null */
2979                 name_len *= 2;
2980         } else {                /* BB improve the check for buffer overruns BB */
2981                 name_len = strnlen(searchName, PATH_MAX);
2982                 name_len++;     /* trailing null */
2983                 strncpy(pSMB->FileName, searchName, name_len);
2984         }
2985
2986         params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
2987         pSMB->TotalDataCount = 0;
2988         pSMB->MaxParameterCount = cpu_to_le16(2);
2989         /* BB find exact max data count below from sess structure BB */
2990         pSMB->MaxDataCount = cpu_to_le16(4000);
2991         pSMB->MaxSetupCount = 0;
2992         pSMB->Reserved = 0;
2993         pSMB->Flags = 0;
2994         pSMB->Timeout = 0;
2995         pSMB->Reserved2 = 0;
2996         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2997                 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2998         pSMB->DataCount = 0;
2999         pSMB->DataOffset = 0;
3000         pSMB->SetupCount = 1;
3001         pSMB->Reserved3 = 0;
3002         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3003         byte_count = params + 1 /* pad */ ;
3004         pSMB->TotalParameterCount = cpu_to_le16(params);
3005         pSMB->ParameterCount = pSMB->TotalParameterCount;
3006         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
3007         pSMB->Reserved4 = 0;
3008         pSMB->hdr.smb_buf_length += byte_count;
3009         pSMB->ByteCount = cpu_to_le16(byte_count);
3010
3011         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3012                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3013         if (rc) {
3014                 cFYI(1, ("error %d in QueryInternalInfo", rc));
3015         } else {
3016                 /* decode response */
3017                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3018                 if (rc || (pSMBr->ByteCount < 2))
3019                 /* BB also check enough total bytes returned */
3020                         /* If rc should we check for EOPNOSUPP and
3021                         disable the srvino flag? or in caller? */
3022                         rc = -EIO;      /* bad smb */
3023                 else {
3024                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3025                         __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
3026                         struct file_internal_info * pfinfo;
3027                         /* BB Do we need a cast or hash here ? */
3028                         if(count < 8) {
3029                                 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
3030                                 rc = -EIO;
3031                                 goto GetInodeNumOut;
3032                         }
3033                         pfinfo = (struct file_internal_info *)
3034                                 (data_offset + (char *) &pSMBr->hdr.Protocol);
3035                         *inode_number = pfinfo->UniqueId;
3036                 }
3037         }
3038 GetInodeNumOut:
3039         cifs_buf_release(pSMB);
3040         if (rc == -EAGAIN)
3041                 goto GetInodeNumberRetry;
3042         return rc;
3043 }
3044 #endif /* CIFS_EXPERIMENTAL */
3045
3046 int
3047 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
3048                 const unsigned char *searchName,
3049                 unsigned char **targetUNCs,
3050                 unsigned int *number_of_UNC_in_array,
3051                 const struct nls_table *nls_codepage, int remap)
3052 {
3053 /* TRANS2_GET_DFS_REFERRAL */
3054         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
3055         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
3056         struct dfs_referral_level_3 * referrals = NULL;
3057         int rc = 0;
3058         int bytes_returned;
3059         int name_len;
3060         unsigned int i;
3061         char * temp;
3062         __u16 params, byte_count;
3063         *number_of_UNC_in_array = 0;
3064         *targetUNCs = NULL;
3065
3066         cFYI(1, ("In GetDFSRefer the path %s", searchName));
3067         if (ses == NULL)
3068                 return -ENODEV;
3069 getDFSRetry:
3070         rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
3071                       (void **) &pSMBr);
3072         if (rc)
3073                 return rc;
3074         
3075         /* server pointer checked in called function, 
3076         but should never be null here anyway */
3077         pSMB->hdr.Mid = GetNextMid(ses->server);
3078         pSMB->hdr.Tid = ses->ipc_tid;
3079         pSMB->hdr.Uid = ses->Suid;
3080         if (ses->capabilities & CAP_STATUS32) {
3081                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
3082         }
3083         if (ses->capabilities & CAP_DFS) {
3084                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
3085         }
3086
3087         if (ses->capabilities & CAP_UNICODE) {
3088                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
3089                 name_len =
3090                     cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
3091                                      searchName, PATH_MAX, nls_codepage, remap);
3092                 name_len++;     /* trailing null */
3093                 name_len *= 2;
3094         } else {                /* BB improve the check for buffer overruns BB */
3095                 name_len = strnlen(searchName, PATH_MAX);
3096                 name_len++;     /* trailing null */
3097                 strncpy(pSMB->RequestFileName, searchName, name_len);
3098         }
3099
3100         params = 2 /* level */  + name_len /*includes null */ ;
3101         pSMB->TotalDataCount = 0;
3102         pSMB->DataCount = 0;
3103         pSMB->DataOffset = 0;
3104         pSMB->MaxParameterCount = 0;
3105         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3106         pSMB->MaxSetupCount = 0;
3107         pSMB->Reserved = 0;
3108         pSMB->Flags = 0;
3109         pSMB->Timeout = 0;
3110         pSMB->Reserved2 = 0;
3111         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3112         struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
3113         pSMB->SetupCount = 1;
3114         pSMB->Reserved3 = 0;
3115         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
3116         byte_count = params + 3 /* pad */ ;
3117         pSMB->ParameterCount = cpu_to_le16(params);
3118         pSMB->TotalParameterCount = pSMB->ParameterCount;
3119         pSMB->MaxReferralLevel = cpu_to_le16(3);
3120         pSMB->hdr.smb_buf_length += byte_count;
3121         pSMB->ByteCount = cpu_to_le16(byte_count);
3122
3123         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
3124                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3125         if (rc) {
3126                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
3127         } else {                /* decode response */
3128 /* BB Add logic to parse referrals here */
3129                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3130
3131                 if (rc || (pSMBr->ByteCount < 17))      /* BB also check enough total bytes returned */
3132                         rc = -EIO;      /* bad smb */
3133                 else {
3134                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); 
3135                         __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
3136
3137                         cFYI(1,
3138                              ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
3139                               pSMBr->ByteCount, data_offset));
3140                         referrals = 
3141                             (struct dfs_referral_level_3 *) 
3142                                         (8 /* sizeof start of data block */ +
3143                                         data_offset +
3144                                         (char *) &pSMBr->hdr.Protocol); 
3145                         cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",
3146                                 le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
3147                         /* BB This field is actually two bytes in from start of
3148                            data block so we could do safety check that DataBlock
3149                            begins at address of pSMBr->NumberOfReferrals */
3150                         *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
3151
3152                         /* BB Fix below so can return more than one referral */
3153                         if(*number_of_UNC_in_array > 1)
3154                                 *number_of_UNC_in_array = 1;
3155
3156                         /* get the length of the strings describing refs */
3157                         name_len = 0;
3158                         for(i=0;i<*number_of_UNC_in_array;i++) {
3159                                 /* make sure that DfsPathOffset not past end */
3160                                 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
3161                                 if (offset > data_count) {
3162                                         /* if invalid referral, stop here and do 
3163                                         not try to copy any more */
3164                                         *number_of_UNC_in_array = i;
3165                                         break;
3166                                 } 
3167                                 temp = ((char *)referrals) + offset;
3168
3169                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3170                                         name_len += UniStrnlen((wchar_t *)temp,data_count);
3171                                 } else {
3172                                         name_len += strnlen(temp,data_count);
3173                                 }
3174                                 referrals++;
3175                                 /* BB add check that referral pointer does not fall off end PDU */
3176                                 
3177                         }
3178                         /* BB add check for name_len bigger than bcc */
3179                         *targetUNCs = 
3180                                 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
3181                         if(*targetUNCs == NULL) {
3182                                 rc = -ENOMEM;
3183                                 goto GetDFSRefExit;
3184                         }
3185                         /* copy the ref strings */
3186                         referrals =  
3187                             (struct dfs_referral_level_3 *) 
3188                                         (8 /* sizeof data hdr */ +
3189                                         data_offset + 
3190                                         (char *) &pSMBr->hdr.Protocol);
3191
3192                         for(i=0;i<*number_of_UNC_in_array;i++) {
3193                                 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
3194                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
3195                                         cifs_strfromUCS_le(*targetUNCs,
3196                                                 (wchar_t *) temp, name_len, nls_codepage);
3197                                 } else {
3198                                         strncpy(*targetUNCs,temp,name_len);
3199                                 }
3200                                 /*  BB update target_uncs pointers */
3201                                 referrals++;
3202                         }
3203                         temp = *targetUNCs;
3204                         temp[name_len] = 0;
3205                 }
3206
3207         }
3208 GetDFSRefExit:
3209         if (pSMB)
3210                 cifs_buf_release(pSMB);
3211
3212         if (rc == -EAGAIN)
3213                 goto getDFSRetry;
3214
3215         return rc;
3216 }
3217
3218 /* Query File System Info such as free space to old servers such as Win 9x */
3219 int
3220 SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3221 {
3222 /* level 0x01 SMB_QUERY_FILE_SYSTEM_INFO */
3223         TRANSACTION2_QFSI_REQ *pSMB = NULL;
3224         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3225         FILE_SYSTEM_ALLOC_INFO *response_data;
3226         int rc = 0;
3227         int bytes_returned = 0;
3228         __u16 params, byte_count;
3229
3230         cFYI(1, ("OldQFSInfo"));
3231 oldQFSInfoRetry:
3232         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3233                 (void **) &pSMBr);
3234         if (rc)
3235                 return rc;
3236         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3237                       (void **) &pSMBr);
3238         if (rc)
3239                 return rc;
3240
3241         params = 2;     /* level */
3242         pSMB->TotalDataCount = 0;
3243         pSMB->MaxParameterCount = cpu_to_le16(2);
3244         pSMB->MaxDataCount = cpu_to_le16(1000);
3245         pSMB->MaxSetupCount = 0;
3246         pSMB->Reserved = 0;
3247         pSMB->Flags = 0;
3248         pSMB->Timeout = 0;
3249         pSMB->Reserved2 = 0;
3250         byte_count = params + 1 /* pad */ ;
3251         pSMB->TotalParameterCount = cpu_to_le16(params);
3252         pSMB->ParameterCount = pSMB->TotalParameterCount;
3253         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3254         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3255         pSMB->DataCount = 0;
3256         pSMB->DataOffset = 0;
3257         pSMB->SetupCount = 1;
3258         pSMB->Reserved3 = 0;
3259         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3260         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_ALLOCATION);
3261         pSMB->hdr.smb_buf_length += byte_count;
3262         pSMB->ByteCount = cpu_to_le16(byte_count);
3263
3264         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3265                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3266         if (rc) {
3267                 cFYI(1, ("Send error in QFSInfo = %d", rc));
3268         } else {                /* decode response */
3269                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3270
3271                 if (rc || (pSMBr->ByteCount < 18))
3272                         rc = -EIO;      /* bad smb */
3273                 else {
3274                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3275                         cFYI(1,("qfsinf resp BCC: %d  Offset %d",
3276                                  pSMBr->ByteCount, data_offset));
3277
3278                         response_data =
3279                                 (FILE_SYSTEM_ALLOC_INFO *) 
3280                                 (((char *) &pSMBr->hdr.Protocol) + data_offset);
3281                         FSData->f_bsize =
3282                                 le16_to_cpu(response_data->BytesPerSector) *
3283                                 le32_to_cpu(response_data->
3284                                         SectorsPerAllocationUnit);
3285                         FSData->f_blocks =
3286                                 le32_to_cpu(response_data->TotalAllocationUnits);
3287                         FSData->f_bfree = FSData->f_bavail =
3288                                 le32_to_cpu(response_data->FreeAllocationUnits);
3289                         cFYI(1,
3290                              ("Blocks: %lld  Free: %lld Block size %ld",
3291                               (unsigned long long)FSData->f_blocks,
3292                               (unsigned long long)FSData->f_bfree,
3293                               FSData->f_bsize));
3294                 }
3295         }
3296         cifs_buf_release(pSMB);
3297
3298         if (rc == -EAGAIN)
3299                 goto oldQFSInfoRetry;
3300
3301         return rc;
3302 }
3303
3304 int
3305 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3306 {
3307 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3308         TRANSACTION2_QFSI_REQ *pSMB = NULL;
3309         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3310         FILE_SYSTEM_INFO *response_data;
3311         int rc = 0;
3312         int bytes_returned = 0;
3313         __u16 params, byte_count;
3314
3315         cFYI(1, ("In QFSInfo"));
3316 QFSInfoRetry:
3317         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3318                       (void **) &pSMBr);
3319         if (rc)
3320                 return rc;
3321
3322         params = 2;     /* level */
3323         pSMB->TotalDataCount = 0;
3324         pSMB->MaxParameterCount = cpu_to_le16(2);
3325         pSMB->MaxDataCount = cpu_to_le16(1000);
3326         pSMB->MaxSetupCount = 0;
3327         pSMB->Reserved = 0;
3328         pSMB->Flags = 0;
3329         pSMB->Timeout = 0;
3330         pSMB->Reserved2 = 0;
3331         byte_count = params + 1 /* pad */ ;
3332         pSMB->TotalParameterCount = cpu_to_le16(params);
3333         pSMB->ParameterCount = pSMB->TotalParameterCount;
3334         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3335         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3336         pSMB->DataCount = 0;
3337         pSMB->DataOffset = 0;
3338         pSMB->SetupCount = 1;
3339         pSMB->Reserved3 = 0;
3340         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3341         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3342         pSMB->hdr.smb_buf_length += byte_count;
3343         pSMB->ByteCount = cpu_to_le16(byte_count);
3344
3345         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3346                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3347         if (rc) {
3348                 cFYI(1, ("Send error in QFSInfo = %d", rc));
3349         } else {                /* decode response */
3350                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3351
3352                 if (rc || (pSMBr->ByteCount < 24))
3353                         rc = -EIO;      /* bad smb */
3354                 else {
3355                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3356
3357                         response_data =
3358                             (FILE_SYSTEM_INFO
3359                              *) (((char *) &pSMBr->hdr.Protocol) +
3360                                  data_offset);
3361                         FSData->f_bsize =
3362                             le32_to_cpu(response_data->BytesPerSector) *
3363                             le32_to_cpu(response_data->
3364                                         SectorsPerAllocationUnit);
3365                         FSData->f_blocks =
3366                             le64_to_cpu(response_data->TotalAllocationUnits);
3367                         FSData->f_bfree = FSData->f_bavail =
3368                             le64_to_cpu(response_data->FreeAllocationUnits);
3369                         cFYI(1,
3370                              ("Blocks: %lld  Free: %lld Block size %ld",
3371                               (unsigned long long)FSData->f_blocks,
3372                               (unsigned long long)FSData->f_bfree,
3373                               FSData->f_bsize));
3374                 }
3375         }
3376         cifs_buf_release(pSMB);
3377
3378         if (rc == -EAGAIN)
3379                 goto QFSInfoRetry;
3380
3381         return rc;
3382 }
3383
3384 int
3385 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3386 {
3387 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
3388         TRANSACTION2_QFSI_REQ *pSMB = NULL;
3389         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3390         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3391         int rc = 0;
3392         int bytes_returned = 0;
3393         __u16 params, byte_count;
3394
3395         cFYI(1, ("In QFSAttributeInfo"));
3396 QFSAttributeRetry:
3397         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3398                       (void **) &pSMBr);
3399         if (rc)
3400                 return rc;
3401
3402         params = 2;     /* level */
3403         pSMB->TotalDataCount = 0;
3404         pSMB->MaxParameterCount = cpu_to_le16(2);
3405         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3406         pSMB->MaxSetupCount = 0;
3407         pSMB->Reserved = 0;
3408         pSMB->Flags = 0;
3409         pSMB->Timeout = 0;
3410         pSMB->Reserved2 = 0;
3411         byte_count = params + 1 /* pad */ ;
3412         pSMB->TotalParameterCount = cpu_to_le16(params);
3413         pSMB->ParameterCount = pSMB->TotalParameterCount;
3414         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3415         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3416         pSMB->DataCount = 0;
3417         pSMB->DataOffset = 0;
3418         pSMB->SetupCount = 1;
3419         pSMB->Reserved3 = 0;
3420         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3421         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3422         pSMB->hdr.smb_buf_length += byte_count;
3423         pSMB->ByteCount = cpu_to_le16(byte_count);
3424
3425         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3426                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3427         if (rc) {
3428                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3429         } else {                /* decode response */
3430                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3431
3432                 if (rc || (pSMBr->ByteCount < 13)) {    /* BB also check enough bytes returned */
3433                         rc = -EIO;      /* bad smb */
3434                 } else {
3435                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3436                         response_data =
3437                             (FILE_SYSTEM_ATTRIBUTE_INFO
3438                              *) (((char *) &pSMBr->hdr.Protocol) +
3439                                  data_offset);
3440                         memcpy(&tcon->fsAttrInfo, response_data,
3441                                sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3442                 }
3443         }
3444         cifs_buf_release(pSMB);
3445
3446         if (rc == -EAGAIN)
3447                 goto QFSAttributeRetry;
3448
3449         return rc;
3450 }
3451
3452 int
3453 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3454 {
3455 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3456         TRANSACTION2_QFSI_REQ *pSMB = NULL;
3457         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3458         FILE_SYSTEM_DEVICE_INFO *response_data;
3459         int rc = 0;
3460         int bytes_returned = 0;
3461         __u16 params, byte_count;
3462
3463         cFYI(1, ("In QFSDeviceInfo"));
3464 QFSDeviceRetry:
3465         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3466                       (void **) &pSMBr);
3467         if (rc)
3468                 return rc;
3469
3470         params = 2;     /* level */
3471         pSMB->TotalDataCount = 0;
3472         pSMB->MaxParameterCount = cpu_to_le16(2);
3473         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3474         pSMB->MaxSetupCount = 0;
3475         pSMB->Reserved = 0;
3476         pSMB->Flags = 0;
3477         pSMB->Timeout = 0;
3478         pSMB->Reserved2 = 0;
3479         byte_count = params + 1 /* pad */ ;
3480         pSMB->TotalParameterCount = cpu_to_le16(params);
3481         pSMB->ParameterCount = pSMB->TotalParameterCount;
3482         pSMB->ParameterOffset = cpu_to_le16(offsetof(
3483         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3484
3485         pSMB->DataCount = 0;
3486         pSMB->DataOffset = 0;
3487         pSMB->SetupCount = 1;
3488         pSMB->Reserved3 = 0;
3489         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3490         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3491         pSMB->hdr.smb_buf_length += byte_count;
3492         pSMB->ByteCount = cpu_to_le16(byte_count);
3493
3494         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3495                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3496         if (rc) {
3497                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3498         } else {                /* decode response */
3499                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3500
3501                 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3502                         rc = -EIO;      /* bad smb */
3503                 else {
3504                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3505                         response_data =
3506                             (FILE_SYSTEM_DEVICE_INFO *)
3507                                 (((char *) &pSMBr->hdr.Protocol) +
3508                                  data_offset);
3509                         memcpy(&tcon->fsDevInfo, response_data,
3510                                sizeof (FILE_SYSTEM_DEVICE_INFO));
3511                 }
3512         }
3513         cifs_buf_release(pSMB);
3514
3515         if (rc == -EAGAIN)
3516                 goto QFSDeviceRetry;
3517
3518         return rc;
3519 }
3520
3521 int
3522 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3523 {
3524 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
3525         TRANSACTION2_QFSI_REQ *pSMB = NULL;
3526         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3527         FILE_SYSTEM_UNIX_INFO *response_data;
3528         int rc = 0;
3529         int bytes_returned = 0;
3530         __u16 params, byte_count;
3531
3532         cFYI(1, ("In QFSUnixInfo"));
3533 QFSUnixRetry:
3534         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3535                       (void **) &pSMBr);
3536         if (rc)
3537                 return rc;
3538
3539         params = 2;     /* level */
3540         pSMB->TotalDataCount = 0;
3541         pSMB->DataCount = 0;
3542         pSMB->DataOffset = 0;
3543         pSMB->MaxParameterCount = cpu_to_le16(2);
3544         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
3545         pSMB->MaxSetupCount = 0;
3546         pSMB->Reserved = 0;
3547         pSMB->Flags = 0;
3548         pSMB->Timeout = 0;
3549         pSMB->Reserved2 = 0;
3550         byte_count = params + 1 /* pad */ ;
3551         pSMB->ParameterCount = cpu_to_le16(params);
3552         pSMB->TotalParameterCount = pSMB->ParameterCount;
3553         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
3554         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3555         pSMB->SetupCount = 1;
3556         pSMB->Reserved3 = 0;
3557         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3558         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3559         pSMB->hdr.smb_buf_length += byte_count;
3560         pSMB->ByteCount = cpu_to_le16(byte_count);
3561
3562         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3563                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3564         if (rc) {
3565                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3566         } else {                /* decode response */
3567                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3568
3569                 if (rc || (pSMBr->ByteCount < 13)) {
3570                         rc = -EIO;      /* bad smb */
3571                 } else {
3572                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3573                         response_data =
3574                             (FILE_SYSTEM_UNIX_INFO
3575                              *) (((char *) &pSMBr->hdr.Protocol) +
3576                                  data_offset);
3577                         memcpy(&tcon->fsUnixInfo, response_data,
3578                                sizeof (FILE_SYSTEM_UNIX_INFO));
3579                 }
3580         }
3581         cifs_buf_release(pSMB);
3582
3583         if (rc == -EAGAIN)
3584                 goto QFSUnixRetry;
3585
3586
3587         return rc;
3588 }
3589
3590 int
3591 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3592 {
3593 /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
3594         TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3595         TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3596         int rc = 0;
3597         int bytes_returned = 0;
3598         __u16 params, param_offset, offset, byte_count;
3599
3600         cFYI(1, ("In SETFSUnixInfo"));
3601 SETFSUnixRetry:
3602         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3603                       (void **) &pSMBr);
3604         if (rc)
3605                 return rc;
3606
3607         params = 4;     /* 2 bytes zero followed by info level. */
3608         pSMB->MaxSetupCount = 0;
3609         pSMB->Reserved = 0;
3610         pSMB->Flags = 0;
3611         pSMB->Timeout = 0;
3612         pSMB->Reserved2 = 0;
3613         param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3614         offset = param_offset + params;
3615
3616         pSMB->MaxParameterCount = cpu_to_le16(4);
3617         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
3618         pSMB->SetupCount = 1;
3619         pSMB->Reserved3 = 0;
3620         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3621         byte_count = 1 /* pad */ + params + 12;
3622
3623         pSMB->DataCount = cpu_to_le16(12);
3624         pSMB->ParameterCount = cpu_to_le16(params);
3625         pSMB->TotalDataCount = pSMB->DataCount;
3626         pSMB->TotalParameterCount = pSMB->ParameterCount;
3627         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3628         pSMB->DataOffset = cpu_to_le16(offset);
3629
3630         /* Params. */
3631         pSMB->FileNum = 0;
3632         pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3633
3634         /* Data. */
3635         pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3636         pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3637         pSMB->ClientUnixCap = cpu_to_le64(cap);
3638
3639         pSMB->hdr.smb_buf_length += byte_count;
3640         pSMB->ByteCount = cpu_to_le16(byte_count);
3641
3642         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3643                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3644         if (rc) {
3645                 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3646         } else {                /* decode response */
3647                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3648                 if (rc) {
3649                         rc = -EIO;      /* bad smb */
3650                 }
3651         }
3652         cifs_buf_release(pSMB);
3653
3654         if (rc == -EAGAIN)
3655                 goto SETFSUnixRetry;
3656
3657         return rc;
3658 }
3659
3660
3661
3662 int
3663 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3664                    struct kstatfs *FSData)
3665 {
3666 /* level 0x201  SMB_QUERY_CIFS_POSIX_INFO */
3667         TRANSACTION2_QFSI_REQ *pSMB = NULL;
3668         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3669         FILE_SYSTEM_POSIX_INFO *response_data;
3670         int rc = 0;
3671         int bytes_returned = 0;
3672         __u16 params, byte_count;
3673
3674         cFYI(1, ("In QFSPosixInfo"));
3675 QFSPosixRetry:
3676         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3677                       (void **) &pSMBr);
3678         if (rc)
3679                 return rc;
3680
3681         params = 2;     /* level */
3682         pSMB->TotalDataCount = 0;
3683         pSMB->DataCount = 0;
3684         pSMB->DataOffset = 0;
3685         pSMB->MaxParameterCount = cpu_to_le16(2);
3686         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
3687         pSMB->MaxSetupCount = 0;
3688         pSMB->Reserved = 0;
3689         pSMB->Flags = 0;
3690         pSMB->Timeout = 0;
3691         pSMB->Reserved2 = 0;
3692         byte_count = params + 1 /* pad */ ;
3693         pSMB->ParameterCount = cpu_to_le16(params);
3694         pSMB->TotalParameterCount = pSMB->ParameterCount;
3695         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
3696         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3697         pSMB->SetupCount = 1;
3698         pSMB->Reserved3 = 0;
3699         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3700         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3701         pSMB->hdr.smb_buf_length += byte_count;
3702         pSMB->ByteCount = cpu_to_le16(byte_count);
3703
3704         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3705                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3706         if (rc) {
3707                 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3708         } else {                /* decode response */
3709                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3710
3711                 if (rc || (pSMBr->ByteCount < 13)) {
3712                         rc = -EIO;      /* bad smb */
3713                 } else {
3714                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3715                         response_data =
3716                             (FILE_SYSTEM_POSIX_INFO
3717                              *) (((char *) &pSMBr->hdr.Protocol) +
3718                                  data_offset);
3719                         FSData->f_bsize =
3720                                         le32_to_cpu(response_data->BlockSize);
3721                         FSData->f_blocks =
3722                                         le64_to_cpu(response_data->TotalBlocks);
3723                         FSData->f_bfree =
3724                             le64_to_cpu(response_data->BlocksAvail);
3725                         if(response_data->UserBlocksAvail == -1) {
3726                                 FSData->f_bavail = FSData->f_bfree;
3727                         } else {
3728                                 FSData->f_bavail =
3729                                         le64_to_cpu(response_data->UserBlocksAvail);
3730                         }
3731                         if(response_data->TotalFileNodes != -1)
3732                                 FSData->f_files =
3733                                         le64_to_cpu(response_data->TotalFileNodes);
3734                         if(response_data->FreeFileNodes != -1)
3735                                 FSData->f_ffree =
3736                                         le64_to_cpu(response_data->FreeFileNodes);
3737                 }
3738         }
3739         cifs_buf_release(pSMB);
3740
3741         if (rc == -EAGAIN)
3742                 goto QFSPosixRetry;
3743
3744         return rc;
3745 }
3746
3747
3748 /* We can not use write of zero bytes trick to 
3749    set file size due to need for large file support.  Also note that 
3750    this SetPathInfo is preferred to SetFileInfo based method in next 
3751    routine which is only needed to work around a sharing violation bug
3752    in Samba which this routine can run into */
3753
3754 int
3755 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3756               __u64 size, int SetAllocation, 
3757               const struct nls_table *nls_codepage, int remap)
3758 {
3759         struct smb_com_transaction2_spi_req *pSMB = NULL;
3760         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3761         struct file_end_of_file_info *parm_data;
3762         int name_len;
3763         int rc = 0;
3764         int bytes_returned = 0;
3765         __u16 params, byte_count, data_count, param_offset, offset;
3766
3767         cFYI(1, ("In SetEOF"));
3768 SetEOFRetry:
3769         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3770                       (void **) &pSMBr);
3771         if (rc)
3772                 return rc;
3773
3774         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3775                 name_len =
3776                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3777                                      PATH_MAX, nls_codepage, remap);
3778                 name_len++;     /* trailing null */
3779                 name_len *= 2;
3780         } else {        /* BB improve the check for buffer overruns BB */
3781                 name_len = strnlen(fileName, PATH_MAX);
3782                 name_len++;     /* trailing null */
3783                 strncpy(pSMB->FileName, fileName, name_len);
3784         }
3785         params = 6 + name_len;
3786         data_count = sizeof (struct file_end_of_file_info);
3787         pSMB->MaxParameterCount = cpu_to_le16(2);
3788         pSMB->MaxDataCount = cpu_to_le16(4100);
3789         pSMB->MaxSetupCount = 0;
3790         pSMB->Reserved = 0;
3791         pSMB->Flags = 0;
3792         pSMB->Timeout = 0;
3793         pSMB->Reserved2 = 0;
3794         param_offset = offsetof(struct smb_com_transaction2_spi_req,
3795                                      InformationLevel) - 4;
3796         offset = param_offset + params;
3797         if(SetAllocation) {
3798                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3799                     pSMB->InformationLevel =
3800                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3801                 else
3802                     pSMB->InformationLevel =
3803                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3804         } else /* Set File Size */  {    
3805             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3806                     pSMB->InformationLevel =
3807                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3808             else
3809                     pSMB->InformationLevel =
3810                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3811         }
3812
3813         parm_data =
3814             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3815                                        offset);
3816         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3817         pSMB->DataOffset = cpu_to_le16(offset);
3818         pSMB->SetupCount = 1;
3819         pSMB->Reserved3 = 0;
3820         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3821         byte_count = 3 /* pad */  + params + data_count;
3822         pSMB->DataCount = cpu_to_le16(data_count);
3823         pSMB->TotalDataCount = pSMB->DataCount;
3824         pSMB->ParameterCount = cpu_to_le16(params);
3825         pSMB->TotalParameterCount = pSMB->ParameterCount;
3826         pSMB->Reserved4 = 0;
3827         pSMB->hdr.smb_buf_length += byte_count;
3828         parm_data->FileSize = cpu_to_le64(size);
3829         pSMB->ByteCount = cpu_to_le16(byte_count);
3830         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3831                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3832         if (rc) {
3833                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3834         }
3835
3836         cifs_buf_release(pSMB);
3837
3838         if (rc == -EAGAIN)
3839                 goto SetEOFRetry;
3840
3841         return rc;
3842 }
3843
3844 int
3845 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, 
3846                    __u16 fid, __u32 pid_of_opener, int SetAllocation)
3847 {
3848         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
3849         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3850         char *data_offset;
3851         struct file_end_of_file_info *parm_data;
3852         int rc = 0;
3853         int bytes_returned = 0;
3854         __u16 params, param_offset, offset, byte_count, count;
3855
3856         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3857                         (long long)size));
3858         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3859
3860         if (rc)
3861                 return rc;
3862
3863         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3864
3865         pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3866         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3867     
3868         params = 6;
3869         pSMB->MaxSetupCount = 0;
3870         pSMB->Reserved = 0;
3871         pSMB->Flags = 0;
3872         pSMB->Timeout = 0;
3873         pSMB->Reserved2 = 0;
3874         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3875         offset = param_offset + params;
3876
3877         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;  
3878
3879         count = sizeof(struct file_end_of_file_info);
3880         pSMB->MaxParameterCount = cpu_to_le16(2);
3881         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3882         pSMB->SetupCount = 1;
3883         pSMB->Reserved3 = 0;
3884         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3885         byte_count = 3 /* pad */  + params + count;
3886         pSMB->DataCount = cpu_to_le16(count);
3887         pSMB->ParameterCount = cpu_to_le16(params);
3888         pSMB->TotalDataCount = pSMB->DataCount;
3889         pSMB->TotalParameterCount = pSMB->ParameterCount;
3890         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3891         parm_data =
3892                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3893                         offset);
3894         pSMB->DataOffset = cpu_to_le16(offset);
3895         parm_data->FileSize = cpu_to_le64(size);
3896         pSMB->Fid = fid;
3897         if(SetAllocation) {
3898                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3899                         pSMB->InformationLevel =
3900                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3901                 else
3902                         pSMB->InformationLevel =
3903                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3904         } else /* Set File Size */  {    
3905             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3906                     pSMB->InformationLevel =
3907                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3908             else
3909                     pSMB->InformationLevel =
3910                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3911         }
3912         pSMB->Reserved4 = 0;
3913         pSMB->hdr.smb_buf_length += byte_count;
3914         pSMB->ByteCount = cpu_to_le16(byte_count);
3915         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3916                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3917         if (rc) {
3918                 cFYI(1,
3919                      ("Send error in SetFileInfo (SetFileSize) = %d",
3920                       rc));
3921         }
3922
3923         if (pSMB)
3924                 cifs_small_buf_release(pSMB);
3925
3926         /* Note: On -EAGAIN error only caller can retry on handle based calls 
3927                 since file handle passed in no longer valid */
3928
3929         return rc;
3930 }
3931
3932 /* Some legacy servers such as NT4 require that the file times be set on 
3933    an open handle, rather than by pathname - this is awkward due to
3934    potential access conflicts on the open, but it is unavoidable for these
3935    old servers since the only other choice is to go from 100 nanosecond DCE
3936    time and resort to the original setpathinfo level which takes the ancient
3937    DOS time format with 2 second granularity */
3938 int
3939 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data, 
3940                    __u16 fid)
3941 {
3942         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
3943         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3944         char *data_offset;
3945         int rc = 0;
3946         int bytes_returned = 0;
3947         __u16 params, param_offset, offset, byte_count, count;
3948
3949         cFYI(1, ("Set Times (via SetFileInfo)"));
3950         rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3951
3952         if (rc)
3953                 return rc;
3954
3955         pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3956
3957         /* At this point there is no need to override the current pid
3958         with the pid of the opener, but that could change if we someday
3959         use an existing handle (rather than opening one on the fly) */
3960         /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3961         pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3962     
3963         params = 6;
3964         pSMB->MaxSetupCount = 0;
3965         pSMB->Reserved = 0;
3966         pSMB->Flags = 0;
3967         pSMB->Timeout = 0;
3968         pSMB->Reserved2 = 0;
3969         param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3970         offset = param_offset + params;
3971
3972         data_offset = (char *) (&pSMB->hdr.Protocol) + offset; 
3973
3974         count = sizeof (FILE_BASIC_INFO);
3975         pSMB->MaxParameterCount = cpu_to_le16(2);
3976         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3977         pSMB->SetupCount = 1;
3978         pSMB->Reserved3 = 0;
3979         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3980         byte_count = 3 /* pad */  + params + count;
3981         pSMB->DataCount = cpu_to_le16(count);
3982         pSMB->ParameterCount = cpu_to_le16(params);
3983         pSMB->TotalDataCount = pSMB->DataCount;
3984         pSMB->TotalParameterCount = pSMB->ParameterCount;
3985         pSMB->ParameterOffset = cpu_to_le16(param_offset);
3986         pSMB->DataOffset = cpu_to_le16(offset);
3987         pSMB->Fid = fid;
3988         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3989                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3990         else
3991                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3992         pSMB->Reserved4 = 0;
3993         pSMB->hdr.smb_buf_length += byte_count;
3994         pSMB->ByteCount = cpu_to_le16(byte_count);
3995         memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3996         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3997                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3998         if (rc) {
3999                 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
4000         }
4001
4002         cifs_small_buf_release(pSMB);
4003
4004         /* Note: On -EAGAIN error only caller can retry on handle based calls 
4005                 since file handle passed in no longer valid */
4006
4007         return rc;
4008 }
4009
4010
4011 int
4012 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4013                 const FILE_BASIC_INFO * data, 
4014                 const struct nls_table *nls_codepage, int remap)
4015 {
4016         TRANSACTION2_SPI_REQ *pSMB = NULL;
4017         TRANSACTION2_SPI_RSP *pSMBr = NULL;
4018         int name_len;
4019         int rc = 0;
4020         int bytes_returned = 0;
4021         char *data_offset;
4022         __u16 params, param_offset, offset, byte_count, count;
4023
4024         cFYI(1, ("In SetTimes"));
4025
4026 SetTimesRetry:
4027         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4028                       (void **) &pSMBr);
4029         if (rc)
4030                 return rc;
4031
4032         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4033                 name_len =
4034                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4035                                      PATH_MAX, nls_codepage, remap);
4036                 name_len++;     /* trailing null */
4037                 name_len *= 2;
4038         } else {                /* BB improve the check for buffer overruns BB */
4039                 name_len = strnlen(fileName, PATH_MAX);
4040                 name_len++;     /* trailing null */
4041                 strncpy(pSMB->FileName, fileName, name_len);
4042         }
4043
4044         params = 6 + name_len;
4045         count = sizeof (FILE_BASIC_INFO);
4046         pSMB->MaxParameterCount = cpu_to_le16(2);
4047         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4048         pSMB->MaxSetupCount = 0;
4049         pSMB->Reserved = 0;
4050         pSMB->Flags = 0;
4051         pSMB->Timeout = 0;
4052         pSMB->Reserved2 = 0;
4053         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4054                                      InformationLevel) - 4;
4055         offset = param_offset + params;
4056         data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
4057         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4058         pSMB->DataOffset = cpu_to_le16(offset);
4059         pSMB->SetupCount = 1;
4060         pSMB->Reserved3 = 0;
4061         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4062         byte_count = 3 /* pad */  + params + count;
4063
4064         pSMB->DataCount = cpu_to_le16(count);
4065         pSMB->ParameterCount = cpu_to_le16(params);
4066         pSMB->TotalDataCount = pSMB->DataCount;
4067         pSMB->TotalParameterCount = pSMB->ParameterCount;
4068         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
4069                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
4070         else
4071                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
4072         pSMB->Reserved4 = 0;
4073         pSMB->hdr.smb_buf_length += byte_count;
4074         memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
4075         pSMB->ByteCount = cpu_to_le16(byte_count);
4076         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4077                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4078         if (rc) {
4079                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
4080         }
4081
4082         cifs_buf_release(pSMB);
4083
4084         if (rc == -EAGAIN)
4085                 goto SetTimesRetry;
4086
4087         return rc;
4088 }
4089
4090 /* Can not be used to set time stamps yet (due to old DOS time format) */
4091 /* Can be used to set attributes */
4092 #if 0  /* Possibly not needed - since it turns out that strangely NT4 has a bug
4093           handling it anyway and NT4 was what we thought it would be needed for
4094           Do not delete it until we prove whether needed for Win9x though */
4095 int
4096 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
4097                 __u16 dos_attrs, const struct nls_table *nls_codepage)
4098 {
4099         SETATTR_REQ *pSMB = NULL;
4100         SETATTR_RSP *pSMBr = NULL;
4101         int rc = 0;
4102         int bytes_returned;
4103         int name_len;
4104
4105         cFYI(1, ("In SetAttrLegacy"));
4106
4107 SetAttrLgcyRetry:
4108         rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
4109                       (void **) &pSMBr);
4110         if (rc)
4111                 return rc;
4112
4113         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4114                 name_len =
4115                         ConvertToUCS((__le16 *) pSMB->fileName, fileName, 
4116                                 PATH_MAX, nls_codepage);
4117                 name_len++;     /* trailing null */
4118                 name_len *= 2;
4119         } else {                /* BB improve the check for buffer overruns BB */
4120                 name_len = strnlen(fileName, PATH_MAX);
4121                 name_len++;     /* trailing null */
4122                 strncpy(pSMB->fileName, fileName, name_len);
4123         }
4124         pSMB->attr = cpu_to_le16(dos_attrs);
4125         pSMB->BufferFormat = 0x04;
4126         pSMB->hdr.smb_buf_length += name_len + 1;
4127         pSMB->ByteCount = cpu_to_le16(name_len + 1);
4128         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4129                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4130         if (rc) {
4131                 cFYI(1, ("Error in LegacySetAttr = %d", rc));
4132         }
4133
4134         cifs_buf_release(pSMB);
4135
4136         if (rc == -EAGAIN)
4137                 goto SetAttrLgcyRetry;
4138
4139         return rc;
4140 }
4141 #endif /* temporarily unneeded SetAttr legacy function */
4142
4143 int
4144 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
4145                     char *fileName, __u64 mode, __u64 uid, __u64 gid, 
4146                     dev_t device, const struct nls_table *nls_codepage, 
4147                     int remap)
4148 {
4149         TRANSACTION2_SPI_REQ *pSMB = NULL;
4150         TRANSACTION2_SPI_RSP *pSMBr = NULL;
4151         int name_len;
4152         int rc = 0;
4153         int bytes_returned = 0;
4154         FILE_UNIX_BASIC_INFO *data_offset;
4155         __u16 params, param_offset, offset, count, byte_count;
4156
4157         cFYI(1, ("In SetUID/GID/Mode"));
4158 setPermsRetry:
4159         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4160                       (void **) &pSMBr);
4161         if (rc)
4162                 return rc;
4163
4164         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4165                 name_len =
4166                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, 
4167                                      PATH_MAX, nls_codepage, remap);
4168                 name_len++;     /* trailing null */
4169                 name_len *= 2;
4170         } else {        /* BB improve the check for buffer overruns BB */
4171                 name_len = strnlen(fileName, PATH_MAX);
4172                 name_len++;     /* trailing null */
4173                 strncpy(pSMB->FileName, fileName, name_len);
4174         }
4175
4176         params = 6 + name_len;
4177         count = sizeof (FILE_UNIX_BASIC_INFO);
4178         pSMB->MaxParameterCount = cpu_to_le16(2);
4179         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
4180         pSMB->MaxSetupCount = 0;
4181         pSMB->Reserved = 0;
4182         pSMB->Flags = 0;
4183         pSMB->Timeout = 0;
4184         pSMB->Reserved2 = 0;
4185         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4186                                      InformationLevel) - 4;
4187         offset = param_offset + params;
4188         data_offset =
4189             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
4190                                       offset);
4191         memset(data_offset, 0, count);
4192         pSMB->DataOffset = cpu_to_le16(offset);
4193         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4194         pSMB->SetupCount = 1;
4195         pSMB->Reserved3 = 0;
4196         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4197         byte_count = 3 /* pad */  + params + count;
4198         pSMB->ParameterCount = cpu_to_le16(params);
4199         pSMB->DataCount = cpu_to_le16(count);
4200         pSMB->TotalParameterCount = pSMB->ParameterCount;
4201         pSMB->TotalDataCount = pSMB->DataCount;
4202         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
4203         pSMB->Reserved4 = 0;
4204         pSMB->hdr.smb_buf_length += byte_count;
4205         data_offset->Uid = cpu_to_le64(uid);
4206         data_offset->Gid = cpu_to_le64(gid);
4207         /* better to leave device as zero when it is  */
4208         data_offset->DevMajor = cpu_to_le64(MAJOR(device));
4209         data_offset->DevMinor = cpu_to_le64(MINOR(device));
4210         data_offset->Permissions = cpu_to_le64(mode);
4211     
4212         if(S_ISREG(mode))
4213                 data_offset->Type = cpu_to_le32(UNIX_FILE);
4214         else if(S_ISDIR(mode))
4215                 data_offset->Type = cpu_to_le32(UNIX_DIR);
4216         else if(S_ISLNK(mode))
4217                 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
4218         else if(S_ISCHR(mode))
4219                 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
4220         else if(S_ISBLK(mode))
4221                 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
4222         else if(S_ISFIFO(mode))
4223                 data_offset->Type = cpu_to_le32(UNIX_FIFO);
4224         else if(S_ISSOCK(mode))
4225                 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
4226
4227
4228         pSMB->ByteCount = cpu_to_le16(byte_count);
4229         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4230                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4231         if (rc) {
4232                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
4233         }
4234
4235         if (pSMB)
4236                 cifs_buf_release(pSMB);
4237         if (rc == -EAGAIN)
4238                 goto setPermsRetry;
4239         return rc;
4240 }
4241
4242 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 
4243                   const int notify_subdirs, const __u16 netfid,
4244                   __u32 filter, struct file * pfile, int multishot, 
4245                   const struct nls_table *nls_codepage)
4246 {
4247         int rc = 0;
4248         struct smb_com_transaction_change_notify_req * pSMB = NULL;
4249         struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
4250         struct dir_notify_req *dnotify_req;
4251         int bytes_returned;
4252
4253         cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
4254         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
4255                       (void **) &pSMBr);
4256         if (rc)
4257                 return rc;
4258
4259         pSMB->TotalParameterCount = 0 ;
4260         pSMB->TotalDataCount = 0;
4261         pSMB->MaxParameterCount = cpu_to_le32(2);
4262         /* BB find exact data count max from sess structure BB */
4263         pSMB->MaxDataCount = 0; /* same in little endian or be */
4264         pSMB->MaxSetupCount = 4;
4265         pSMB->Reserved = 0;
4266         pSMB->ParameterOffset = 0;
4267         pSMB->DataCount = 0;
4268         pSMB->DataOffset = 0;
4269         pSMB->SetupCount = 4; /* single byte does not need le conversion */
4270         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
4271         pSMB->ParameterCount = pSMB->TotalParameterCount;
4272         if(notify_subdirs)
4273                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
4274         pSMB->Reserved2 = 0;
4275         pSMB->CompletionFilter = cpu_to_le32(filter);
4276         pSMB->Fid = netfid; /* file handle always le */
4277         pSMB->ByteCount = 0;
4278
4279         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4280                         (struct smb_hdr *) pSMBr, &bytes_returned, -1);
4281         if (rc) {
4282                 cFYI(1, ("Error in Notify = %d", rc));
4283         } else {
4284                 /* Add file to outstanding requests */
4285                 dnotify_req = (struct dir_notify_req *) kmalloc(
4286                                                 sizeof(struct dir_notify_req), GFP_KERNEL);
4287                 dnotify_req->Pid = pSMB->hdr.Pid;
4288                 dnotify_req->PidHigh = pSMB->hdr.PidHigh;
4289                 dnotify_req->Mid = pSMB->hdr.Mid;
4290                 dnotify_req->Tid = pSMB->hdr.Tid;
4291                 dnotify_req->Uid = pSMB->hdr.Uid;
4292                 dnotify_req->netfid = netfid;
4293                 dnotify_req->pfile = pfile;
4294                 dnotify_req->filter = filter;
4295                 dnotify_req->multishot = multishot;
4296                 spin_lock(&GlobalMid_Lock);
4297                 list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
4298                 spin_unlock(&GlobalMid_Lock);
4299         }
4300         cifs_buf_release(pSMB);
4301         return rc;      
4302 }
4303 #ifdef CONFIG_CIFS_XATTR
4304 ssize_t
4305 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4306                  const unsigned char *searchName,
4307                  char * EAData, size_t buf_size,
4308                  const struct nls_table *nls_codepage, int remap)
4309 {
4310                 /* BB assumes one setup word */
4311         TRANSACTION2_QPI_REQ *pSMB = NULL;
4312         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4313         int rc = 0;
4314         int bytes_returned;
4315         int name_len;
4316         struct fea * temp_fea;
4317         char * temp_ptr;
4318         __u16 params, byte_count;
4319
4320         cFYI(1, ("In Query All EAs path %s", searchName));
4321 QAllEAsRetry:
4322         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4323                       (void **) &pSMBr);
4324         if (rc)
4325                 return rc;
4326
4327         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4328                 name_len =
4329                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
4330                                      PATH_MAX, nls_codepage, remap);
4331                 name_len++;     /* trailing null */
4332                 name_len *= 2;
4333         } else {        /* BB improve the check for buffer overruns BB */
4334                 name_len = strnlen(searchName, PATH_MAX);
4335                 name_len++;     /* trailing null */
4336                 strncpy(pSMB->FileName, searchName, name_len);
4337         }
4338
4339         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4340         pSMB->TotalDataCount = 0;
4341         pSMB->MaxParameterCount = cpu_to_le16(2);
4342         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4343         pSMB->MaxSetupCount = 0;
4344         pSMB->Reserved = 0;
4345         pSMB->Flags = 0;
4346         pSMB->Timeout = 0;
4347         pSMB->Reserved2 = 0;
4348         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4349         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4350         pSMB->DataCount = 0;
4351         pSMB->DataOffset = 0;
4352         pSMB->SetupCount = 1;
4353         pSMB->Reserved3 = 0;
4354         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4355         byte_count = params + 1 /* pad */ ;
4356         pSMB->TotalParameterCount = cpu_to_le16(params);
4357         pSMB->ParameterCount = pSMB->TotalParameterCount;
4358         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4359         pSMB->Reserved4 = 0;
4360         pSMB->hdr.smb_buf_length += byte_count;
4361         pSMB->ByteCount = cpu_to_le16(byte_count);
4362
4363         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4364                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4365         if (rc) {
4366                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4367         } else {                /* decode response */
4368                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4369
4370                 /* BB also check enough total bytes returned */
4371                 /* BB we need to improve the validity checking
4372                 of these trans2 responses */
4373                 if (rc || (pSMBr->ByteCount < 4)) 
4374                         rc = -EIO;      /* bad smb */
4375            /* else if (pFindData){
4376                         memcpy((char *) pFindData,
4377                                (char *) &pSMBr->hdr.Protocol +
4378                                data_offset, kl);
4379                 }*/ else {
4380                         /* check that length of list is not more than bcc */
4381                         /* check that each entry does not go beyond length
4382                            of list */
4383                         /* check that each element of each entry does not
4384                            go beyond end of list */
4385                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4386                         struct fealist * ea_response_data;
4387                         rc = 0;
4388                         /* validate_trans2_offsets() */
4389                         /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4390                         ea_response_data = (struct fealist *)
4391                                 (((char *) &pSMBr->hdr.Protocol) +
4392                                 data_offset);
4393                         name_len = le32_to_cpu(ea_response_data->list_len);
4394                         cFYI(1,("ea length %d", name_len));
4395                         if(name_len <= 8) {
4396                         /* returned EA size zeroed at top of function */
4397                                 cFYI(1,("empty EA list returned from server"));
4398                         } else {
4399                                 /* account for ea list len */
4400                                 name_len -= 4;
4401                                 temp_fea = ea_response_data->list;
4402                                 temp_ptr = (char *)temp_fea;
4403                                 while(name_len > 0) {
4404                                         __u16 value_len;
4405                                         name_len -= 4;
4406                                         temp_ptr += 4;
4407                                         rc += temp_fea->name_len;
4408                                 /* account for prefix user. and trailing null */
4409                                         rc = rc + 5 + 1; 
4410                                         if(rc<(int)buf_size) {
4411                                                 memcpy(EAData,"user.",5);
4412                                                 EAData+=5;
4413                                                 memcpy(EAData,temp_ptr,temp_fea->name_len);
4414                                                 EAData+=temp_fea->name_len;
4415                                                 /* null terminate name */
4416                                                 *EAData = 0;
4417                                                 EAData = EAData + 1;
4418                                         } else if(buf_size == 0) {
4419                                                 /* skip copy - calc size only */
4420                                         } else {
4421                                                 /* stop before overrun buffer */
4422                                                 rc = -ERANGE;
4423                                                 break;
4424                                         }
4425                                         name_len -= temp_fea->name_len;
4426                                         temp_ptr += temp_fea->name_len;
4427                                         /* account for trailing null */
4428                                         name_len--;
4429                                         temp_ptr++;
4430                                         value_len = le16_to_cpu(temp_fea->value_len);
4431                                         name_len -= value_len;
4432                                         temp_ptr += value_len;
4433                                         /* BB check that temp_ptr is still within smb BB*/
4434                                 /* no trailing null to account for in value len */
4435                                         /* go on to next EA */
4436                                         temp_fea = (struct fea *)temp_ptr;
4437                                 }
4438                         }
4439                 }
4440         }
4441         if (pSMB)
4442                 cifs_buf_release(pSMB);
4443         if (rc == -EAGAIN)
4444                 goto QAllEAsRetry;
4445
4446         return (ssize_t)rc;
4447 }
4448
4449 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4450                 const unsigned char * searchName,const unsigned char * ea_name,
4451                 unsigned char * ea_value, size_t buf_size, 
4452                 const struct nls_table *nls_codepage, int remap)
4453 {
4454         TRANSACTION2_QPI_REQ *pSMB = NULL;
4455         TRANSACTION2_QPI_RSP *pSMBr = NULL;
4456         int rc = 0;
4457         int bytes_returned;
4458         int name_len;
4459         struct fea * temp_fea;
4460         char * temp_ptr;
4461         __u16 params, byte_count;
4462
4463         cFYI(1, ("In Query EA path %s", searchName));
4464 QEARetry:
4465         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4466                       (void **) &pSMBr);
4467         if (rc)
4468                 return rc;
4469
4470         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4471                 name_len =
4472                     cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, 
4473                                      PATH_MAX, nls_codepage, remap);
4474                 name_len++;     /* trailing null */
4475                 name_len *= 2;
4476         } else {        /* BB improve the check for buffer overruns BB */
4477                 name_len = strnlen(searchName, PATH_MAX);
4478                 name_len++;     /* trailing null */
4479                 strncpy(pSMB->FileName, searchName, name_len);
4480         }
4481
4482         params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4483         pSMB->TotalDataCount = 0;
4484         pSMB->MaxParameterCount = cpu_to_le16(2);
4485         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4486         pSMB->MaxSetupCount = 0;
4487         pSMB->Reserved = 0;
4488         pSMB->Flags = 0;
4489         pSMB->Timeout = 0;
4490         pSMB->Reserved2 = 0;
4491         pSMB->ParameterOffset = cpu_to_le16(offsetof(
4492         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4493         pSMB->DataCount = 0;
4494         pSMB->DataOffset = 0;
4495         pSMB->SetupCount = 1;
4496         pSMB->Reserved3 = 0;
4497         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4498         byte_count = params + 1 /* pad */ ;
4499         pSMB->TotalParameterCount = cpu_to_le16(params);
4500         pSMB->ParameterCount = pSMB->TotalParameterCount;
4501         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4502         pSMB->Reserved4 = 0;
4503         pSMB->hdr.smb_buf_length += byte_count;
4504         pSMB->ByteCount = cpu_to_le16(byte_count);
4505
4506         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4507                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4508         if (rc) {
4509                 cFYI(1, ("Send error in Query EA = %d", rc));
4510         } else {                /* decode response */
4511                 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4512
4513                 /* BB also check enough total bytes returned */
4514                 /* BB we need to improve the validity checking
4515                 of these trans2 responses */
4516                 if (rc || (pSMBr->ByteCount < 4)) 
4517                         rc = -EIO;      /* bad smb */
4518            /* else if (pFindData){
4519                         memcpy((char *) pFindData,
4520                                (char *) &pSMBr->hdr.Protocol +
4521                                data_offset, kl);
4522                 }*/ else {
4523                         /* check that length of list is not more than bcc */
4524                         /* check that each entry does not go beyond length
4525                            of list */
4526                         /* check that each element of each entry does not
4527                            go beyond end of list */
4528                         __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4529                         struct fealist * ea_response_data;
4530                         rc = -ENODATA;
4531                         /* validate_trans2_offsets() */
4532                         /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4533                         ea_response_data = (struct fealist *)
4534                                 (((char *) &pSMBr->hdr.Protocol) +
4535                                 data_offset);
4536                         name_len = le32_to_cpu(ea_response_data->list_len);
4537                         cFYI(1,("ea length %d", name_len));
4538                         if(name_len <= 8) {
4539                         /* returned EA size zeroed at top of function */
4540                                 cFYI(1,("empty EA list returned from server"));
4541                         } else {
4542                                 /* account for ea list len */
4543                                 name_len -= 4;
4544                                 temp_fea = ea_response_data->list;
4545                                 temp_ptr = (char *)temp_fea;
4546                                 /* loop through checking if we have a matching
4547                                 name and then return the associated value */
4548                                 while(name_len > 0) {
4549                                         __u16 value_len;
4550                                         name_len -= 4;
4551                                         temp_ptr += 4;
4552                                         value_len = le16_to_cpu(temp_fea->value_len);
4553                                 /* BB validate that value_len falls within SMB, 
4554                                 even though maximum for name_len is 255 */ 
4555                                         if(memcmp(temp_fea->name,ea_name,
4556                                                   temp_fea->name_len) == 0) {
4557                                                 /* found a match */
4558                                                 rc = value_len;
4559                                 /* account for prefix user. and trailing null */
4560                                                 if(rc<=(int)buf_size) {
4561                                                         memcpy(ea_value,
4562                                                                 temp_fea->name+temp_fea->name_len+1,
4563                                                                 rc);
4564                                                         /* ea values, unlike ea names,
4565                                                         are not null terminated */
4566                                                 } else if(buf_size == 0) {
4567                                                 /* skip copy - calc size only */
4568                                                 } else {
4569                                                         /* stop before overrun buffer */
4570                                                         rc = -ERANGE;
4571                                                 }
4572                                                 break;
4573                                         }
4574                                         name_len -= temp_fea->name_len;
4575                                         temp_ptr += temp_fea->name_len;
4576                                         /* account for trailing null */
4577                                         name_len--;
4578                                         temp_ptr++;
4579                                         name_len -= value_len;
4580                                         temp_ptr += value_len;
4581                                 /* no trailing null to account for in value len */
4582                                         /* go on to next EA */
4583                                         temp_fea = (struct fea *)temp_ptr;
4584                                 }
4585                         } 
4586                 }
4587         }
4588         if (pSMB)
4589                 cifs_buf_release(pSMB);
4590         if (rc == -EAGAIN)
4591                 goto QEARetry;
4592
4593         return (ssize_t)rc;
4594 }
4595
4596 int
4597 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4598                 const char * ea_name, const void * ea_value, 
4599                 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4600                 int remap)
4601 {
4602         struct smb_com_transaction2_spi_req *pSMB = NULL;
4603         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4604         struct fealist *parm_data;
4605         int name_len;
4606         int rc = 0;
4607         int bytes_returned = 0;
4608         __u16 params, param_offset, byte_count, offset, count;
4609
4610         cFYI(1, ("In SetEA"));
4611 SetEARetry:
4612         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4613                       (void **) &pSMBr);
4614         if (rc)
4615                 return rc;
4616
4617         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4618                 name_len =
4619                     cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, 
4620                                      PATH_MAX, nls_codepage, remap);
4621                 name_len++;     /* trailing null */
4622                 name_len *= 2;
4623         } else {                /* BB improve the check for buffer overruns BB */
4624                 name_len = strnlen(fileName, PATH_MAX);
4625                 name_len++;     /* trailing null */
4626                 strncpy(pSMB->FileName, fileName, name_len);
4627         }
4628
4629         params = 6 + name_len;
4630
4631         /* done calculating parms using name_len of file name,
4632         now use name_len to calculate length of ea name
4633         we are going to create in the inode xattrs */
4634         if(ea_name == NULL)
4635                 name_len = 0;
4636         else
4637                 name_len = strnlen(ea_name,255);
4638
4639         count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4640         pSMB->MaxParameterCount = cpu_to_le16(2);
4641         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4642         pSMB->MaxSetupCount = 0;
4643         pSMB->Reserved = 0;
4644         pSMB->Flags = 0;
4645         pSMB->Timeout = 0;
4646         pSMB->Reserved2 = 0;
4647         param_offset = offsetof(struct smb_com_transaction2_spi_req,
4648                                      InformationLevel) - 4;
4649         offset = param_offset + params;
4650         pSMB->InformationLevel =
4651                 cpu_to_le16(SMB_SET_FILE_EA);
4652
4653         parm_data =
4654                 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4655                                        offset);
4656         pSMB->ParameterOffset = cpu_to_le16(param_offset);
4657         pSMB->DataOffset = cpu_to_le16(offset);
4658         pSMB->SetupCount = 1;
4659         pSMB->Reserved3 = 0;
4660         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4661         byte_count = 3 /* pad */  + params + count;
4662         pSMB->DataCount = cpu_to_le16(count);
4663         parm_data->list_len = cpu_to_le32(count);
4664         parm_data->list[0].EA_flags = 0;
4665         /* we checked above that name len is less than 255 */
4666         parm_data->list[0].name_len = (__u8)name_len;;
4667         /* EA names are always ASCII */
4668         if(ea_name)
4669                 strncpy(parm_data->list[0].name,ea_name,name_len);
4670         parm_data->list[0].name[name_len] = 0;
4671         parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4672         /* caller ensures that ea_value_len is less than 64K but
4673         we need to ensure that it fits within the smb */
4674
4675         /*BB add length check that it would fit in negotiated SMB buffer size BB */
4676         /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4677         if(ea_value_len)
4678                 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4679
4680         pSMB->TotalDataCount = pSMB->DataCount;
4681         pSMB->ParameterCount = cpu_to_le16(params);
4682         pSMB->TotalParameterCount = pSMB->ParameterCount;
4683         pSMB->Reserved4 = 0;
4684         pSMB->hdr.smb_buf_length += byte_count;
4685         pSMB->ByteCount = cpu_to_le16(byte_count);
4686         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4687                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4688         if (rc) {
4689                 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4690         }
4691
4692         cifs_buf_release(pSMB);
4693
4694         if (rc == -EAGAIN)
4695                 goto SetEARetry;
4696
4697         return rc;
4698 }
4699
4700 #endif