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