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