patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2003
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 <asm/uaccess.h>
34 #include "cifspdu.h"
35 #include "cifsglob.h"
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
39
40 #ifdef CONFIG_CIFS_POSIX
41 static struct {
42         int index;
43         char *name;
44 } protocols[] = {
45         {CIFS_PROT, "\2NT LM 0.12"}, 
46         {CIFS_PROT, "\2POSIX 2"},
47         {BAD_PROT, "\2"}
48 };
49 #else
50 static struct {
51         int index;
52         char *name;
53 } protocols[] = {
54         {CIFS_PROT, "\2NT LM 0.12"}, 
55         {BAD_PROT, "\2"}
56 };
57 #endif
58
59
60 /* Mark as invalid, all open files on tree connections since they
61    were closed when session to server was lost */
62 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
63 {
64         struct cifsFileInfo *open_file = NULL;
65         struct list_head * tmp;
66         struct list_head * tmp1;
67
68 /* list all files open on tree connection and mark them invalid */
69         write_lock(&GlobalSMBSeslock);
70         list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
71                 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
72                 if(open_file) {
73                         open_file->invalidHandle = TRUE;
74                 }
75         }
76         write_unlock(&GlobalSMBSeslock);
77         /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
78 }
79
80 static int
81 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
82          void **request_buf /* returned */ ,
83          void **response_buf /* returned */ )
84 {
85         int rc = 0;
86
87         /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
88            check for tcp and smb session status done differently
89            for those three - in the calling routine */
90         if(tcon) {
91                 if((tcon->ses) && (tcon->ses->server)){
92                         struct nls_table *nls_codepage;
93                                 /* Give Demultiplex thread up to 10 seconds to 
94                                         reconnect, should be greater than cifs socket
95                                         timeout which is 7 seconds */
96                         while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
97                                 wait_event_interruptible_timeout(tcon->ses->server->response_q,
98                                         (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
99                                 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100                                         /* on "soft" mounts we wait once */
101                                         if((tcon->retry == FALSE) || 
102                                            (tcon->ses->status == CifsExiting)) {
103                                                 cFYI(1,("gave up waiting on reconnect in smb_init"));
104                                                 return -EHOSTDOWN;
105                                         } /* else "hard" mount - keep retrying until 
106                                         process is killed or server comes back up */
107                                 } else /* TCP session is reestablished now */
108                                         break;
109                                  
110                         }
111                         
112                         nls_codepage = load_nls_default();
113                 /* need to prevent multiple threads trying to
114                 simultaneously reconnect the same SMB session */
115                         down(&tcon->ses->sesSem);
116                         if(tcon->ses->status == CifsNeedReconnect)
117                                 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
118                         if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
119                                 mark_open_files_invalid(tcon);
120                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
121                                         nls_codepage);
122                                 up(&tcon->ses->sesSem);
123                                 if(rc == 0)
124                                         atomic_inc(&tconInfoReconnectCount);
125
126                                 cFYI(1, ("reconnect tcon rc = %d", rc));
127                                 /* Removed call to reopen open files here - 
128                                         it is safer (and faster) to reopen files
129                                         one at a time as needed in read and write */
130
131                                 /* Check if handle based operation so we 
132                                         know whether we can continue or not without
133                                         returning to caller to reset file handle */
134                                 switch(smb_command) {
135                                         case SMB_COM_READ_ANDX:
136                                         case SMB_COM_WRITE_ANDX:
137                                         case SMB_COM_CLOSE:
138                                         case SMB_COM_FIND_CLOSE2:
139                                         case SMB_COM_LOCKING_ANDX: {
140                                                 unload_nls(nls_codepage);
141                                                 return -EAGAIN;
142                                         }
143                                 }
144                         } else {
145                                 up(&tcon->ses->sesSem);
146                         }
147                         unload_nls(nls_codepage);
148
149                 } else {
150                         return -EIO;
151                 }
152         }
153         if(rc)
154                 return rc;
155
156         *request_buf = cifs_buf_get();
157         if (*request_buf == 0) {
158                 /* BB should we add a retry in here if not a writepage? */
159                 return -ENOMEM;
160         }
161     /* Although the original thought was we needed the response buf for  */
162     /* potential retries of smb operations it turns out we can determine */
163     /* from the mid flags when the request buffer can be resent without  */
164     /* having to use a second distinct buffer for the response */
165         *response_buf = *request_buf; 
166
167         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
168                         wct /*wct */ );
169
170 #ifdef CONFIG_CIFS_STATS
171         if(tcon != NULL) {
172                 atomic_inc(&tcon->num_smbs_sent);
173         }
174 #endif
175         return rc;
176 }
177
178 int
179 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
180 {
181         NEGOTIATE_REQ *pSMB;
182         NEGOTIATE_RSP *pSMBr;
183         int rc = 0;
184         int bytes_returned;
185         struct TCP_Server_Info * server;
186
187         if(ses->server)
188                 server = ses->server;
189         else {
190                 rc = -EIO;
191                 return rc;
192         }
193         rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
194                       (void **) &pSMB, (void **) &pSMBr);
195         if (rc)
196                 return rc;
197
198         pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
199         if (extended_security)
200                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
201
202         pSMB->ByteCount = strlen(protocols[0].name) + 1;
203         strncpy(pSMB->DialectsArray, protocols[0].name, 30);    
204     /* null guaranteed to be at end of source and target buffers anyway */
205
206         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
207         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
208
209         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
210                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
211         if (rc == 0) {
212                 server->secMode = pSMBr->SecurityMode;  
213                 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
214                 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
215                 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
216                 /* probably no need to store and check maxvcs */
217                 server->maxBuf =
218                         min(le32_to_cpu(pSMBr->MaxBufferSize),
219                         (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
220                 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
221                 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
222                 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
223                 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
224                 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);  
225         /* BB with UTC do we ever need to be using srvr timezone? */
226                 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
227                         memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
228                                CIFS_CRYPTO_KEY_SIZE);
229                 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
230                            && (pSMBr->EncryptionKeyLength == 0)) {
231                         /* decode security blob */
232                 } else
233                         rc = -EIO;
234
235                 /* BB might be helpful to save off the domain of server here */
236
237                 if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
238                         if (pSMBr->ByteCount < 16)
239                                 rc = -EIO;
240                         else if (pSMBr->ByteCount == 16) {
241                                 server->secType = RawNTLMSSP;
242                                 if (server->socketUseCount.counter > 1) {
243                                         if (memcmp
244                                                 (server->server_GUID,
245                                                 pSMBr->u.extended_response.
246                                                 GUID, 16) != 0) {
247                                                 cFYI(1,
248                                                         ("UID of server does not match previous connection to same ip address"));
249                                                 memcpy(server->
250                                                         server_GUID,
251                                                         pSMBr->u.
252                                                         extended_response.
253                                                         GUID, 16);
254                                         }
255                                 } else
256                                         memcpy(server->server_GUID,
257                                                pSMBr->u.extended_response.
258                                                GUID, 16);
259                         } else {
260                                 rc = decode_negTokenInit(pSMBr->u.
261                                                          extended_response.
262                                                          SecurityBlob,
263                                                          pSMBr->ByteCount -
264                                                          16, &server->secType);
265                         }
266                 } else
267                         server->capabilities &= ~CAP_EXTENDED_SECURITY;
268                 if(sign_CIFS_PDUs == FALSE) {        
269                         if(server->secMode & SECMODE_SIGN_REQUIRED)
270                                 cERROR(1,
271                                  ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
272                         server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
273                 } else if(sign_CIFS_PDUs == 1) {
274                         if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
275                                 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
276                 }
277                                 
278         }
279         if (pSMB)
280                 cifs_buf_release(pSMB);
281         return rc;
282 }
283
284 int
285 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
286 {
287         struct smb_hdr *smb_buffer;
288         struct smb_hdr *smb_buffer_response;
289         int rc = 0;
290         int length;
291
292         cFYI(1, ("In tree disconnect"));
293         /*
294          *  If last user of the connection and
295          *  connection alive - disconnect it
296          *  If this is the last connection on the server session disconnect it
297          *  (and inside session disconnect we should check if tcp socket needs 
298          *  to be freed and kernel thread woken up).
299          */
300         if (tcon)
301                 down(&tcon->tconSem);
302         else
303                 return -EIO;
304
305         atomic_dec(&tcon->useCount);
306         if (atomic_read(&tcon->useCount) > 0) {
307                 up(&tcon->tconSem);
308                 return -EBUSY;
309         }
310
311         /* No need to return error on this operation if tid invalidated and 
312         closed on server already e.g. due to tcp session crashing */
313         if(tcon->tidStatus == CifsNeedReconnect) {
314                 up(&tcon->tconSem);
315                 return 0;  
316         }
317
318 /* BB remove (from server) list of shares - but with smp safety  BB */
319 /* BB is ses active - do we need to check here - but how? BB */
320         if((tcon->ses == 0) || (tcon->ses->server == 0)) {    
321                 up(&tcon->tconSem);
322                 return -EIO;
323         }
324
325         rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
326                       (void **) &smb_buffer, (void **) &smb_buffer_response);
327         if (rc) {
328                 up(&tcon->tconSem);
329                 return rc;
330         }
331         rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
332                          &length, 0);
333         if (rc)
334                 cFYI(1, (" Tree disconnect failed %d", rc));
335
336         if (smb_buffer)
337                 cifs_buf_release(smb_buffer);
338         up(&tcon->tconSem);
339
340         /* No need to return error on this operation if tid invalidated and 
341         closed on server already e.g. due to tcp session crashing */
342         if (rc == -EAGAIN)
343                 rc = 0;
344
345         return rc;
346 }
347
348 int
349 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
350 {
351         struct smb_hdr *smb_buffer_response;
352         LOGOFF_ANDX_REQ *pSMB;
353         int rc = 0;
354         int length;
355
356         cFYI(1, ("In SMBLogoff for session disconnect"));
357         if (ses)
358                 down(&ses->sesSem);
359         else
360                 return -EIO;
361
362         atomic_dec(&ses->inUse);
363         if (atomic_read(&ses->inUse) > 0) {
364                 up(&ses->sesSem);
365                 return -EBUSY;
366         }
367
368         rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
369                  (void **) &pSMB, (void **) &smb_buffer_response);
370
371         if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
372                 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
373
374         if (rc) {
375                 up(&ses->sesSem);
376                 return rc;
377         }
378
379         pSMB->hdr.Uid = ses->Suid;
380
381         pSMB->AndXCommand = 0xFF;
382         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
383                          smb_buffer_response, &length, 0);
384         if (ses->server) {
385                 atomic_dec(&ses->server->socketUseCount);
386                 if (atomic_read(&ses->server->socketUseCount) == 0) {
387                         spin_lock(&GlobalMid_Lock);
388                         ses->server->tcpStatus = CifsExiting;
389                         spin_unlock(&GlobalMid_Lock);
390                 }
391         }
392         if (pSMB)
393                 cifs_buf_release(pSMB);
394         up(&ses->sesSem);
395
396         /* if session dead then we do not need to do ulogoff,
397                 since server closed smb session, no sense reporting 
398                 error */
399         if (rc == -EAGAIN)
400                 rc = 0;
401         return rc;
402 }
403
404 int
405 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
406                const char *fileName, const struct nls_table *nls_codepage)
407 {
408         DELETE_FILE_REQ *pSMB = NULL;
409         DELETE_FILE_RSP *pSMBr = NULL;
410         int rc = 0;
411         int bytes_returned;
412         int name_len;
413
414 DelFileRetry:
415         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
416                       (void **) &pSMBr);
417         if (rc)
418                 return rc;
419
420         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
421                 name_len =
422                     cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
423                                   /* find define for this maxpathcomponent */
424                                   , nls_codepage);
425                 name_len++;     /* trailing null */
426                 name_len *= 2;
427         } else {                /* BB improve the check for buffer overruns BB */
428                 name_len = strnlen(fileName, 530);
429                 name_len++;     /* trailing null */
430                 strncpy(pSMB->fileName, fileName, name_len);
431         }
432         pSMB->SearchAttributes =
433             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
434         pSMB->ByteCount = name_len + 1;
435         pSMB->BufferFormat = 0x04;
436         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
437         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
438         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
439                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
440         if (rc) {
441                 cFYI(1, ("Error in RMFile = %d", rc));
442         } 
443 #ifdef CONFIG_CIFS_STATS
444         else {
445                 atomic_inc(&tcon->num_deletes);
446         }
447 #endif
448
449         if (pSMB)
450                 cifs_buf_release(pSMB);
451         if (rc == -EAGAIN)
452                 goto DelFileRetry;
453
454         return rc;
455 }
456
457 int
458 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
459              const char *dirName, const struct nls_table *nls_codepage)
460 {
461         DELETE_DIRECTORY_REQ *pSMB = NULL;
462         DELETE_DIRECTORY_RSP *pSMBr = NULL;
463         int rc = 0;
464         int bytes_returned;
465         int name_len;
466
467         cFYI(1, ("In CIFSSMBRmDir"));
468 RmDirRetry:
469         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
470                       (void **) &pSMBr);
471         if (rc)
472                 return rc;
473
474         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
475                 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
476                                 /* find define for this maxpathcomponent */
477                                 , nls_codepage);
478                 name_len++;     /* trailing null */
479                 name_len *= 2;
480         } else {                /* BB improve the check for buffer overruns BB */
481                 name_len = strnlen(dirName, 530);
482                 name_len++;     /* trailing null */
483                 strncpy(pSMB->DirName, dirName, name_len);
484         }
485
486         pSMB->ByteCount = name_len + 1;
487         pSMB->BufferFormat = 0x04;
488         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
489         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
490         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
491                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
492         if (rc) {
493                 cFYI(1, ("Error in RMDir = %d", rc));
494         }
495 #ifdef CONFIG_CIFS_STATS
496         else {
497                 atomic_inc(&tcon->num_rmdirs);
498         }
499 #endif
500
501         if (pSMB)
502                 cifs_buf_release(pSMB);
503         if (rc == -EAGAIN)
504                 goto RmDirRetry;
505         return rc;
506 }
507
508 int
509 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
510              const char *name, const struct nls_table *nls_codepage)
511 {
512         int rc = 0;
513         CREATE_DIRECTORY_REQ *pSMB = NULL;
514         CREATE_DIRECTORY_RSP *pSMBr = NULL;
515         int bytes_returned;
516         int name_len;
517
518         cFYI(1, ("In CIFSSMBMkDir"));
519 MkDirRetry:
520         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
521                       (void **) &pSMBr);
522         if (rc)
523                 return rc;
524
525         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
526                 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
527                                          /* find define for this maxpathcomponent */
528                                          , nls_codepage);
529                 name_len++;     /* trailing null */
530                 name_len *= 2;
531         } else {                /* BB improve the check for buffer overruns BB */
532                 name_len = strnlen(name, 530);
533                 name_len++;     /* trailing null */
534                 strncpy(pSMB->DirName, name, name_len);
535         }
536
537         pSMB->ByteCount = name_len + 1 /* for buf format */ ;
538         pSMB->BufferFormat = 0x04;
539         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
540         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
541         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
542                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
543         if (rc) {
544                 cFYI(1, ("Error in Mkdir = %d", rc));
545         }
546 #ifdef CONFIG_CIFS_STATS
547         else {
548                 atomic_inc(&tcon->num_mkdirs);
549         }
550 #endif
551         if (pSMB)
552                 cifs_buf_release(pSMB);
553         if (rc == -EAGAIN)
554                 goto MkDirRetry;
555         return rc;
556 }
557
558 int
559 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
560             const char *fileName, const int openDisposition,
561             const int access_flags, const int create_options, __u16 * netfid,
562             int *pOplock, FILE_ALL_INFO * pfile_info, 
563             const struct nls_table *nls_codepage)
564 {
565         int rc = -EACCES;
566         OPEN_REQ *pSMB = NULL;
567         OPEN_RSP *pSMBr = NULL;
568         int bytes_returned;
569         int name_len;
570
571 openRetry:
572         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
573                       (void **) &pSMBr);
574         if (rc)
575                 return rc;
576
577         pSMB->AndXCommand = 0xFF;       /* none */
578
579         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
580                 pSMB->ByteCount = 1;    /* account for one byte pad to word boundary */
581                 name_len =
582                     cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
583                                   fileName, 530
584                                   /* find define for this maxpathcomponent */
585                                   , nls_codepage);
586                 name_len++;     /* trailing null */
587                 name_len *= 2;
588                 pSMB->NameLength = cpu_to_le16(name_len);
589         } else {                /* BB improve the check for buffer overruns BB */
590                 pSMB->ByteCount = 0;    /* no pad */
591                 name_len = strnlen(fileName, 530);
592                 name_len++;     /* trailing null */
593                 pSMB->NameLength = cpu_to_le16(name_len);
594                 strncpy(pSMB->fileName, fileName, name_len);
595         }
596         if (*pOplock & REQ_OPLOCK)
597                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
598         else if (*pOplock & REQ_BATCHOPLOCK) {
599                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
600         }
601         pSMB->DesiredAccess = cpu_to_le32(access_flags);
602         pSMB->AllocationSize = 0;
603         pSMB->FileAttributes = ATTR_NORMAL;
604         /* XP does not handle ATTR_POSIX_SEMANTICS */
605         /* but it helps speed up case sensitive checks for other
606         servers such as Samba */
607         if (tcon->ses->capabilities & CAP_UNIX)
608                 pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
609
610         /* if ((omode & S_IWUGO) == 0)
611                 pSMB->FileAttributes |= ATTR_READONLY;*/
612         /*  Above line causes problems due to vfs splitting create into two
613                 pieces - need to set mode after file created not while it is
614                 being created */
615         pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
616         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
617         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
618         pSMB->CreateOptions = cpu_to_le32(create_options);
619         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
620         pSMB->SecurityFlags =
621             cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
622
623         pSMB->ByteCount += name_len;
624         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
625
626         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
627         /* long_op set to 1 to allow for oplock break timeouts */
628         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
629                          (struct smb_hdr *) pSMBr, &bytes_returned, 1);
630         if (rc) {
631                 cFYI(1, ("Error in Open = %d", rc));
632         } else {
633                 *pOplock = pSMBr->OplockLevel;  /* one byte no need to le_to_cpu */
634                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
635                 /* Let caller know file was created so we can set the mode. */
636                 /* Do we care about the CreateAction in any other cases? */
637                 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
638                         *pOplock |= CIFS_CREATE_ACTION; 
639                 if(pfile_info) {
640                     memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
641                         36 /* CreationTime to Attributes */);
642                     /* the file_info buf is endian converted by caller */
643                     pfile_info->AllocationSize = pSMBr->AllocationSize;
644                     pfile_info->EndOfFile = pSMBr->EndOfFile;
645                     pfile_info->NumberOfLinks = cpu_to_le32(1);
646                 }
647
648 #ifdef CONFIG_CIFS_STATS
649                 atomic_inc(&tcon->num_opens);
650 #endif
651         }
652         if (pSMB)
653                 cifs_buf_release(pSMB);
654         if (rc == -EAGAIN)
655                 goto openRetry;
656         return rc;
657 }
658
659 /* If no buffer passed in, then caller wants to do the copy
660         as in the case of readpages so the SMB buffer must be
661         freed by the caller */
662
663 int
664 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
665             const int netfid, const unsigned int count,
666             const __u64 lseek, unsigned int *nbytes, char **buf)
667 {
668         int rc = -EACCES;
669         READ_REQ *pSMB = NULL;
670         READ_RSP *pSMBr = NULL;
671         char *pReadData = NULL;
672         int bytes_returned;
673
674         *nbytes = 0;
675         rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
676                       (void **) &pSMBr);
677         if (rc)
678                 return rc;
679
680         /* tcon and ses pointer are checked in smb_init */
681         if (tcon->ses->server == NULL)
682                 return -ECONNABORTED;
683
684         pSMB->AndXCommand = 0xFF;       /* none */
685         pSMB->Fid = netfid;
686         pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
687         pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
688         pSMB->Remaining = 0;
689         pSMB->MaxCount = cpu_to_le16(count);
690         pSMB->MaxCountHigh = 0;
691         pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
692
693         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
694                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
695         if (rc) {
696                 cERROR(1, ("Send error in read = %d", rc));
697         } else {
698                 pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
699                 *nbytes = pSMBr->DataLength;
700                 /*check that DataLength would not go beyond end of SMB */
701                 if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE) 
702                                 || (pSMBr->DataLength > count)) {
703                         cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
704                         rc = -EIO;
705                         *nbytes = 0;
706                 } else {
707                         pReadData =
708                             (char *) (&pSMBr->hdr.Protocol) +
709                             le16_to_cpu(pSMBr->DataOffset);
710 /*                      if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
711                                 cERROR(1,("Faulting on read rc = %d",rc));
712                                 rc = -EFAULT;
713                         }*/ /* can not use copy_to_user when using page cache*/
714                         if(*buf)
715                             memcpy(*buf,pReadData,pSMBr->DataLength);
716                 }
717         }
718         if (pSMB) {
719                 if(*buf)
720                         cifs_buf_release(pSMB);
721                 else
722                         *buf = (char *)pSMB;
723         }
724
725         /* Note: On -EAGAIN error only caller can retry on handle based calls 
726                 since file handle passed in no longer valid */
727         return rc;
728 }
729
730 int
731 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
732              const int netfid, const unsigned int count,
733              const __u64 offset, unsigned int *nbytes, const char *buf,
734              const int long_op)
735 {
736         int rc = -EACCES;
737         WRITE_REQ *pSMB = NULL;
738         WRITE_RSP *pSMBr = NULL;
739         int bytes_returned;
740
741         rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
742                       (void **) &pSMBr);
743         if (rc)
744                 return rc;
745         /* tcon and ses pointer are checked in smb_init */
746         if (tcon->ses->server == NULL)
747                 return -ECONNABORTED;
748
749         pSMB->AndXCommand = 0xFF;       /* none */
750         pSMB->Fid = netfid;
751         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
752         pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
753         pSMB->Remaining = 0;
754         if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
755                 pSMB->DataLengthLow =
756                     (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
757         else
758                 pSMB->DataLengthLow = count;
759         pSMB->DataLengthHigh = 0;
760         pSMB->DataOffset =
761             cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
762
763         memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
764
765         pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
766         pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
767         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
768         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
769
770         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
771                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
772         if (rc) {
773                 cFYI(1, ("Send error in write = %d", rc));
774                 *nbytes = 0;
775         } else
776                 *nbytes = le16_to_cpu(pSMBr->Count);
777
778         if (pSMB)
779                 cifs_buf_release(pSMB);
780
781         /* Note: On -EAGAIN error only caller can retry on handle based calls 
782                 since file handle passed in no longer valid */
783
784         return rc;
785 }
786
787 int
788 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
789             const __u16 smb_file_id, const __u64 len,
790             const __u64 offset, const __u32 numUnlock,
791             const __u32 numLock, const __u8 lockType, const int waitFlag)
792 {
793         int rc = 0;
794         LOCK_REQ *pSMB = NULL;
795         LOCK_RSP *pSMBr = NULL;
796         int bytes_returned;
797         int timeout = 0;
798         __u64 temp;
799
800         cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
801         rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
802                       (void **) &pSMBr);
803         if (rc)
804                 return rc;
805
806         if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
807                 timeout = -1; /* no response expected */
808                 pSMB->Timeout = 0;
809         } else if (waitFlag == TRUE) {
810                 timeout = 3;  /* blocking operation, no timeout */
811                 pSMB->Timeout = -1; /* blocking - do not time out */
812         } else {
813                 pSMB->Timeout = 0;
814         }
815
816         pSMB->NumberOfLocks = cpu_to_le32(numLock);
817         pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
818         pSMB->LockType = lockType;
819         pSMB->AndXCommand = 0xFF;       /* none */
820         pSMB->Fid = smb_file_id; /* netfid stays le */
821
822         pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
823         temp = cpu_to_le64(len);
824         pSMB->Locks[0].LengthLow = (__u32)(len & 0xFFFFFFFF);
825         pSMB->Locks[0].LengthHigh =  (__u32)(len>>32);
826         temp = cpu_to_le64(offset);
827         pSMB->Locks[0].OffsetLow = (__u32)(offset & 0xFFFFFFFF);
828         pSMB->Locks[0].OffsetHigh = (__u32)(offset>>32);
829         pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
830         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
831         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
832
833         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
834                          (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
835
836         if (rc) {
837                 cFYI(1, ("Send error in Lock = %d", rc));
838         }
839         if (pSMB)
840                 cifs_buf_release(pSMB);
841
842         /* Note: On -EAGAIN error only caller can retry on handle based calls 
843         since file handle passed in no longer valid */
844         return rc;
845 }
846
847 int
848 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
849 {
850         int rc = 0;
851         CLOSE_REQ *pSMB = NULL;
852         CLOSE_RSP *pSMBr = NULL;
853         int bytes_returned;
854         cFYI(1, ("In CIFSSMBClose"));
855
856 /* do not retry on dead session on close */
857         rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
858                       (void **) &pSMBr);
859         if(rc == -EAGAIN)
860                 return 0;
861         if (rc)
862                 return rc;
863
864         pSMB->FileID = (__u16) smb_file_id;
865         pSMB->LastWriteTime = 0;
866         pSMB->ByteCount = 0;
867         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
868                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
869         if (rc) {
870                 if(rc!=-EINTR) {
871                         /* EINTR is expected when user ctl-c to kill app */
872                         cERROR(1, ("Send error in Close = %d", rc));
873                 }
874         }
875         if (pSMB)
876                 cifs_buf_release(pSMB);
877
878         /* Since session is dead, file will be closed on server already */
879         if(rc == -EAGAIN)
880                 rc = 0;
881
882         return rc;
883 }
884
885 int
886 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
887               const char *fromName, const char *toName,
888               const struct nls_table *nls_codepage)
889 {
890         int rc = 0;
891         RENAME_REQ *pSMB = NULL;
892         RENAME_RSP *pSMBr = NULL;
893         int bytes_returned;
894         int name_len, name_len2;
895
896         cFYI(1, ("In CIFSSMBRename"));
897 renameRetry:
898         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
899                       (void **) &pSMBr);
900         if (rc)
901                 return rc;
902
903         pSMB->BufferFormat = 0x04;
904         pSMB->SearchAttributes =
905             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
906                         ATTR_DIRECTORY);
907
908         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
909                 name_len =
910                     cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
911                                   /* find define for this maxpathcomponent */
912                                   , nls_codepage);
913                 name_len++;     /* trailing null */
914                 name_len *= 2;
915                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
916         /* protocol requires ASCII signature byte on Unicode string */
917                 pSMB->OldFileName[name_len + 1] = 0x00;
918                 name_len2 =
919                     cifs_strtoUCS((wchar_t *) & pSMB->
920                                   OldFileName[name_len + 2], toName, 530,
921                                   nls_codepage);
922                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
923                 name_len2 *= 2; /* convert to bytes */
924         } else {                /* BB improve the check for buffer overruns BB */
925                 name_len = strnlen(fromName, 530);
926                 name_len++;     /* trailing null */
927                 strncpy(pSMB->OldFileName, fromName, name_len);
928                 name_len2 = strnlen(toName, 530);
929                 name_len2++;    /* trailing null */
930                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
931                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
932                 name_len2++;    /* trailing null */
933                 name_len2++;    /* signature byte */
934         }
935
936         pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
937         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
938         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
939
940         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
941                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
942         if (rc) {
943                 cFYI(1, ("Send error in rename = %d", rc));
944         }
945         if (pSMB)
946                 cifs_buf_release(pSMB);
947
948         if (rc == -EAGAIN)
949                 goto renameRetry;
950
951         return rc;
952 }
953
954 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, 
955                 int netfid, char * target_name, const struct nls_table * nls_codepage) 
956 {
957         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
958         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
959         struct set_file_rename * rename_info;
960         char *data_offset;
961         char dummy_string[30];
962         int rc = 0;
963         int bytes_returned = 0;
964         int len_of_str;
965
966         cFYI(1, ("Rename to File by handle"));
967         rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
968                         (void **) &pSMBr);
969         if (rc)
970                 return rc;
971
972         pSMB->ParameterCount = 6;
973         pSMB->MaxSetupCount = 0;
974         pSMB->Reserved = 0;
975         pSMB->Flags = 0;
976         pSMB->Timeout = 0;
977         pSMB->Reserved2 = 0;
978         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
979                                 Fid) - 4;
980         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
981
982         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
983         rename_info = (struct set_file_rename *) data_offset;
984         pSMB->MaxParameterCount = cpu_to_le16(2);
985         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
986         pSMB->SetupCount = 1;
987         pSMB->Reserved3 = 0;
988         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
989         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount;
990         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
991         pSMB->TotalParameterCount = pSMB->ParameterCount;
992         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
993         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
994         /* construct random name ".cifs_tmp<inodenum><mid>" */
995         rename_info->overwrite = cpu_to_le32(1);
996         rename_info->root_fid  = 0;
997         /* unicode only call */
998         if(target_name == NULL) {
999                 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1000                 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
1001         } else {
1002                 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
1003         }
1004         rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1005         pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1006         pSMB->ByteCount += pSMB->DataCount;
1007         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1008         pSMB->TotalDataCount = pSMB->DataCount;
1009         pSMB->Fid = netfid;
1010         pSMB->InformationLevel =
1011                 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1012         pSMB->Reserved4 = 0;
1013         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1014         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1015         rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1016                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1017         if (rc) {
1018                 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1019         }
1020
1021         if (pSMB)
1022                 cifs_buf_release(pSMB);
1023
1024         /* Note: On -EAGAIN error only caller can retry on handle based calls
1025                 since file handle passed in no longer valid */
1026
1027         return rc;
1028 }
1029
1030 int
1031 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, 
1032             const __u16 target_tid, const char *toName, const int flags,
1033             const struct nls_table *nls_codepage)
1034 {
1035         int rc = 0;
1036         COPY_REQ *pSMB = NULL;
1037         COPY_RSP *pSMBr = NULL;
1038         int bytes_returned;
1039         int name_len, name_len2;
1040
1041         cFYI(1, ("In CIFSSMBCopy"));
1042 copyRetry:
1043         rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1044                         (void **) &pSMBr);
1045         if (rc)
1046                 return rc;
1047
1048         pSMB->BufferFormat = 0x04;
1049         pSMB->Tid2 = target_tid;
1050
1051         if(flags & COPY_TREE)
1052                 pSMB->Flags |= COPY_TREE;
1053         pSMB->Flags = cpu_to_le16(pSMB->Flags);
1054
1055         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1056                 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, 
1057                                 fromName, 
1058                                 530 /* find define for this maxpathcomponent */,
1059                                 nls_codepage);
1060                 name_len++;     /* trailing null */
1061                 name_len *= 2;
1062                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
1063                 /* protocol requires ASCII signature byte on Unicode string */
1064                 pSMB->OldFileName[name_len + 1] = 0x00;
1065                 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1066                                 OldFileName[name_len + 2], toName, 530,
1067                                 nls_codepage);
1068                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1069                 name_len2 *= 2; /* convert to bytes */
1070         } else {                /* BB improve the check for buffer overruns BB */
1071                 name_len = strnlen(fromName, 530);
1072                 name_len++;     /* trailing null */
1073                 strncpy(pSMB->OldFileName, fromName, name_len);
1074                 name_len2 = strnlen(toName, 530);
1075                 name_len2++;    /* trailing null */
1076                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
1077                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1078                 name_len2++;    /* trailing null */
1079                 name_len2++;    /* signature byte */
1080         }
1081
1082         pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
1083         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1084         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1085
1086         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1087                 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1088         if (rc) {
1089                 cFYI(1, ("Send error in copy = %d with %d files copied",
1090                         rc, pSMBr->CopyCount));
1091         }
1092         if (pSMB)
1093                 cifs_buf_release(pSMB);
1094
1095         if (rc == -EAGAIN)
1096                 goto copyRetry;
1097
1098         return rc;
1099 }
1100
1101 int
1102 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1103                       const char *fromName, const char *toName,
1104                       const struct nls_table *nls_codepage)
1105 {
1106         TRANSACTION2_SPI_REQ *pSMB = NULL;
1107         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1108         char *data_offset;
1109         int name_len;
1110         int name_len_target;
1111         int rc = 0;
1112         int bytes_returned = 0;
1113
1114         cFYI(1, ("In Symlink Unix style"));
1115 createSymLinkRetry:
1116         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1117                       (void **) &pSMBr);
1118         if (rc)
1119                 return rc;
1120
1121         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1122                 name_len =
1123                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
1124                                   /* find define for this maxpathcomponent */
1125                                   , nls_codepage);
1126                 name_len++;     /* trailing null */
1127                 name_len *= 2;
1128
1129         } else {                /* BB improve the check for buffer overruns BB */
1130                 name_len = strnlen(fromName, 530);
1131                 name_len++;     /* trailing null */
1132                 strncpy(pSMB->FileName, fromName, name_len);
1133         }
1134         pSMB->ParameterCount = 6 + name_len;
1135         pSMB->MaxSetupCount = 0;
1136         pSMB->Reserved = 0;
1137         pSMB->Flags = 0;
1138         pSMB->Timeout = 0;
1139         pSMB->Reserved2 = 0;
1140         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1141                                      InformationLevel) - 4;
1142         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1143
1144         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1145         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1146                 name_len_target =
1147                     cifs_strtoUCS((wchar_t *) data_offset, toName, 530
1148                                   /* find define for this maxpathcomponent */
1149                                   , nls_codepage);
1150                 name_len_target++;      /* trailing null */
1151                 name_len_target *= 2;
1152         } else {                /* BB improve the check for buffer overruns BB */
1153                 name_len_target = strnlen(toName, 530);
1154                 name_len_target++;      /* trailing null */
1155                 strncpy(data_offset, toName, name_len_target);
1156         }
1157
1158         pSMB->DataCount = name_len_target;
1159         pSMB->MaxParameterCount = cpu_to_le16(2);
1160         /* BB find exact max on data count below from sess */
1161         pSMB->MaxDataCount = cpu_to_le16(1000);
1162         pSMB->SetupCount = 1;
1163         pSMB->Reserved3 = 0;
1164         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1165         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
1166         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1167         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1168         pSMB->TotalDataCount = pSMB->DataCount;
1169         pSMB->TotalParameterCount = pSMB->ParameterCount;
1170         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1171         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1172         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1173         pSMB->Reserved4 = 0;
1174         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1175         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1176         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1177                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1178         if (rc) {
1179                 cFYI(1,
1180                      ("Send error in SetPathInfo (create symlink) = %d",
1181                       rc));
1182         }
1183
1184         if (pSMB)
1185                 cifs_buf_release(pSMB);
1186
1187         if (rc == -EAGAIN)
1188                 goto createSymLinkRetry;
1189
1190         return rc;
1191 }
1192
1193 int
1194 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1195                        const char *fromName, const char *toName,
1196                        const struct nls_table *nls_codepage)
1197 {
1198         TRANSACTION2_SPI_REQ *pSMB = NULL;
1199         TRANSACTION2_SPI_RSP *pSMBr = NULL;
1200         char *data_offset;
1201         int name_len;
1202         int name_len_target;
1203         int rc = 0;
1204         int bytes_returned = 0;
1205
1206         cFYI(1, ("In Create Hard link Unix style"));
1207 createHardLinkRetry:
1208         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1209                       (void **) &pSMBr);
1210         if (rc)
1211                 return rc;
1212
1213         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1214                 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
1215                                          /* find define for this maxpathcomponent */
1216                                          , nls_codepage);
1217                 name_len++;     /* trailing null */
1218                 name_len *= 2;
1219
1220         } else {                /* BB improve the check for buffer overruns BB */
1221                 name_len = strnlen(toName, 530);
1222                 name_len++;     /* trailing null */
1223                 strncpy(pSMB->FileName, toName, name_len);
1224         }
1225         pSMB->ParameterCount = 6 + name_len;
1226         pSMB->MaxSetupCount = 0;
1227         pSMB->Reserved = 0;
1228         pSMB->Flags = 0;
1229         pSMB->Timeout = 0;
1230         pSMB->Reserved2 = 0;
1231         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1232                                      InformationLevel) - 4;
1233         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1234
1235         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1236         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1237                 name_len_target =
1238                     cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
1239                                   /* find define for this maxpathcomponent */
1240                                   , nls_codepage);
1241                 name_len_target++;      /* trailing null */
1242                 name_len_target *= 2;
1243         } else {                /* BB improve the check for buffer overruns BB */
1244                 name_len_target = strnlen(fromName, 530);
1245                 name_len_target++;      /* trailing null */
1246                 strncpy(data_offset, fromName, name_len_target);
1247         }
1248
1249         pSMB->DataCount = name_len_target;
1250         pSMB->MaxParameterCount = cpu_to_le16(2);
1251         /* BB find exact max on data count below from sess*/
1252         pSMB->MaxDataCount = cpu_to_le16(1000);
1253         pSMB->SetupCount = 1;
1254         pSMB->Reserved3 = 0;
1255         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1256         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
1257         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1258         pSMB->TotalParameterCount = pSMB->ParameterCount;
1259         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1260         pSMB->TotalDataCount = pSMB->DataCount;
1261         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1262         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1263         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1264         pSMB->Reserved4 = 0;
1265         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1266         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1267         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1268                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1269         if (rc) {
1270                 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1271         }
1272
1273         if (pSMB)
1274                 cifs_buf_release(pSMB);
1275         if (rc == -EAGAIN)
1276                 goto createHardLinkRetry;
1277
1278         return rc;
1279 }
1280
1281 int
1282 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1283                    const char *fromName, const char *toName,
1284                    const struct nls_table *nls_codepage)
1285 {
1286         int rc = 0;
1287         NT_RENAME_REQ *pSMB = NULL;
1288         RENAME_RSP *pSMBr = NULL;
1289         int bytes_returned;
1290         int name_len, name_len2;
1291
1292         cFYI(1, ("In CIFSCreateHardLink"));
1293 winCreateHardLinkRetry:
1294
1295         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1296                       (void **) &pSMBr);
1297         if (rc)
1298                 return rc;
1299
1300         pSMB->SearchAttributes =
1301             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1302                         ATTR_DIRECTORY);
1303         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1304         pSMB->ClusterCount = 0;
1305
1306         pSMB->BufferFormat = 0x04;
1307
1308         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1309                 name_len =
1310                     cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
1311                                   /* find define for this maxpathcomponent */
1312                                   , nls_codepage);
1313                 name_len++;     /* trailing null */
1314                 name_len *= 2;
1315                 pSMB->OldFileName[name_len] = 0;        /* pad */
1316                 pSMB->OldFileName[name_len + 1] = 0x04; 
1317                 name_len2 =
1318                     cifs_strtoUCS((wchar_t *) & pSMB->
1319                                   OldFileName[name_len + 2], toName, 530,
1320                                   nls_codepage);
1321                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
1322                 name_len2 *= 2; /* convert to bytes */
1323         } else {                /* BB improve the check for buffer overruns BB */
1324                 name_len = strnlen(fromName, 530);
1325                 name_len++;     /* trailing null */
1326                 strncpy(pSMB->OldFileName, fromName, name_len);
1327                 name_len2 = strnlen(toName, 530);
1328                 name_len2++;    /* trailing null */
1329                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
1330                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1331                 name_len2++;    /* trailing null */
1332                 name_len2++;    /* signature byte */
1333         }
1334
1335         pSMB->ByteCount = 1 /* string type byte */  + name_len + name_len2;
1336         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1337         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1338
1339         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1340                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1341         if (rc) {
1342                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1343         }
1344         if (pSMB)
1345                 cifs_buf_release(pSMB);
1346         if (rc == -EAGAIN)
1347                 goto winCreateHardLinkRetry;
1348
1349         return rc;
1350 }
1351
1352 int
1353 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1354                         const unsigned char *searchName,
1355                         char *symlinkinfo, const int buflen,
1356                         const struct nls_table *nls_codepage)
1357 {
1358 /* SMB_QUERY_FILE_UNIX_LINK */
1359         TRANSACTION2_QPI_REQ *pSMB = NULL;
1360         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1361         int rc = 0;
1362         int bytes_returned;
1363         int name_len;
1364
1365         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1366
1367 querySymLinkRetry:
1368         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1369                       (void **) &pSMBr);
1370         if (rc)
1371                 return rc;
1372
1373         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1374                 name_len =
1375                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1376                                   /* find define for this maxpathcomponent */
1377                                   , nls_codepage);
1378                 name_len++;     /* trailing null */
1379                 name_len *= 2;
1380         } else {                /* BB improve the check for buffer overruns BB */
1381                 name_len = strnlen(searchName, 530);
1382                 name_len++;     /* trailing null */
1383                 strncpy(pSMB->FileName, searchName, name_len);
1384         }
1385
1386         pSMB->TotalParameterCount =
1387             2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
1388         pSMB->TotalDataCount = 0;
1389         pSMB->MaxParameterCount = cpu_to_le16(2);
1390         /* BB find exact max data count below from sess structure BB */
1391         pSMB->MaxDataCount = cpu_to_le16(4000);
1392         pSMB->MaxSetupCount = 0;
1393         pSMB->Reserved = 0;
1394         pSMB->Flags = 0;
1395         pSMB->Timeout = 0;
1396         pSMB->Reserved2 = 0;
1397         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1398         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1399         pSMB->DataCount = 0;
1400         pSMB->DataOffset = 0;
1401         pSMB->SetupCount = 1;
1402         pSMB->Reserved3 = 0;
1403         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1404         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1405         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1406         pSMB->ParameterCount = pSMB->TotalParameterCount;
1407         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1408         pSMB->Reserved4 = 0;
1409         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1410         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1411
1412         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1413                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1414         if (rc) {
1415                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1416         } else {                /* decode response */
1417                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1418                 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1419                 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1420                 /* BB also check enough total bytes returned */
1421                         rc = -EIO;      /* bad smb */
1422                 else {
1423                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1424                                 name_len = UniStrnlen((wchar_t *) ((char *)
1425                                         &pSMBr->hdr.Protocol +pSMBr->DataOffset),
1426                                         min_t(const int, buflen,pSMBr->DataCount) / 2);
1427                                 cifs_strfromUCS_le(symlinkinfo,
1428                                         (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1429                                                 pSMBr->DataOffset),
1430                                         name_len, nls_codepage);
1431                         } else {
1432                                 strncpy(symlinkinfo,
1433                                         (char *) &pSMBr->hdr.Protocol + 
1434                                                 pSMBr->DataOffset,
1435                                         min_t(const int, buflen, pSMBr->DataCount));
1436                         }
1437                         symlinkinfo[buflen] = 0;
1438         /* just in case so calling code does not go off the end of buffer */
1439                 }
1440         }
1441         if (pSMB)
1442                 cifs_buf_release(pSMB);
1443         if (rc == -EAGAIN)
1444                 goto querySymLinkRetry;
1445         return rc;
1446 }
1447
1448
1449
1450 int
1451 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1452                         const unsigned char *searchName,
1453                         char *symlinkinfo, const int buflen,__u16 fid,
1454                         const struct nls_table *nls_codepage)
1455 {
1456         int rc = 0;
1457         int bytes_returned;
1458         int name_len;
1459         struct smb_com_transaction_ioctl_req * pSMB;
1460         struct smb_com_transaction_ioctl_rsp * pSMBr;
1461
1462         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1463         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1464                       (void **) &pSMBr);
1465         if (rc)
1466                 return rc;
1467
1468         pSMB->TotalParameterCount = 0 ;
1469         pSMB->TotalDataCount = 0;
1470         pSMB->MaxParameterCount = cpu_to_le32(2);
1471         /* BB find exact data count max from sess structure BB */
1472         pSMB->MaxDataCount = cpu_to_le32(4000);
1473         pSMB->MaxSetupCount = 4;
1474         pSMB->Reserved = 0;
1475         pSMB->ParameterOffset = 0;
1476         pSMB->DataCount = 0;
1477         pSMB->DataOffset = 0;
1478         pSMB->SetupCount = 4;
1479         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1480         pSMB->ParameterCount = pSMB->TotalParameterCount;
1481         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1482         pSMB->IsFsctl = 1; /* FSCTL */
1483         pSMB->IsRootFlag = 0;
1484         pSMB->Fid = fid; /* file handle always le */
1485         pSMB->ByteCount = 0;
1486
1487         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1488                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1489         if (rc) {
1490                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1491         } else {                /* decode response */
1492                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1493                 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1494                 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1495                 /* BB also check enough total bytes returned */
1496                         rc = -EIO;      /* bad smb */
1497                 else {
1498                         if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
1499                 /* could also validate reparse tag && better check name length */
1500                                 struct reparse_data * reparse_buf = (struct reparse_data *)
1501                                         ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
1502                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1503                                         name_len = UniStrnlen((wchar_t *)
1504                                                         (reparse_buf->LinkNamesBuf + 
1505                                                         reparse_buf->TargetNameOffset),
1506                                                         min(buflen/2, reparse_buf->TargetNameLen / 2)); 
1507                                         cifs_strfromUCS_le(symlinkinfo,
1508                                                 (wchar_t *) (reparse_buf->LinkNamesBuf + 
1509                                                 reparse_buf->TargetNameOffset),
1510                                                 name_len, nls_codepage);
1511                                 } else { /* ASCII names */
1512                                         strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + 
1513                                                 reparse_buf->TargetNameOffset, 
1514                                                 min_t(const int, buflen, reparse_buf->TargetNameLen));
1515                                 }
1516                         } else {
1517                                 rc = -EIO;
1518                                 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1519                         }
1520                         symlinkinfo[buflen] = 0; /* just in case so the caller
1521                                         does not go off the end of the buffer */
1522                         cFYI(1,("readlink result - %s ",symlinkinfo));
1523                 }
1524         }
1525         if (pSMB)
1526                 cifs_buf_release(pSMB);
1527
1528         /* Note: On -EAGAIN error only caller can retry on handle based calls
1529                 since file handle passed in no longer valid */
1530
1531         return rc;
1532 }
1533
1534 int
1535 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1536                  const unsigned char *searchName,
1537                  FILE_ALL_INFO * pFindData,
1538                  const struct nls_table *nls_codepage)
1539 {
1540 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1541         TRANSACTION2_QPI_REQ *pSMB = NULL;
1542         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1543         int rc = 0;
1544         int bytes_returned;
1545         int name_len;
1546
1547         cFYI(1, ("In QPathInfo path %s", searchName));
1548 QPathInfoRetry:
1549         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1550                       (void **) &pSMBr);
1551         if (rc)
1552                 return rc;
1553
1554         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1555                 name_len =
1556                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1557                                   /* find define for this maxpathcomponent */
1558                                   , nls_codepage);
1559                 name_len++;     /* trailing null */
1560                 name_len *= 2;
1561         } else {                /* BB improve the check for buffer overruns BB */
1562                 name_len = strnlen(searchName, 530);
1563                 name_len++;     /* trailing null */
1564                 strncpy(pSMB->FileName, searchName, name_len);
1565         }
1566
1567         pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
1568             name_len /* includes null */ ;
1569         pSMB->TotalDataCount = 0;
1570         pSMB->MaxParameterCount = cpu_to_le16(2);
1571         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1572         pSMB->MaxSetupCount = 0;
1573         pSMB->Reserved = 0;
1574         pSMB->Flags = 0;
1575         pSMB->Timeout = 0;
1576         pSMB->Reserved2 = 0;
1577         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1578         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1579         pSMB->DataCount = 0;
1580         pSMB->DataOffset = 0;
1581         pSMB->SetupCount = 1;
1582         pSMB->Reserved3 = 0;
1583         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1584         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1585         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1586         pSMB->ParameterCount = pSMB->TotalParameterCount;
1587         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1588         pSMB->Reserved4 = 0;
1589         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1590         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1591
1592         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1593                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1594         if (rc) {
1595                 cFYI(1, ("Send error in QPathInfo = %d", rc));
1596         } else {                /* decode response */
1597                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1598                 /* BB also check enough total bytes returned */
1599                 /* BB we need to improve the validity checking
1600                 of these trans2 responses */
1601                 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) 
1602                         rc = -EIO;      /* bad smb */
1603                 else if (pFindData){
1604                         memcpy((char *) pFindData,
1605                                (char *) &pSMBr->hdr.Protocol +
1606                                pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
1607                 } else
1608                     rc = -ENOMEM;
1609         }
1610         if (pSMB)
1611                 cifs_buf_release(pSMB);
1612         if (rc == -EAGAIN)
1613                 goto QPathInfoRetry;
1614
1615         return rc;
1616 }
1617
1618 int
1619 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1620                      const unsigned char *searchName,
1621                      FILE_UNIX_BASIC_INFO * pFindData,
1622                      const struct nls_table *nls_codepage)
1623 {
1624 /* SMB_QUERY_FILE_UNIX_BASIC */
1625         TRANSACTION2_QPI_REQ *pSMB = NULL;
1626         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1627         int rc = 0;
1628         int bytes_returned = 0;
1629         int name_len;
1630
1631         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1632 UnixQPathInfoRetry:
1633         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1634                       (void **) &pSMBr);
1635         if (rc)
1636                 return rc;
1637
1638         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1639                 name_len =
1640                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1641                                   /* find define for this maxpathcomponent */
1642                                   , nls_codepage);
1643                 name_len++;     /* trailing null */
1644                 name_len *= 2;
1645         } else {                /* BB improve the check for buffer overruns BB */
1646                 name_len = strnlen(searchName, 530);
1647                 name_len++;     /* trailing null */
1648                 strncpy(pSMB->FileName, searchName, name_len);
1649         }
1650
1651         pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
1652             name_len /* includes null */ ;
1653         pSMB->TotalDataCount = 0;
1654         pSMB->MaxParameterCount = cpu_to_le16(2);
1655         /* BB find exact max SMB PDU from sess structure BB */
1656         pSMB->MaxDataCount = cpu_to_le16(4000); 
1657         pSMB->MaxSetupCount = 0;
1658         pSMB->Reserved = 0;
1659         pSMB->Flags = 0;
1660         pSMB->Timeout = 0;
1661         pSMB->Reserved2 = 0;
1662         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1663         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1664         pSMB->DataCount = 0;
1665         pSMB->DataOffset = 0;
1666         pSMB->SetupCount = 1;
1667         pSMB->Reserved3 = 0;
1668         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1669         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1670         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1671         pSMB->ParameterCount = pSMB->TotalParameterCount;
1672         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1673         pSMB->Reserved4 = 0;
1674         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1675         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1676
1677         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1678                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1679         if (rc) {
1680                 cFYI(1, ("Send error in QPathInfo = %d", rc));
1681         } else {                /* decode response */
1682                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1683                 /* BB also check if enough total bytes returned */
1684                 if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) || 
1685                         (pSMBr->DataOffset > 512) || 
1686                         (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
1687                         cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
1688                                         (int)pSMBr->DataOffset,bytes_returned));
1689                         rc = -EIO;      /* bad smb */
1690                 } else {
1691                         memcpy((char *) pFindData,
1692                                (char *) &pSMBr->hdr.Protocol +
1693                                pSMBr->DataOffset,
1694                                sizeof (FILE_UNIX_BASIC_INFO));
1695                 }
1696         }
1697         if (pSMB)
1698                 cifs_buf_release(pSMB);
1699         if (rc == -EAGAIN)
1700                 goto UnixQPathInfoRetry;
1701
1702         return rc;
1703 }
1704
1705 int
1706 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1707                const char *searchName, FILE_ALL_INFO * findData,
1708                const struct nls_table *nls_codepage)
1709 {
1710 /* level 257 SMB_ */
1711         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1712         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1713         int rc = 0;
1714         int bytes_returned;
1715         int name_len;
1716
1717         cFYI(1, ("In FindUnique"));
1718 findUniqueRetry:
1719         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1720                       (void **) &pSMBr);
1721         if (rc)
1722                 return rc;
1723
1724         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1725                 name_len =
1726                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1727                                   /* find define for this maxpathcomponent */
1728                                   , nls_codepage);
1729                 name_len++;     /* trailing null */
1730                 name_len *= 2;
1731         } else {                /* BB improve the check for buffer overruns BB */
1732                 name_len = strnlen(searchName, 530);
1733                 name_len++;     /* trailing null */
1734                 strncpy(pSMB->FileName, searchName, name_len);
1735         }
1736
1737         pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1738         pSMB->TotalDataCount = 0;       /* no EAs */
1739         pSMB->MaxParameterCount = cpu_to_le16(2);
1740         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1741         pSMB->MaxSetupCount = 0;
1742         pSMB->Reserved = 0;
1743         pSMB->Flags = 0;
1744         pSMB->Timeout = 0;
1745         pSMB->Reserved2 = 0;
1746         pSMB->ParameterOffset = cpu_to_le16(
1747         offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1748         pSMB->DataCount = 0;
1749         pSMB->DataOffset = 0;
1750         pSMB->SetupCount = 1;   /* one byte, no need to le convert */
1751         pSMB->Reserved3 = 0;
1752         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1753         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1754         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
1755         pSMB->ParameterCount = pSMB->TotalParameterCount;
1756         pSMB->SearchAttributes =
1757             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1758                         ATTR_DIRECTORY);
1759         pSMB->SearchCount = cpu_to_le16(16);    /* BB increase */
1760         pSMB->SearchFlags = cpu_to_le16(1);
1761         pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1762         pSMB->SearchStorageType = 0;    /* BB what should we set this to? BB */
1763         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1764         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1765
1766         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1767                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1768
1769         if (rc) {
1770                 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1771         } else {                /* decode response */
1772
1773                 /* BB fill in */
1774         }
1775         if (pSMB)
1776                 cifs_buf_release(pSMB);
1777         if (rc == -EAGAIN)
1778                 goto findUniqueRetry;
1779
1780         return rc;
1781 }
1782
1783 int
1784 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1785               const char *searchName, FILE_DIRECTORY_INFO * findData,
1786               T2_FFIRST_RSP_PARMS * findParms,
1787               const struct nls_table *nls_codepage, int *pUnicodeFlag,
1788               int *pUnixFlag)
1789 {
1790 /* level 257 SMB_ */
1791         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1792         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1793         char *response_data;
1794         int rc = 0;
1795         int bytes_returned;
1796         int name_len;
1797
1798         cFYI(1, ("In FindFirst"));
1799 findFirstRetry:
1800         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1801                       (void **) &pSMBr);
1802         if (rc)
1803                 return rc;
1804
1805         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1806                 name_len =
1807                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1808                                   /* find define for this maxpathcomponent */
1809                                   , nls_codepage);
1810                 name_len++;     /* trailing null */
1811                 name_len *= 2;
1812         } else {                /* BB improve the check for buffer overruns BB */
1813                 name_len = strnlen(searchName, 530);
1814                 name_len++;     /* trailing null */
1815                 strncpy(pSMB->FileName, searchName, name_len);
1816         }
1817
1818         pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1819         pSMB->TotalDataCount = 0;       /* no EAs */
1820         pSMB->MaxParameterCount = cpu_to_le16(10);
1821         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1822                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1823         pSMB->MaxSetupCount = 0;
1824         pSMB->Reserved = 0;
1825         pSMB->Flags = 0;
1826         pSMB->Timeout = 0;
1827         pSMB->Reserved2 = 0;
1828         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1829         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1830         pSMB->ParameterCount = pSMB->TotalParameterCount;
1831         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
1832         smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1833         pSMB->DataCount = 0;
1834         pSMB->DataOffset = 0;
1835         pSMB->SetupCount = 1;   /* one byte no need to make endian neutral */
1836         pSMB->Reserved3 = 0;
1837         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1838         pSMB->SearchAttributes =
1839             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1840                         ATTR_DIRECTORY);
1841         pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));       /* should this be shrunk even more ? */
1842         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1843
1844         /* test for Unix extensions */
1845         if (tcon->ses->capabilities & CAP_UNIX) {
1846                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1847                 *pUnixFlag = TRUE;
1848         } else {
1849                 pSMB->InformationLevel =
1850                     cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1851                 *pUnixFlag = FALSE;
1852         }
1853         pSMB->SearchStorageType = 0;    /* BB what should we set this to? It is not clear if it matters BB */
1854         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1855         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1856
1857         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1858                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1859
1860         if (rc) {               /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1861                 cFYI(1, ("Error in FindFirst = %d", rc));
1862         } else {                /* decode response */
1863                 /* BB add safety checks for these memcpys */
1864                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1865                         *pUnicodeFlag = TRUE;
1866                 else
1867                         *pUnicodeFlag = FALSE;
1868                 memcpy(findParms,
1869                        (char *) &pSMBr->hdr.Protocol +
1870                        le16_to_cpu(pSMBr->ParameterOffset),
1871                        sizeof (T2_FFIRST_RSP_PARMS));
1872                 /* search handle can stay LE and EAoffset not needed so not converted */
1873                 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1874                 findParms->LastNameOffset =
1875                     le16_to_cpu(findParms->LastNameOffset);
1876                 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1877                 response_data =
1878                     (char *) &pSMBr->hdr.Protocol +
1879                     le16_to_cpu(pSMBr->DataOffset);
1880                 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1881         }
1882         if (pSMB)
1883                 cifs_buf_release(pSMB);
1884
1885         if (rc == -EAGAIN)
1886                 goto findFirstRetry;
1887
1888         return rc;
1889 }
1890
1891 int
1892 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1893                 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1894                 const __u16 searchHandle, char * resume_file_name, int name_len,
1895                 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1896 {
1897 /* level 257 SMB_ */
1898         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1899         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1900         char *response_data;
1901         int rc = 0;
1902         int bytes_returned;
1903
1904         cFYI(1, ("In FindNext"));
1905
1906         if(resume_file_name == NULL) {
1907                 return -EIO;
1908         }
1909         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1910                       (void **) &pSMBr);
1911         if (rc)
1912                 return rc;
1913
1914         pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
1915         pSMB->TotalDataCount = 0;       /* no EAs */
1916         pSMB->MaxParameterCount = cpu_to_le16(8);
1917         pSMB->MaxDataCount =
1918             cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1919         pSMB->MaxSetupCount = 0;
1920         pSMB->Reserved = 0;
1921         pSMB->Flags = 0;
1922         pSMB->Timeout = 0;
1923         pSMB->Reserved2 = 0;
1924         pSMB->ParameterOffset =  cpu_to_le16(offsetof(
1925         struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1926         pSMB->DataCount = 0;
1927         pSMB->DataOffset = 0;
1928         pSMB->SetupCount = 1;
1929         pSMB->Reserved3 = 0;
1930         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1931         pSMB->SearchHandle = searchHandle;      /* always kept as le */
1932         findParms->SearchCount = 0;     /* set to zero in case of error */
1933         pSMB->SearchCount =
1934             cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1935         /* test for Unix extensions */
1936         if (tcon->ses->capabilities & CAP_UNIX) {
1937                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1938                 *pUnixFlag = TRUE;
1939         } else {
1940                 pSMB->InformationLevel =
1941                     cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1942                 *pUnixFlag = FALSE;
1943         }
1944         pSMB->ResumeKey = resume_key;
1945         pSMB->SearchFlags =
1946             cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1947         /* BB add check to make sure we do not cross end of smb */
1948         if(name_len < CIFS_MAX_MSGSIZE) {
1949                 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1950                 pSMB->ByteCount += name_len;
1951         }
1952         pSMB->TotalParameterCount += name_len;
1953         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1954         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1955         pSMB->ParameterCount = pSMB->TotalParameterCount;
1956         /* BB improve error handling here */
1957         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1958         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1959
1960         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1961                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1962
1963         if (rc) {
1964                 if (rc == -EBADF)
1965                         rc = 0; /* search probably was closed at end of search above */
1966                 else
1967                         cFYI(1, ("FindNext returned = %d", rc));
1968         } else {                /* decode response */
1969                 /* BB add safety checks for these memcpys */
1970                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1971                         *pUnicodeFlag = TRUE;
1972                 else
1973                         *pUnicodeFlag = FALSE;
1974                 memcpy(findParms,
1975                        (char *) &pSMBr->hdr.Protocol +
1976                        le16_to_cpu(pSMBr->ParameterOffset),
1977                        sizeof (T2_FNEXT_RSP_PARMS));
1978                 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1979                 findParms->LastNameOffset =
1980                     le16_to_cpu(findParms->LastNameOffset);
1981                 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1982                 response_data =
1983                     (char *) &pSMBr->hdr.Protocol +
1984                     le16_to_cpu(pSMBr->DataOffset);
1985                 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1986         }
1987         if (pSMB)
1988                 cifs_buf_release(pSMB);
1989
1990         /* Note: On -EAGAIN error only caller can retry on handle based calls
1991                 since file handle passed in no longer valid */
1992
1993         return rc;
1994 }
1995
1996 int
1997 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
1998 {
1999         int rc = 0;
2000         FINDCLOSE_REQ *pSMB = NULL;
2001         CLOSE_RSP *pSMBr = NULL;
2002         int bytes_returned;
2003
2004         cFYI(1, ("In CIFSSMBFindClose"));
2005         rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
2006                       (void **) &pSMBr);
2007         /* no sense returning error if session restarted
2008                 file handle has been closed */
2009         if(rc == -EAGAIN)
2010                 return 0;
2011         if (rc)
2012                 return rc;
2013
2014         pSMB->FileID = searchHandle;
2015         pSMB->ByteCount = 0;
2016         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2017                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2018         if (rc) {
2019                 cERROR(1, ("Send error in FindClose = %d", rc));
2020         }
2021         if (pSMB)
2022                 cifs_buf_release(pSMB);
2023
2024         /* Since session is dead, search handle closed on server already */
2025         if (rc == -EAGAIN)
2026                 rc = 0;
2027
2028         return rc;
2029 }
2030
2031 int
2032 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2033                 const unsigned char *searchName,
2034                 unsigned char **targetUNCs,
2035                 unsigned int *number_of_UNC_in_array,
2036                 const struct nls_table *nls_codepage)
2037 {
2038 /* TRANS2_GET_DFS_REFERRAL */
2039         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2040         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2041         struct dfs_referral_level_3 * referrals = NULL;
2042         int rc = 0;
2043         int bytes_returned;
2044         int name_len;
2045         unsigned int i;
2046         char * temp;
2047         *number_of_UNC_in_array = 0;
2048         *targetUNCs = NULL;
2049
2050         cFYI(1, ("In GetDFSRefer the path %s", searchName));
2051         if (ses == NULL)
2052                 return -ENODEV;
2053 getDFSRetry:
2054         rc = smb_init(SMB_COM_TRANSACTION2, 15, 0, (void **) &pSMB,
2055                       (void **) &pSMBr);
2056         if (rc)
2057                 return rc;
2058
2059         pSMB->hdr.Tid = ses->ipc_tid;
2060         pSMB->hdr.Uid = ses->Suid;
2061         if (ses->capabilities & CAP_STATUS32) {
2062                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2063         }
2064         if (ses->capabilities & CAP_DFS) {
2065                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2066         }
2067
2068         if (ses->capabilities & CAP_UNICODE) {
2069                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2070                 name_len =
2071                     cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2072                                   searchName, 530
2073                                   /* find define for this maxpathcomponent */
2074                                   , nls_codepage);
2075                 name_len++;     /* trailing null */
2076                 name_len *= 2;
2077         } else {                /* BB improve the check for buffer overruns BB */
2078                 name_len = strnlen(searchName, 530);
2079                 name_len++;     /* trailing null */
2080                 strncpy(pSMB->RequestFileName, searchName, name_len);
2081         }
2082
2083         pSMB->ParameterCount = 2 /* level */  + name_len /*includes null */ ;
2084         pSMB->TotalDataCount = 0;
2085         pSMB->DataCount = 0;
2086         pSMB->DataOffset = 0;
2087         pSMB->MaxParameterCount = 0;
2088         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2089         pSMB->MaxSetupCount = 0;
2090         pSMB->Reserved = 0;
2091         pSMB->Flags = 0;
2092         pSMB->Timeout = 0;
2093         pSMB->Reserved2 = 0;
2094         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2095         struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2096         pSMB->SetupCount = 1;
2097         pSMB->Reserved3 = 0;
2098         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2099         pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
2100         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2101         pSMB->TotalParameterCount = pSMB->ParameterCount;
2102         pSMB->MaxReferralLevel = cpu_to_le16(3);
2103         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2104         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2105
2106         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2107                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2108         if (rc) {
2109                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2110         } else {                /* decode response */
2111 /* BB Add logic to parse referrals here */
2112                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2113                 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
2114                 cFYI(1,
2115                      ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
2116                       pSMBr->ByteCount, pSMBr->DataOffset));
2117                 if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512))       /* BB also check enough total bytes returned */
2118                         rc = -EIO;      /* bad smb */
2119                 else {
2120                         referrals = 
2121                             (struct dfs_referral_level_3 *) 
2122                                         (8 /* sizeof start of data block */ +
2123                                         pSMBr->DataOffset +
2124                                         (char *) &pSMBr->hdr.Protocol); 
2125                         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",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
2126                         /* BB This field is actually two bytes in from start of
2127                            data block so we could do safety check that DataBlock
2128                            begins at address of pSMBr->NumberOfReferrals */
2129                         *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2130
2131                         /* BB Fix below so can return more than one referral */
2132                         if(*number_of_UNC_in_array > 1)
2133                                 *number_of_UNC_in_array = 1;
2134
2135                         /* get the length of the strings describing refs */
2136                         name_len = 0;
2137                         for(i=0;i<*number_of_UNC_in_array;i++) {
2138                                 /* make sure that DfsPathOffset not past end */
2139                                 referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
2140                                 if(referrals->DfsPathOffset > pSMBr->DataCount) {
2141                                         /* if invalid referral, stop here and do 
2142                                         not try to copy any more */
2143                                         *number_of_UNC_in_array = i;
2144                                         break;
2145                                 } 
2146                                 temp = ((char *)referrals) + referrals->DfsPathOffset;
2147
2148                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2149                                         name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
2150                                 } else {
2151                                         name_len += strnlen(temp,pSMBr->DataCount);
2152                                 }
2153                                 referrals++;
2154                                 /* BB add check that referral pointer does not fall off end PDU */
2155                                 
2156                         }
2157                         /* BB add check for name_len bigger than bcc */
2158                         *targetUNCs = 
2159                                 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2160                         /* copy the ref strings */
2161                         referrals =  
2162                             (struct dfs_referral_level_3 *) 
2163                                         (8 /* sizeof data hdr */ +
2164                                         pSMBr->DataOffset + 
2165                                         (char *) &pSMBr->hdr.Protocol);
2166
2167                         for(i=0;i<*number_of_UNC_in_array;i++) {
2168                                 temp = ((char *)referrals) + referrals->DfsPathOffset;
2169                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2170                                         cifs_strfromUCS_le(*targetUNCs,
2171                                                 (wchar_t *) temp, name_len, nls_codepage);
2172                                 } else {
2173                                         strncpy(*targetUNCs,temp,name_len);
2174                                 }
2175                                 /*  BB update target_uncs pointers */
2176                                 referrals++;
2177                         }
2178                         temp = *targetUNCs;
2179                         temp[name_len] = 0;
2180                 }
2181
2182         }
2183         if (pSMB)
2184                 cifs_buf_release(pSMB);
2185
2186         if (rc == -EAGAIN)
2187                 goto getDFSRetry;
2188
2189         return rc;
2190 }
2191
2192 int
2193 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2194                struct kstatfs *FSData, const struct nls_table *nls_codepage)
2195 {
2196 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2197         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2198         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2199         FILE_SYSTEM_INFO *response_data;
2200         int rc = 0;
2201         int bytes_returned = 0;
2202
2203         cFYI(1, ("In QFSInfo"));
2204 QFSInfoRetry:
2205         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2206                       (void **) &pSMBr);
2207         if (rc)
2208                 return rc;
2209
2210         pSMB->TotalParameterCount = 2;  /* level */
2211         pSMB->TotalDataCount = 0;
2212         pSMB->MaxParameterCount = cpu_to_le16(2);
2213         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2214         pSMB->MaxSetupCount = 0;
2215         pSMB->Reserved = 0;
2216         pSMB->Flags = 0;
2217         pSMB->Timeout = 0;
2218         pSMB->Reserved2 = 0;
2219         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2220         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2221         pSMB->ParameterCount = pSMB->TotalParameterCount;
2222         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2223         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2224         pSMB->DataCount = 0;
2225         pSMB->DataOffset = 0;
2226         pSMB->SetupCount = 1;
2227         pSMB->Reserved3 = 0;
2228         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2229         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2230         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2231         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2232
2233         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2234                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2235         if (rc) {
2236                 cERROR(1, ("Send error in QFSInfo = %d", rc));
2237         } else {                /* decode response */
2238                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2239                 cFYI(1,
2240                      ("Decoding qfsinfo response.  BCC: %d  Offset %d",
2241                       pSMBr->ByteCount, pSMBr->DataOffset));
2242                 if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512))       /* BB also check enough total bytes returned */
2243                         rc = -EIO;      /* bad smb */
2244                 else {
2245                         response_data =
2246                             (FILE_SYSTEM_INFO
2247                              *) (((char *) &pSMBr->hdr.Protocol) +
2248                                  pSMBr->DataOffset);
2249                         FSData->f_bsize =
2250                             le32_to_cpu(response_data->BytesPerSector) *
2251                             le32_to_cpu(response_data->
2252                                         SectorsPerAllocationUnit);
2253                         FSData->f_blocks =
2254                             le64_to_cpu(response_data->TotalAllocationUnits);
2255                         FSData->f_bfree = FSData->f_bavail =
2256                             le64_to_cpu(response_data->FreeAllocationUnits);
2257                         cFYI(1,
2258                              ("Blocks: %lld  Free: %lld Block size %ld",
2259                               (unsigned long long)FSData->f_blocks,
2260                               (unsigned long long)FSData->f_bfree,
2261                               FSData->f_bsize));
2262                 }
2263         }
2264         if (pSMB)
2265                 cifs_buf_release(pSMB);
2266
2267         if (rc == -EAGAIN)
2268                 goto QFSInfoRetry;
2269
2270         return rc;
2271 }
2272
2273 int
2274 CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
2275                         const struct nls_table *nls_codepage)
2276 {
2277 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
2278         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2279         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2280         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
2281         int rc = 0;
2282         int bytes_returned = 0;
2283
2284         cFYI(1, ("In QFSAttributeInfo"));
2285 QFSAttributeRetry:
2286         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2287                       (void **) &pSMBr);
2288         if (rc)
2289                 return rc;
2290
2291         pSMB->TotalParameterCount = 2;  /* level */
2292         pSMB->TotalDataCount = 0;
2293         pSMB->MaxParameterCount = cpu_to_le16(2);
2294         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2295         pSMB->MaxSetupCount = 0;
2296         pSMB->Reserved = 0;
2297         pSMB->Flags = 0;
2298         pSMB->Timeout = 0;
2299         pSMB->Reserved2 = 0;
2300         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2301         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2302         pSMB->ParameterCount = pSMB->TotalParameterCount;
2303         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2304         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2305         pSMB->DataCount = 0;
2306         pSMB->DataOffset = 0;
2307         pSMB->SetupCount = 1;
2308         pSMB->Reserved3 = 0;
2309         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2310         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
2311         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2312         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2313
2314         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2315                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2316         if (rc) {
2317                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
2318         } else {                /* decode response */
2319                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2320                 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {     /* BB also check enough bytes returned */
2321                         rc = -EIO;      /* bad smb */
2322                 } else {
2323                         response_data =
2324                             (FILE_SYSTEM_ATTRIBUTE_INFO
2325                              *) (((char *) &pSMBr->hdr.Protocol) +
2326                                  pSMBr->DataOffset);
2327                         response_data->Attributes = le32_to_cpu(response_data->Attributes);
2328                         response_data->MaxPathNameComponentLength = 
2329                                 le32_to_cpu(response_data->MaxPathNameComponentLength);
2330                         response_data->FileSystemNameLen = 
2331                                 le32_to_cpu(response_data->FileSystemNameLen);
2332                         memcpy(&tcon->fsAttrInfo, response_data,
2333                                sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
2334                 }
2335         }
2336         if (pSMB)
2337                 cifs_buf_release(pSMB);
2338
2339         if (rc == -EAGAIN)
2340                 goto QFSAttributeRetry;
2341
2342         return rc;
2343 }
2344
2345 int
2346 CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
2347                      const struct nls_table *nls_codepage)
2348 {
2349 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
2350         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2351         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2352         FILE_SYSTEM_DEVICE_INFO *response_data;
2353         int rc = 0;
2354         int bytes_returned = 0;
2355
2356         cFYI(1, ("In QFSDeviceInfo"));
2357 QFSDeviceRetry:
2358         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2359                       (void **) &pSMBr);
2360         if (rc)
2361                 return rc;
2362
2363         pSMB->TotalParameterCount = 2;  /* level */
2364         pSMB->TotalDataCount = 0;
2365         pSMB->MaxParameterCount = cpu_to_le16(2);
2366         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2367         pSMB->MaxSetupCount = 0;
2368         pSMB->Reserved = 0;
2369         pSMB->Flags = 0;
2370         pSMB->Timeout = 0;
2371         pSMB->Reserved2 = 0;
2372         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2373         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2374         pSMB->ParameterCount = pSMB->TotalParameterCount;
2375         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2376         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2377
2378         pSMB->DataCount = 0;
2379         pSMB->DataOffset = 0;
2380         pSMB->SetupCount = 1;
2381         pSMB->Reserved3 = 0;
2382         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2383         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
2384         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2385         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2386
2387         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2388                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2389         if (rc) {
2390                 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
2391         } else {                /* decode response */
2392                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2393                 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
2394                  || (pSMBr->DataOffset > 512))
2395                         rc = -EIO;      /* bad smb */
2396                 else {
2397                         response_data =
2398                             (FILE_SYSTEM_DEVICE_INFO
2399                              *) (((char *) &pSMBr->hdr.Protocol) +
2400                                  pSMBr->DataOffset);
2401                         response_data->DeviceType = 
2402                                 le32_to_cpu(response_data->DeviceType);
2403                         response_data->DeviceCharacteristics = 
2404                                 le32_to_cpu(response_data->DeviceCharacteristics);
2405                         memcpy(&tcon->fsDevInfo, response_data,
2406                                sizeof (FILE_SYSTEM_DEVICE_INFO));
2407                 }
2408         }
2409         if (pSMB)
2410                 cifs_buf_release(pSMB);
2411
2412         if (rc == -EAGAIN)
2413                 goto QFSDeviceRetry;
2414
2415         return rc;
2416 }
2417
2418 int
2419 CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
2420                    const struct nls_table *nls_codepage)
2421 {
2422 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
2423         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2424         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2425         FILE_SYSTEM_UNIX_INFO *response_data;
2426         int rc = 0;
2427         int bytes_returned = 0;
2428
2429         cFYI(1, ("In QFSUnixInfo"));
2430 QFSUnixRetry:
2431         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2432                       (void **) &pSMBr);
2433         if (rc)
2434                 return rc;
2435
2436         pSMB->ParameterCount = 2;       /* level */
2437         pSMB->TotalDataCount = 0;
2438         pSMB->DataCount = 0;
2439         pSMB->DataOffset = 0;
2440         pSMB->MaxParameterCount = cpu_to_le16(2);
2441         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
2442         pSMB->MaxSetupCount = 0;
2443         pSMB->Reserved = 0;
2444         pSMB->Flags = 0;
2445         pSMB->Timeout = 0;
2446         pSMB->Reserved2 = 0;
2447         pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
2448         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2449         pSMB->TotalParameterCount = pSMB->ParameterCount;
2450         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
2451         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2452         pSMB->SetupCount = 1;
2453         pSMB->Reserved3 = 0;
2454         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2455         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2456         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2457         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2458
2459         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2460                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2461         if (rc) {
2462                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2463         } else {                /* decode response */
2464                 pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
2465                 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
2466                         rc = -EIO;      /* bad smb */
2467                 } else {
2468                         response_data =
2469                             (FILE_SYSTEM_UNIX_INFO
2470                              *) (((char *) &pSMBr->hdr.Protocol) +
2471                                  pSMBr->DataOffset);
2472                         response_data->MajorVersionNumber =
2473                                 le16_to_cpu(response_data->MajorVersionNumber);
2474                         response_data->MinorVersionNumber =
2475                                 le16_to_cpu(response_data->MinorVersionNumber);
2476                         response_data->Capability =
2477                                 le64_to_cpu(response_data->Capability);
2478                         memcpy(&tcon->fsUnixInfo, response_data,
2479                                sizeof (FILE_SYSTEM_UNIX_INFO));
2480                 }
2481         }
2482         if (pSMB)
2483                 cifs_buf_release(pSMB);
2484
2485         if (rc == -EAGAIN)
2486                 goto QFSUnixRetry;
2487
2488
2489         return rc;
2490 }
2491
2492 /* We can not use write of zero bytes trick to 
2493    set file size due to need for large file support.  Also note that 
2494    this SetPathInfo is preferred to SetFileInfo based method in next 
2495    routine which is only needed to work around a sharing violation bug
2496    in Samba which this routine can run into */
2497
2498 int
2499 CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
2500               __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2501 {
2502         struct smb_com_transaction2_spi_req *pSMB = NULL;
2503         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2504         struct file_end_of_file_info *parm_data;
2505         int name_len;
2506         int rc = 0;
2507         int bytes_returned = 0;
2508
2509         cFYI(1, ("In SetEOF"));
2510 SetEOFRetry:
2511         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2512                       (void **) &pSMBr);
2513         if (rc)
2514                 return rc;
2515
2516         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2517                 name_len =
2518                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2519                                   /* find define for this maxpathcomponent */
2520                                   , nls_codepage);
2521                 name_len++;     /* trailing null */
2522                 name_len *= 2;
2523         } else {                /* BB improve the check for buffer overruns BB */
2524                 name_len = strnlen(fileName, 530);
2525                 name_len++;     /* trailing null */
2526                 strncpy(pSMB->FileName, fileName, name_len);
2527         }
2528         pSMB->ParameterCount = 6 + name_len;
2529         pSMB->DataCount = sizeof (struct file_end_of_file_info);
2530         pSMB->MaxParameterCount = cpu_to_le16(2);
2531         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2532         pSMB->MaxSetupCount = 0;
2533         pSMB->Reserved = 0;
2534         pSMB->Flags = 0;
2535         pSMB->Timeout = 0;
2536         pSMB->Reserved2 = 0;
2537         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2538                                      InformationLevel) - 4;
2539         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2540         if(SetAllocation) {
2541                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2542                     pSMB->InformationLevel =
2543                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2544                 else
2545                     pSMB->InformationLevel =
2546                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2547         } else /* Set File Size */  {    
2548             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2549                     pSMB->InformationLevel =
2550                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2551             else
2552                     pSMB->InformationLevel =
2553                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2554         }
2555
2556         parm_data =
2557             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2558                                        pSMB->DataOffset);
2559         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2560         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2561         pSMB->SetupCount = 1;
2562         pSMB->Reserved3 = 0;
2563         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2564         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2565         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2566         pSMB->TotalDataCount = pSMB->DataCount;
2567         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2568         pSMB->TotalParameterCount = pSMB->ParameterCount;
2569         pSMB->Reserved4 = 0;
2570         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2571         parm_data->FileSize = cpu_to_le64(size);
2572         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2573         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2574                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2575         if (rc) {
2576                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2577         }
2578
2579         if (pSMB)
2580                 cifs_buf_release(pSMB);
2581
2582         if (rc == -EAGAIN)
2583                 goto SetEOFRetry;
2584
2585         return rc;
2586 }
2587
2588 int
2589 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, 
2590                    __u16 fid, __u32 pid_of_opener, int SetAllocation)
2591 {
2592         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2593         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2594         char *data_offset;
2595         struct file_end_of_file_info *parm_data;
2596         int rc = 0;
2597         int bytes_returned = 0;
2598         __u32 tmp;
2599
2600         cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
2601                         (long long)size));
2602         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2603                       (void **) &pSMBr);
2604         if (rc)
2605                 return rc;
2606
2607         tmp = cpu_to_le32(pid_of_opener);  /* override pid of current process
2608                                          so network fid will be valid */
2609         pSMB->hdr.Pid = tmp & 0xFFFF;
2610         tmp >>= 16;
2611         pSMB->hdr.PidHigh = tmp & 0xFFFF;
2612     
2613         pSMB->ParameterCount = 6;
2614         pSMB->MaxSetupCount = 0;
2615         pSMB->Reserved = 0;
2616         pSMB->Flags = 0;
2617         pSMB->Timeout = 0;
2618         pSMB->Reserved2 = 0;
2619         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
2620                                      Fid) - 4;
2621         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2622
2623         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;        
2624
2625         pSMB->DataCount = sizeof(struct file_end_of_file_info);
2626         pSMB->MaxParameterCount = cpu_to_le16(2);
2627         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2628         pSMB->SetupCount = 1;
2629         pSMB->Reserved3 = 0;
2630         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2631         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2632         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2633         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2634         pSMB->TotalDataCount = pSMB->DataCount;
2635         pSMB->TotalParameterCount = pSMB->ParameterCount;
2636         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2637         parm_data =
2638                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2639                         pSMB->DataOffset);
2640         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
2641         parm_data->FileSize = cpu_to_le64(size);
2642         pSMB->Fid = fid;
2643         if(SetAllocation) {
2644                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2645                         pSMB->InformationLevel =
2646                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2647                 else
2648                         pSMB->InformationLevel =
2649                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2650         } else /* Set File Size */  {    
2651             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2652                     pSMB->InformationLevel =
2653                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2654             else
2655                     pSMB->InformationLevel =
2656                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2657         }
2658         pSMB->Reserved4 = 0;
2659         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2660         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2661         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2662                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2663         if (rc) {
2664                 cFYI(1,
2665                      ("Send error in SetFileInfo (SetFileSize) = %d",
2666                       rc));
2667         }
2668
2669         if (pSMB)
2670                 cifs_buf_release(pSMB);
2671
2672         /* Note: On -EAGAIN error only caller can retry on handle based calls 
2673                 since file handle passed in no longer valid */
2674
2675         return rc;
2676 }
2677
2678 int
2679 CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
2680                 FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
2681 {
2682         TRANSACTION2_SPI_REQ *pSMB = NULL;
2683         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2684         int name_len;
2685         int rc = 0;
2686         int bytes_returned = 0;
2687         char *data_offset;
2688
2689         cFYI(1, ("In SetTimes"));
2690
2691 SetTimesRetry:
2692         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2693                       (void **) &pSMBr);
2694         if (rc)
2695                 return rc;
2696
2697         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2698                 name_len =
2699                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2700                                   /* find define for this maxpathcomponent */
2701                                   , nls_codepage);
2702                 name_len++;     /* trailing null */
2703                 name_len *= 2;
2704         } else {                /* BB improve the check for buffer overruns BB */
2705                 name_len = strnlen(fileName, 530);
2706                 name_len++;     /* trailing null */
2707                 strncpy(pSMB->FileName, fileName, name_len);
2708         }
2709
2710         pSMB->ParameterCount = 6 + name_len;
2711         pSMB->DataCount = sizeof (FILE_BASIC_INFO);
2712         pSMB->MaxParameterCount = cpu_to_le16(2);
2713         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2714         pSMB->MaxSetupCount = 0;
2715         pSMB->Reserved = 0;
2716         pSMB->Flags = 0;
2717         pSMB->Timeout = 0;
2718         pSMB->Reserved2 = 0;
2719         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2720                                      InformationLevel) - 4;
2721         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2722         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2723         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2724         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2725         pSMB->SetupCount = 1;
2726         pSMB->Reserved3 = 0;
2727         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2728         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2729
2730         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2731         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2732         pSMB->TotalDataCount = pSMB->DataCount;
2733         pSMB->TotalParameterCount = pSMB->ParameterCount;
2734         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2735                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2736         else
2737                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2738         pSMB->Reserved4 = 0;
2739         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2740         memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2741         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2742         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2743                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2744         if (rc) {
2745                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2746         }
2747
2748         if (pSMB)
2749                 cifs_buf_release(pSMB);
2750
2751         if (rc == -EAGAIN)
2752                 goto SetTimesRetry;
2753
2754         return rc;
2755 }
2756
2757 int
2758 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2759                     char *fileName, __u64 mode, __u64 uid, __u64 gid,
2760                     dev_t device, const struct nls_table *nls_codepage)
2761 {
2762         TRANSACTION2_SPI_REQ *pSMB = NULL;
2763         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2764         int name_len;
2765         int rc = 0;
2766         int bytes_returned = 0;
2767         FILE_UNIX_BASIC_INFO *data_offset;
2768
2769         cFYI(1, ("In SetUID/GID/Mode"));
2770 setPermsRetry:
2771         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2772                       (void **) &pSMBr);
2773         if (rc)
2774                 return rc;
2775
2776         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2777                 name_len =
2778                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2779                                   /* find define for this maxpathcomponent */
2780                                   , nls_codepage);
2781                 name_len++;     /* trailing null */
2782                 name_len *= 2;
2783         } else {                /* BB improve the check for buffer overruns BB */
2784                 name_len = strnlen(fileName, 530);
2785                 name_len++;     /* trailing null */
2786                 strncpy(pSMB->FileName, fileName, name_len);
2787         }
2788
2789         pSMB->ParameterCount = 6 + name_len;
2790         pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
2791         pSMB->MaxParameterCount = cpu_to_le16(2);
2792         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2793         pSMB->MaxSetupCount = 0;
2794         pSMB->Reserved = 0;
2795         pSMB->Flags = 0;
2796         pSMB->Timeout = 0;
2797         pSMB->Reserved2 = 0;
2798         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2799                                      InformationLevel) - 4;
2800         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2801         data_offset =
2802             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2803                                       pSMB->DataOffset);
2804         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2805         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2806         pSMB->SetupCount = 1;
2807         pSMB->Reserved3 = 0;
2808         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2809         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2810         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2811         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2812         pSMB->TotalParameterCount = pSMB->ParameterCount;
2813         pSMB->TotalDataCount = pSMB->DataCount;
2814         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2815         pSMB->Reserved4 = 0;
2816         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2817         data_offset->Uid = cpu_to_le64(uid);
2818         data_offset->Gid = cpu_to_le64(gid);
2819         /* better to leave device as zero when it is  */
2820         data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2821         data_offset->DevMinor = cpu_to_le64(MINOR(device));
2822         data_offset->Permissions = cpu_to_le64(mode);
2823         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2824         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2825                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2826         if (rc) {
2827                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2828         }
2829
2830         if (pSMB)
2831                 cifs_buf_release(pSMB);
2832         if (rc == -EAGAIN)
2833                 goto setPermsRetry;
2834         return rc;
2835 }
2836
2837 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, 
2838                         const int notify_subdirs, const __u16 netfid,
2839                         __u32 filter, const struct nls_table *nls_codepage)
2840 {
2841         int rc = 0;
2842         struct smb_com_transaction_change_notify_req * pSMB = NULL;
2843         struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
2844         int bytes_returned;
2845
2846         cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
2847         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2848                       (void **) &pSMBr);
2849         if (rc)
2850                 return rc;
2851
2852         pSMB->TotalParameterCount = 0 ;
2853         pSMB->TotalDataCount = 0;
2854         pSMB->MaxParameterCount = cpu_to_le32(2);
2855         /* BB find exact data count max from sess structure BB */
2856         pSMB->MaxDataCount = 0; /* same in little endian or be */
2857         pSMB->MaxSetupCount = 4;
2858         pSMB->Reserved = 0;
2859         pSMB->ParameterOffset = 0;
2860         pSMB->DataCount = 0;
2861         pSMB->DataOffset = 0;
2862         pSMB->SetupCount = 4; /* single byte does not need le conversion */
2863         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
2864         pSMB->ParameterCount = pSMB->TotalParameterCount;
2865         if(notify_subdirs)
2866                 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
2867         pSMB->Reserved2 = 0;
2868         pSMB->CompletionFilter = cpu_to_le32(filter);
2869         pSMB->Fid = netfid; /* file handle always le */
2870         pSMB->ByteCount = 0;
2871
2872         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2873         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2874                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2875         if (rc) {
2876                 cFYI(1, ("Error in Notify = %d", rc));
2877         }
2878         if (pSMB)
2879                 cifs_buf_release(pSMB);
2880 /*              if (rc == -EAGAIN)
2881                         goto NotifyRetry; */
2882         return rc;      
2883 }
2884 #ifdef CONFIG_CIFS_XATTR
2885 int
2886 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
2887                  const unsigned char *searchName,
2888                  char * EAData, size_t size,
2889                  const struct nls_table *nls_codepage)
2890 {
2891                 /* BB assumes one setup word */
2892         TRANSACTION2_QPI_REQ *pSMB = NULL;
2893         TRANSACTION2_QPI_RSP *pSMBr = NULL;
2894         int rc = 0;
2895         int bytes_returned;
2896         int name_len;
2897
2898         cFYI(1, ("In Query All EAs path %s", searchName));
2899 QAllEAsRetry:
2900         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2901                       (void **) &pSMBr);
2902         if (rc)
2903                 return rc;
2904
2905         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2906                 name_len =
2907                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
2908                                   /* find define for this maxpathcomponent */
2909                                   , nls_codepage);
2910                 name_len++;     /* trailing null */
2911                 name_len *= 2;
2912         } else {                /* BB improve the check for buffer overruns BB */
2913                 name_len = strnlen(searchName, 530);
2914                 name_len++;     /* trailing null */
2915                 strncpy(pSMB->FileName, searchName, name_len);
2916         }
2917
2918         pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
2919             name_len /* includes null */ ;
2920         pSMB->TotalDataCount = 0;
2921         pSMB->MaxParameterCount = cpu_to_le16(2);
2922         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2923         pSMB->MaxSetupCount = 0;
2924         pSMB->Reserved = 0;
2925         pSMB->Flags = 0;
2926         pSMB->Timeout = 0;
2927         pSMB->Reserved2 = 0;
2928         pSMB->ParameterOffset = cpu_to_le16(offsetof(
2929         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2930         pSMB->DataCount = 0;
2931         pSMB->DataOffset = 0;
2932         pSMB->SetupCount = 1;
2933         pSMB->Reserved3 = 0;
2934         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2935         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2936         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2937         pSMB->ParameterCount = pSMB->TotalParameterCount;
2938         pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
2939         pSMB->Reserved4 = 0;
2940         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2941         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2942
2943         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2944                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2945         if (rc) {
2946                 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
2947         } else {                /* decode response */
2948                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2949                 /* BB also check enough total bytes returned */
2950                 /* BB we need to improve the validity checking
2951                 of these trans2 responses */
2952                 if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512)) 
2953                         rc = -EIO;      /* bad smb */
2954            /* else if (pFindData){
2955                         memcpy((char *) pFindData,
2956                                (char *) &pSMBr->hdr.Protocol +
2957                                pSMBr->DataOffset, kl);
2958                 }*/ else {
2959                         /* check that length of list is not more than bcc */
2960                         /* check that each entry does not go beyond length
2961                            of list */
2962                         /* check that each element of each entry does not
2963                            go beyond end of list */
2964                         struct fealist * ea_response_data;
2965                         rc = 0;
2966                         /* validate_trans2_offsets() */
2967                         /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
2968                         ea_response_data = (struct fealist *)
2969                                 (((char *) &pSMBr->hdr.Protocol) +
2970                                 pSMBr->DataOffset);
2971                         cFYI(1,("ea length %d",ea_response_data->list_len));
2972                 }
2973         }
2974         if (pSMB)
2975                 cifs_buf_release(pSMB);
2976         if (rc == -EAGAIN)
2977                 goto QAllEAsRetry;
2978
2979         return rc;
2980 }
2981 #endif