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