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