commented early_printk patch because of rejects.
[linux-flexiantxendom0-3.2.10.git] / fs / cifs / cifssmb.c
1 /*
2  *   fs/cifs/cifssmb.c
3  *
4  *   Copyright (c) International Business Machines  Corp., 2002
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
26 #include <linux/fs.h>
27 #include <linux/kernel.h>
28 #include <linux/vfs.h>
29 #include <asm/uaccess.h>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsproto.h"
33 #include "cifs_unicode.h"
34 #include "cifs_debug.h"
35
36 static struct {
37         int index;
38         char *name;
39 } protocols[] = {
40         {
41         CIFS_PROT, "\2NT LM 0.12"}, {
42         BAD_PROT, "\2"}
43 };
44
45 int
46 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
47          void **request_buf /* returned */ ,
48          void **response_buf /* returned */ )
49 {
50         int rc = 0;
51
52         if(tcon && (tcon->tidStatus == CifsNeedReconnect)) {
53                 rc = -EIO;
54                 if(tcon->ses) {
55                         struct nls_table *nls_codepage = load_nls_default();
56                         if(tcon->ses->status == CifsNeedReconnect)
57                                 rc = setup_session(0, tcon->ses, nls_codepage);
58                         if(!rc) {
59                                 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
60                                         nls_codepage);
61                                 cFYI(1, ("reconnect tcon rc = %d", rc));
62                                 if(!rc)
63                                         reopen_files(tcon,nls_codepage);
64                         }
65                 }
66         }
67         if(rc)
68                 return rc;
69
70         *request_buf = buf_get();
71         if (request_buf == 0) {
72                 return -ENOMEM;
73         }
74     /* Although the original thought was we needed the response buf for  */
75     /* potential retries of smb operations it turns out we can determine */
76     /* from the mid flags when the request buffer can be resent without  */
77     /* having to use a second distinct buffer for the response */
78         *response_buf = *request_buf; 
79
80         header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
81                         wct /*wct */ );
82         return rc;
83 }
84
85 int
86 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
87 {
88         NEGOTIATE_REQ *pSMB;
89         NEGOTIATE_RSP *pSMBr;
90         int rc = 0;
91         int bytes_returned;
92         struct TCP_Server_Info * server;
93
94         if(ses->server)
95                 server = ses->server;
96         else {
97                 rc = -EIO;
98                 return rc;
99         }
100
101         rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
102                       (void **) &pSMB, (void **) &pSMBr);
103         if (rc)
104                 return rc;
105
106         pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
107         if (extended_security)
108                 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
109
110         pSMB->ByteCount = strlen(protocols[0].name) + 1;
111         strncpy(pSMB->DialectsArray, protocols[0].name, 30);    
112     /* null guaranteed to be at end of source and target buffers anyway */
113
114         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
115         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
116
117         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
118                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
119         if (rc == 0) {
120                 server->secMode = pSMBr->SecurityMode;  
121                 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
122         /* one byte - no need to convert this or EncryptionKeyLen from le,*/
123                 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
124                 /* probably no need to store and check maxvcs */
125                 server->maxBuf =
126                     min(le32_to_cpu(pSMBr->MaxBufferSize),
127                         (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
128                 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
129                 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
130                 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
131                 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
132                 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);  
133         /* BB with UTC do we ever need to be using srvr timezone? */
134                 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
135                         memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
136                                CIFS_CRYPTO_KEY_SIZE);
137                 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
138                            && (pSMBr->EncryptionKeyLength == 0)) {
139                         /* decode security blob */
140                 } else
141                         rc = -EIO;
142
143                 /* BB might be helpful to save off the domain of server here */
144
145                 if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
146                         if (pSMBr->ByteCount < 16)
147                                 rc = -EIO;
148                         else if (pSMBr->ByteCount == 16) {
149                                 server->secType = RawNTLMSSP;
150                                 if (server->socketUseCount.counter > 1) {
151                                         if (memcmp
152                                                 (server->server_GUID,
153                                                 pSMBr->u.extended_response.
154                                                 GUID, 16) != 0) {
155                                                 cFYI(1,
156                                                         ("UID of server does not match previous connection to same ip address"));
157                                                 memcpy(server->
158                                                         server_GUID,
159                                                         pSMBr->u.
160                                                         extended_response.
161                                                         GUID, 16);
162                                         }
163                                 } else
164                                         memcpy(server->server_GUID,
165                                                pSMBr->u.extended_response.
166                                                GUID, 16);
167                         } else {
168                                 rc = decode_negTokenInit(pSMBr->u.
169                                                          extended_response.
170                                                          SecurityBlob,
171                                                          pSMBr->ByteCount -
172                                                          16, &server->secType);
173                         }
174
175                 } else
176                         server->capabilities &= ~CAP_EXTENDED_SECURITY;
177                 if(sign_CIFS_PDUs == FALSE) {        
178                         if(server->secMode & SECMODE_SIGN_REQUIRED)
179                                 cERROR(1,
180                                  ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
181                         server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
182                 } else if(sign_CIFS_PDUs == 1) {
183                         if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
184                                 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
185                 }
186                                 
187         }
188         if (pSMB)
189                 buf_release(pSMB);
190         return rc;
191 }
192
193 int
194 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
195 {
196         struct smb_hdr *smb_buffer;
197         struct smb_hdr *smb_buffer_response;
198         int rc = 0;
199         int length;
200
201         cFYI(1, ("In tree disconnect"));
202         /*
203          *  If last user of the connection and
204          *  connection alive - disconnect it
205          *  If this is the last connection on the server session disconnect it
206          *  (and inside session disconnect we should check if tcp socket needs 
207          *  to be freed and kernel thread woken up).
208          */
209         if (tcon)
210                 down(&tcon->tconSem);
211         else
212                 return -EIO;
213
214         atomic_dec(&tcon->useCount);
215         if (atomic_read(&tcon->useCount) > 0) {
216                 up(&tcon->tconSem);
217                 return -EBUSY;
218         }
219
220 /* BB remove (from server) list of shares - but with smp safety  BB */
221 /* BB is ses active - do we need to check here - but how? BB */
222     if((tcon->ses == 0) || (tcon->ses->server == 0)) {    
223         up(&tcon->tconSem);
224         return -EIO;
225     }
226
227         rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
228                       (void **) &smb_buffer, (void **) &smb_buffer_response);
229         if (rc) {
230                 up(&tcon->tconSem);
231                 return rc;
232         }
233         rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
234                          &length, 0);
235         if (rc)
236                 cFYI(1, (" Tree disconnect failed %d", rc));
237
238         if (smb_buffer)
239                 buf_release(smb_buffer);
240         up(&tcon->tconSem);
241         return rc;
242 }
243
244 int
245 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
246 {
247         struct smb_hdr *smb_buffer_response;
248         LOGOFF_ANDX_REQ *pSMB;
249         int rc = 0;
250         int length;
251
252         cFYI(1, ("In SMBLogoff for session disconnect"));
253
254         if (ses)
255                 down(&ses->sesSem); /* check this sem more places */
256         else
257                 return -EIO;
258
259         atomic_dec(&ses->inUse);
260         if (atomic_read(&ses->inUse) > 0) {
261                 up(&ses->sesSem);
262                 return -EBUSY;
263         }
264
265         rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
266                  (void **) &pSMB, (void **) &smb_buffer_response);
267
268         if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
269                 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
270
271         if (rc) {
272                 up(&ses->sesSem);
273                 return rc;
274         }
275
276         pSMB->hdr.Uid = ses->Suid;
277
278         pSMB->AndXCommand = 0xFF;
279         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
280                          smb_buffer_response, &length, 0);
281         if (ses->server) {
282                 atomic_dec(&ses->server->socketUseCount);
283                 if (atomic_read(&ses->server->socketUseCount) == 0)
284                         ses->server->tcpStatus = CifsExiting;
285         }
286         if (pSMB)
287                 buf_release(pSMB);
288         up(&ses->sesSem);
289         return rc;
290 }
291
292 int
293 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
294                const char *fileName, const struct nls_table *nls_codepage)
295 {
296         DELETE_FILE_REQ *pSMB = NULL;
297         DELETE_FILE_RSP *pSMBr = NULL;
298         int rc = 0;
299         int bytes_returned;
300         int name_len;
301
302         rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
303                       (void **) &pSMBr);
304         if (rc)
305                 return rc;
306
307         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
308                 name_len =
309                     cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
310                                   /* find define for this maxpathcomponent */
311                                   , nls_codepage);
312                 name_len++;     /* trailing null */
313                 name_len *= 2;
314         } else {                /* BB improve the check for buffer overruns BB */
315                 name_len = strnlen(fileName, 530);
316                 name_len++;     /* trailing null */
317                 strncpy(pSMB->fileName, fileName, name_len);
318         }
319         pSMB->SearchAttributes =
320             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
321         pSMB->ByteCount = name_len + 1;
322         pSMB->BufferFormat = 0x04;
323         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
324         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
325         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
326                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
327         if (rc) {
328                 cFYI(1, ("Error in RMFile = %d", rc));
329         }
330         if (pSMB)
331                 buf_release(pSMB);
332         return rc;
333 }
334
335 int
336 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
337              const char *dirName, const struct nls_table *nls_codepage)
338 {
339         DELETE_DIRECTORY_REQ *pSMB = NULL;
340         DELETE_DIRECTORY_RSP *pSMBr = NULL;
341         int rc = 0;
342         int bytes_returned;
343         int name_len;
344
345         cFYI(1, ("In CIFSSMBRmDir"));
346
347         rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
348                       (void **) &pSMBr);
349         if (rc)
350                 return rc;
351
352         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
353                 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
354                                          /* find define for this maxpathcomponent */
355                                          , nls_codepage);
356                 name_len++;     /* trailing null */
357                 name_len *= 2;
358         } else {                /* BB improve the check for buffer overruns BB */
359                 name_len = strnlen(dirName, 530);
360                 name_len++;     /* trailing null */
361                 strncpy(pSMB->DirName, dirName, name_len);
362         }
363
364         pSMB->ByteCount = name_len + 1;
365         pSMB->BufferFormat = 0x04;
366         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
367         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
368         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
369                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
370         if (rc) {
371                 cFYI(1, ("Error in RMDir = %d", rc));
372         }
373         if (pSMB)
374                 buf_release(pSMB);
375         return rc;
376 }
377
378 int
379 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
380              const char *name, const struct nls_table *nls_codepage)
381 {
382         int rc = 0;
383         CREATE_DIRECTORY_REQ *pSMB = NULL;
384         CREATE_DIRECTORY_RSP *pSMBr = NULL;
385         int bytes_returned;
386         int name_len;
387
388         cFYI(1, ("In CIFSSMBMkDir"));
389
390         rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
391                       (void **) &pSMBr);
392         if (rc)
393                 return rc;
394
395         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
396                 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
397                                          /* find define for this maxpathcomponent */
398                                          , nls_codepage);
399                 name_len++;     /* trailing null */
400                 name_len *= 2;
401         } else {                /* BB improve the check for buffer overruns BB */
402                 name_len = strnlen(name, 530);
403                 name_len++;     /* trailing null */
404                 strncpy(pSMB->DirName, name, name_len);
405         }
406
407         pSMB->ByteCount = name_len + 1 /* for buf format */ ;
408         pSMB->BufferFormat = 0x04;
409         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
410         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
411         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
412                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
413         if (rc) {
414                 cFYI(1, ("Error in Mkdir = %d", rc));
415         }
416         if (pSMB)
417                 buf_release(pSMB);
418
419         return rc;
420 }
421
422 int
423 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
424             const char *fileName, const int openDisposition,
425             const int access_flags, const int create_options, __u16 * netfid,
426             int *pOplock, FILE_ALL_INFO * pfile_info, 
427             const struct nls_table *nls_codepage)
428 {
429         int rc = -EACCES;
430         OPEN_REQ *pSMB = NULL;
431         OPEN_RSP *pSMBr = NULL;
432         int bytes_returned;
433         int name_len;
434
435         rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
436                       (void **) &pSMBr);
437         if (rc)
438                 return rc;
439
440         pSMB->AndXCommand = 0xFF;       /* none */
441
442         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
443                 pSMB->ByteCount = 1;    /* account for one byte pad to word boundary */
444                 name_len =
445                     cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
446                                   fileName, 530
447                                   /* find define for this maxpathcomponent */
448                                   , nls_codepage);
449                 name_len++;     /* trailing null */
450                 name_len *= 2;
451                 pSMB->NameLength = cpu_to_le16(name_len);
452         } else {                /* BB improve the check for buffer overruns BB */
453                 pSMB->ByteCount = 0;    /* no pad */
454                 name_len = strnlen(fileName, 530);
455                 name_len++;     /* trailing null */
456                 pSMB->NameLength = cpu_to_le16(name_len);
457                 strncpy(pSMB->fileName, fileName, name_len);
458         }
459         if (*pOplock & REQ_OPLOCK)
460                 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
461         else if (*pOplock & REQ_BATCHOPLOCK) {
462                 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
463         }
464         pSMB->DesiredAccess = cpu_to_le32(access_flags);
465         pSMB->AllocationSize = 0;
466         pSMB->FileAttributes = ATTR_NORMAL;     /* XP does not handle ATTR_POSIX_SEMANTICS */
467         /*if ((omode & S_IWUGO) == 0)
468                 pSMB->FileAttributes |= ATTR_READONLY;*/
469         /*  Above line causes problems due to vfs splitting create into two
470                 pieces - need to set mode after file created not while it is
471                 being created */
472         pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
473         pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
474         pSMB->CreateDisposition = cpu_to_le32(openDisposition);
475         pSMB->CreateOptions = cpu_to_le32(create_options);
476         pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
477         pSMB->SecurityFlags =
478             cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
479
480         pSMB->ByteCount += name_len;
481         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
482
483         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
484         /* long_op set to 1 to allow for oplock break timeouts */
485         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
486                          (struct smb_hdr *) pSMBr, &bytes_returned, 1);
487         if (rc) {
488                 cFYI(1, ("Error in Open = %d", rc));
489         } else {
490                 *pOplock = pSMBr->OplockLevel;  /* one byte no need to le_to_cpu */
491                 *netfid = pSMBr->Fid;   /* cifs fid stays in le */
492                 /* Do we care about the CreateAction in any cases? */
493                 if(pfile_info) {
494                     memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
495                         36 /* CreationTime to Attributes */);
496                     /* the file_info buf is endian converted by caller */
497                     pfile_info->AllocationSize = pSMBr->AllocationSize;
498                     pfile_info->EndOfFile = pSMBr->EndOfFile;
499                     pfile_info->NumberOfLinks = cpu_to_le32(1);
500                 }
501         }
502         if (pSMB)
503                 buf_release(pSMB);
504
505         return rc;
506 }
507
508 /* If no buffer passed in, then caller wants to do the copy
509         as in the case of readpages so the SMB buffer must be
510         freed by the caller */
511
512 int
513 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
514             const int netfid, const unsigned int count,
515             const __u64 lseek, unsigned int *nbytes, char **buf)
516 {
517         int rc = -EACCES;
518         READ_REQ *pSMB = NULL;
519         READ_RSP *pSMBr = NULL;
520         char *pReadData = NULL;
521         int bytes_returned;
522
523         *nbytes = 0;
524         rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
525                       (void **) &pSMBr);
526         if (rc)
527                 return rc;
528
529         pSMB->AndXCommand = 0xFF;       /* none */
530         pSMB->Fid = netfid;
531         pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
532         pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
533         pSMB->Remaining = 0;
534         pSMB->MaxCount = cpu_to_le16(count);
535         pSMB->MaxCountHigh = 0;
536         pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
537
538         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
539                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
540         if (rc) {
541                 cERROR(1, ("Send error in read = %d", rc));
542         } else {
543                 pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
544                 *nbytes = pSMBr->DataLength;
545                 /*check that DataLength would not go beyond end of SMB */
546                 if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE) 
547                                 || (pSMBr->DataLength > count)) {
548                         cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
549                         rc = -EIO;
550                         *nbytes = 0;
551                 } else {
552                         pReadData =
553                             (char *) (&pSMBr->hdr.Protocol) +
554                             le16_to_cpu(pSMBr->DataOffset);
555 /*                      if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
556                                 cERROR(1,("Faulting on read rc = %d",rc));
557                                 rc = -EFAULT;
558                         }*/ /* can not use copy_to_user when using page cache*/
559                         if(*buf)
560                             memcpy(*buf,pReadData,pSMBr->DataLength);
561                 }
562         }
563         if (pSMB) {
564                 if(*buf)
565                         buf_release(pSMB);
566                 else
567                         *buf = (char *)pSMB;
568         }
569         return rc;
570 }
571
572 int
573 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
574              const int netfid, const unsigned int count,
575              const __u64 offset, unsigned int *nbytes, const char *buf,
576              const int long_op)
577 {
578         int rc = -EACCES;
579         WRITE_REQ *pSMB = NULL;
580         WRITE_RSP *pSMBr = NULL;
581         int bytes_returned;
582
583         rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
584                       (void **) &pSMBr);
585         if (rc)
586                 return rc;
587
588         pSMB->AndXCommand = 0xFF;       /* none */
589         pSMB->Fid = netfid;
590         pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
591         pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
592         pSMB->Remaining = 0;
593         if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
594                 pSMB->DataLengthLow =
595                     (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
596         else
597                 pSMB->DataLengthLow = count;
598         pSMB->DataLengthHigh = 0;
599         pSMB->DataOffset =
600             cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
601
602         memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
603
604         pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
605         pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
606         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
607         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
608
609         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
610                          (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
611         if (rc) {
612                 cERROR(1, ("Send error in write = %d", rc));
613                 *nbytes = 0;
614         } else
615                 *nbytes = le16_to_cpu(pSMBr->Count);
616
617         if (pSMB)
618                 buf_release(pSMB);
619
620         return rc;
621 }
622
623 int
624 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
625             const __u16 smb_file_id, const __u64 len,
626             const __u64 offset, const __u32 numUnlock,
627             const __u32 numLock, const __u8 lockType, const int waitFlag)
628 {
629         int rc = 0;
630         LOCK_REQ *pSMB = NULL;
631         LOCK_RSP *pSMBr = NULL;
632         int bytes_returned;
633         int timeout = 0;
634
635         cFYI(1, ("In CIFSSMBLock"));
636
637         rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
638                       (void **) &pSMBr);
639         if (rc)
640                 return rc;
641
642         if(lockType == LOCKING_ANDX_OPLOCK_RELEASE)
643                 timeout = -1; /* no response expected */
644
645         pSMB->NumberOfLocks = cpu_to_le32(numLock);
646         pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
647         pSMB->LockType = lockType;
648         pSMB->AndXCommand = 0xFF;       /* none */
649         pSMB->Fid = smb_file_id; /* netfid stays le */
650
651         pSMB->Locks[0].Pid = cpu_to_le16(current->pid);
652         pSMB->Locks[0].Length = cpu_to_le64(len);
653         pSMB->Locks[0].Offset = cpu_to_le64(offset);
654         pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
655         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
656         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
657
658         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
659                          (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
660
661         if (rc) {
662                 cERROR(1, ("Send error in Lock = %d", rc));
663         }
664         if (pSMB)
665                 buf_release(pSMB);
666
667         return rc;
668 }
669
670 int
671 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
672 {
673         int rc = 0;
674         CLOSE_REQ *pSMB = NULL;
675         CLOSE_RSP *pSMBr = NULL;
676         int bytes_returned;
677         cFYI(1, ("In CIFSSMBClose"));
678
679         rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
680                       (void **) &pSMBr);
681         if (rc)
682                 return rc;
683
684         pSMB->FileID = (__u16) smb_file_id;
685         pSMB->LastWriteTime = 0;
686         pSMB->ByteCount = 0;
687         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
688                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
689         if (rc) {
690                 cERROR(1, ("Send error in Close = %d", rc));
691         }
692         if (pSMB)
693                 buf_release(pSMB);
694
695         return rc;
696 }
697
698 int
699 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
700               const char *fromName, const char *toName,
701               const struct nls_table *nls_codepage)
702 {
703         int rc = 0;
704         RENAME_REQ *pSMB = NULL;
705         RENAME_RSP *pSMBr = NULL;
706         int bytes_returned;
707         int name_len, name_len2;
708
709         cFYI(1, ("In CIFSSMBRename"));
710
711         rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
712                       (void **) &pSMBr);
713         if (rc)
714                 return rc;
715
716         pSMB->BufferFormat = 0x04;
717         pSMB->SearchAttributes =
718             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
719                         ATTR_DIRECTORY);
720
721         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
722                 name_len =
723                     cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
724                                   /* find define for this maxpathcomponent */
725                                   , nls_codepage);
726                 name_len++;     /* trailing null */
727                 name_len *= 2;
728                 pSMB->OldFileName[name_len] = 0x04;     /* pad */
729         /* protocol requires ASCII signature byte on Unicode string */
730                 pSMB->OldFileName[name_len + 1] = 0x00;
731                 name_len2 =
732                     cifs_strtoUCS((wchar_t *) & pSMB->
733                                   OldFileName[name_len + 2], toName, 530,
734                                   nls_codepage);
735                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
736                 name_len2 *= 2; /* convert to bytes */
737         } else {                /* BB improve the check for buffer overruns BB */
738                 name_len = strnlen(fromName, 530);
739                 name_len++;     /* trailing null */
740                 strncpy(pSMB->OldFileName, fromName, name_len);
741                 name_len2 = strnlen(toName, 530);
742                 name_len2++;    /* trailing null */
743                 pSMB->OldFileName[name_len] = 0x04;  /* 2nd buffer format */
744                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
745                 name_len2++;    /* trailing null */
746                 name_len2++;    /* signature byte */
747         }
748
749         pSMB->ByteCount = 1 /* 1st signature byte */  + name_len + name_len2;
750     /* we could also set search attributes but not needed */
751         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
752         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
753
754         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
755                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
756         if (rc) {
757                 cFYI(1, ("Send error in RMDir = %d", rc));
758         }
759         if (pSMB)
760                 buf_release(pSMB);
761
762         return rc;
763 }
764
765 int
766 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
767                       const char *fromName, const char *toName,
768                       const struct nls_table *nls_codepage)
769 {
770         TRANSACTION2_SPI_REQ *pSMB = NULL;
771         TRANSACTION2_SPI_RSP *pSMBr = NULL;
772         char *data_offset;
773         int name_len;
774         int name_len_target;
775         int rc = 0;
776         int bytes_returned = 0;
777
778         cFYI(1, ("In Symlink Unix style"));
779
780         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
781                       (void **) &pSMBr);
782         if (rc)
783                 return rc;
784
785         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
786                 name_len =
787                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
788                                   /* find define for this maxpathcomponent */
789                                   , nls_codepage);
790                 name_len++;     /* trailing null */
791                 name_len *= 2;
792
793         } else {                /* BB improve the check for buffer overruns BB */
794                 name_len = strnlen(fromName, 530);
795                 name_len++;     /* trailing null */
796                 strncpy(pSMB->FileName, fromName, name_len);
797         }
798         pSMB->ParameterCount = 6 + name_len;
799         pSMB->MaxSetupCount = 0;
800         pSMB->Reserved = 0;
801         pSMB->Flags = 0;
802         pSMB->Timeout = 0;
803         pSMB->Reserved2 = 0;
804         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
805                                      InformationLevel) - 4;
806         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
807
808         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
809         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
810                 name_len_target =
811                     cifs_strtoUCS((wchar_t *) data_offset, toName, 530
812                                   /* find define for this maxpathcomponent */
813                                   , nls_codepage);
814                 name_len_target++;      /* trailing null */
815                 name_len_target *= 2;
816         } else {                /* BB improve the check for buffer overruns BB */
817                 name_len_target = strnlen(toName, 530);
818                 name_len_target++;      /* trailing null */
819                 strncpy(data_offset, toName, name_len_target);
820         }
821
822         pSMB->DataCount = name_len_target;
823         pSMB->MaxParameterCount = cpu_to_le16(2);
824         /* BB find exact max on data count below from sess */
825         pSMB->MaxDataCount = cpu_to_le16(1000);
826         pSMB->SetupCount = 1;
827         pSMB->Reserved3 = 0;
828         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
829         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
830         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
831         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
832         pSMB->TotalDataCount = pSMB->DataCount;
833         pSMB->TotalParameterCount = pSMB->ParameterCount;
834         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
835         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
836         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
837         pSMB->Reserved4 = 0;
838         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
839         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
840         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
841                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
842         if (rc) {
843                 cFYI(1,
844                      ("Send error in SetPathInfo (create symlink) = %d",
845                       rc));
846         }
847
848         if (pSMB)
849                 buf_release(pSMB);
850         return rc;
851 }
852
853 int
854 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
855                        const char *fromName, const char *toName,
856                        const struct nls_table *nls_codepage)
857 {
858         TRANSACTION2_SPI_REQ *pSMB = NULL;
859         TRANSACTION2_SPI_RSP *pSMBr = NULL;
860         char *data_offset;
861         int name_len;
862         int name_len_target;
863         int rc = 0;
864         int bytes_returned = 0;
865
866         cFYI(1, ("In Create Hard link Unix style"));
867
868         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
869                       (void **) &pSMBr);
870         if (rc)
871                 return rc;
872
873         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
874                 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
875                                          /* find define for this maxpathcomponent */
876                                          , nls_codepage);
877                 name_len++;     /* trailing null */
878                 name_len *= 2;
879
880         } else {                /* BB improve the check for buffer overruns BB */
881                 name_len = strnlen(toName, 530);
882                 name_len++;     /* trailing null */
883                 strncpy(pSMB->FileName, toName, name_len);
884         }
885         pSMB->ParameterCount = 6 + name_len;
886         pSMB->MaxSetupCount = 0;
887         pSMB->Reserved = 0;
888         pSMB->Flags = 0;
889         pSMB->Timeout = 0;
890         pSMB->Reserved2 = 0;
891         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
892                                      InformationLevel) - 4;
893         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
894
895         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
896         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
897                 name_len_target =
898                     cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
899                                   /* find define for this maxpathcomponent */
900                                   , nls_codepage);
901                 name_len_target++;      /* trailing null */
902                 name_len_target *= 2;
903         } else {                /* BB improve the check for buffer overruns BB */
904                 name_len_target = strnlen(fromName, 530);
905                 name_len_target++;      /* trailing null */
906                 strncpy(data_offset, fromName, name_len_target);
907         }
908
909         pSMB->DataCount = name_len_target;
910         pSMB->MaxParameterCount = cpu_to_le16(2);
911         /* BB find exact max on data count below from sess*/
912         pSMB->MaxDataCount = cpu_to_le16(1000);
913         pSMB->SetupCount = 1;
914         pSMB->Reserved3 = 0;
915         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
916         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
917         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
918         pSMB->TotalParameterCount = pSMB->ParameterCount;
919         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
920         pSMB->TotalDataCount = pSMB->DataCount;
921         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
922         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
923         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
924         pSMB->Reserved4 = 0;
925         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
926         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
927         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
928                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
929         if (rc) {
930                 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
931         }
932
933         if (pSMB)
934                 buf_release(pSMB);
935         return rc;
936 }
937
938 int
939 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
940                    const char *fromName, const char *toName,
941                    const struct nls_table *nls_codepage)
942 {
943         int rc = 0;
944         NT_RENAME_REQ *pSMB = NULL;
945         RENAME_RSP *pSMBr = NULL;
946         int bytes_returned;
947         int name_len, name_len2;
948
949         cFYI(1, ("In CIFSCreateHardLink"));
950
951         rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
952                       (void **) &pSMBr);
953         if (rc)
954                 return rc;
955
956         pSMB->SearchAttributes =
957             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
958                         ATTR_DIRECTORY);
959         pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
960         pSMB->ClusterCount = 0;
961
962         pSMB->BufferFormat = 0x04;
963
964         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
965                 name_len =
966                     cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
967                                   /* find define for this maxpathcomponent */
968                                   , nls_codepage);
969                 name_len++;     /* trailing null */
970                 name_len *= 2;
971                 pSMB->OldFileName[name_len] = 0;        /* pad */
972                 pSMB->OldFileName[name_len + 1] = 0x04; 
973                 name_len2 =
974                     cifs_strtoUCS((wchar_t *) & pSMB->
975                                   OldFileName[name_len + 2], toName, 530,
976                                   nls_codepage);
977                 name_len2 += 1 /* trailing null */  + 1 /* Signature word */ ;
978                 name_len2 *= 2; /* convert to bytes */
979         } else {                /* BB improve the check for buffer overruns BB */
980                 name_len = strnlen(fromName, 530);
981                 name_len++;     /* trailing null */
982                 strncpy(pSMB->OldFileName, fromName, name_len);
983                 name_len2 = strnlen(toName, 530);
984                 name_len2++;    /* trailing null */
985                 pSMB->OldFileName[name_len] = 0x04;     /* 2nd buffer format */
986                 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
987                 name_len2++;    /* trailing null */
988                 name_len2++;    /* signature byte */
989         }
990
991         pSMB->ByteCount = 1 /* string type byte */  + name_len + name_len2;
992         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
993         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
994
995         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
996                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
997         if (rc) {
998                 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
999         }
1000         if (pSMB)
1001                 buf_release(pSMB);
1002
1003         return rc;
1004 }
1005
1006 int
1007 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1008                         const unsigned char *searchName,
1009                         char *symlinkinfo, const int buflen,
1010                         const struct nls_table *nls_codepage)
1011 {
1012 /* SMB_QUERY_FILE_UNIX_LINK */
1013         TRANSACTION2_QPI_REQ *pSMB = NULL;
1014         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1015         int rc = 0;
1016         int bytes_returned;
1017         int name_len;
1018
1019         cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1020         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1021                       (void **) &pSMBr);
1022         if (rc)
1023                 return rc;
1024
1025         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1026                 name_len =
1027                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1028                                   /* find define for this maxpathcomponent */
1029                                   , nls_codepage);
1030                 name_len++;     /* trailing null */
1031                 name_len *= 2;
1032         } else {                /* BB improve the check for buffer overruns BB */
1033                 name_len = strnlen(searchName, 530);
1034                 name_len++;     /* trailing null */
1035                 strncpy(pSMB->FileName, searchName, name_len);
1036         }
1037
1038         pSMB->TotalParameterCount =
1039             2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
1040         pSMB->TotalDataCount = 0;
1041         pSMB->MaxParameterCount = cpu_to_le16(2);
1042         /* BB find exact max data count below from sess structure BB */
1043         pSMB->MaxDataCount = cpu_to_le16(4000);
1044         pSMB->MaxSetupCount = 0;
1045         pSMB->Reserved = 0;
1046         pSMB->Flags = 0;
1047         pSMB->Timeout = 0;
1048         pSMB->Reserved2 = 0;
1049         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1050         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1051         pSMB->DataCount = 0;
1052         pSMB->DataOffset = 0;
1053         pSMB->SetupCount = 1;
1054         pSMB->Reserved3 = 0;
1055         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1056         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1057         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1058         pSMB->ParameterCount = pSMB->TotalParameterCount;
1059         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1060         pSMB->Reserved4 = 0;
1061         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1062         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1063
1064         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1065                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1066         if (rc) {
1067                 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1068         } else {                /* decode response */
1069                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1070                 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1071                 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1072                 /* BB also check enough total bytes returned */
1073                         rc = -EIO;      /* bad smb */
1074                 else {
1075                         if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1076                                 name_len = UniStrnlen((wchar_t *) ((char *)
1077                                         &pSMBr->hdr.Protocol +pSMBr->DataOffset),
1078                                         min_t(const int, buflen,pSMBr->DataCount) / 2);
1079                                 cifs_strfromUCS_le(symlinkinfo,
1080                                         (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1081                                                 pSMBr->DataOffset),
1082                                         name_len, nls_codepage);
1083                         } else {
1084                                 strncpy(symlinkinfo,
1085                                         (char *) &pSMBr->hdr.Protocol + 
1086                                                 pSMBr->DataOffset,
1087                                         min_t(const int, buflen, pSMBr->DataCount));
1088                         }
1089                         symlinkinfo[buflen] = 0;
1090         /* just in case so calling code does not go off the end of buffer */
1091                 }
1092         }
1093         if (pSMB)
1094                 buf_release(pSMB);
1095         return rc;
1096 }
1097
1098
1099
1100 int
1101 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1102                         const unsigned char *searchName,
1103                         char *symlinkinfo, const int buflen,__u16 fid,
1104                         const struct nls_table *nls_codepage)
1105 {
1106         int rc = 0;
1107         int bytes_returned;
1108         int name_len;
1109         struct smb_com_transaction_ioctl_req * pSMB;
1110         struct smb_com_transaction_ioctl_rsp * pSMBr;
1111
1112         cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1113         rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1114                       (void **) &pSMBr);
1115         if (rc)
1116                 return rc;
1117
1118         pSMB->TotalParameterCount = 0 ;
1119         pSMB->TotalDataCount = 0;
1120         pSMB->MaxParameterCount = cpu_to_le16(2);
1121         /* BB find exact data count max from sess structure BB */
1122         pSMB->MaxDataCount = cpu_to_le16(4000);
1123         pSMB->MaxSetupCount = 4;
1124         pSMB->Reserved = 0;
1125         pSMB->ParameterOffset = 0;
1126         pSMB->DataCount = 0;
1127         pSMB->DataOffset = 0;
1128         pSMB->SetupCount = 4;
1129         pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1130         pSMB->ParameterCount = pSMB->TotalParameterCount;
1131         pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1132         pSMB->IsFsctl = 1; /* FSCTL */
1133         pSMB->IsRootFlag = 0;
1134         pSMB->Fid = fid; /* file handle always le */
1135         pSMB->ByteCount = 0;
1136
1137         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1138                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1139         if (rc) {
1140                 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1141         } else {                /* decode response */
1142                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1143                 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1144                 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1145                 /* BB also check enough total bytes returned */
1146                         rc = -EIO;      /* bad smb */
1147                 else {
1148                         if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
1149                 /* could also validate reparse tag && better check name length */
1150                                 struct reparse_data * reparse_buf = (struct reparse_data *)
1151                                         ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
1152                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1153                                         name_len = UniStrnlen((wchar_t *)
1154                                                         (reparse_buf->LinkNamesBuf + 
1155                                                         reparse_buf->TargetNameOffset),
1156                                                         min(buflen/2, reparse_buf->TargetNameLen / 2)); 
1157                                         cifs_strfromUCS_le(symlinkinfo,
1158                                                 (wchar_t *) (reparse_buf->LinkNamesBuf + 
1159                                                 reparse_buf->TargetNameOffset),
1160                                                 name_len, nls_codepage);
1161                                 } else { /* ASCII names */
1162                                         strncpy(symlinkinfo,reparse_buf->LinkNamesBuf + 
1163                                                 reparse_buf->TargetNameOffset, 
1164                                                 min_t(const int, buflen, reparse_buf->TargetNameLen));
1165                                 }
1166                         } else {
1167                                 rc = -EIO;
1168                                 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1169                         }
1170                         symlinkinfo[buflen] = 0; /* just in case so the caller
1171                                         does not go off the end of the buffer */
1172                         cFYI(1,("readlink result - %s ",symlinkinfo));
1173                 }
1174         }
1175         if (pSMB)
1176                 buf_release(pSMB);
1177         return rc;
1178 }
1179
1180 int
1181 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1182                  const unsigned char *searchName,
1183                  FILE_ALL_INFO * pFindData,
1184                  const struct nls_table *nls_codepage)
1185 {
1186 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1187         TRANSACTION2_QPI_REQ *pSMB = NULL;
1188         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1189         int rc = 0;
1190         int bytes_returned;
1191         int name_len;
1192
1193         cFYI(1, ("In QPathInfo path %s", searchName));
1194         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1195                       (void **) &pSMBr);
1196         if (rc)
1197                 return rc;
1198
1199         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1200                 name_len =
1201                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1202                                   /* find define for this maxpathcomponent */
1203                                   , nls_codepage);
1204                 name_len++;     /* trailing null */
1205                 name_len *= 2;
1206         } else {                /* BB improve the check for buffer overruns BB */
1207                 name_len = strnlen(searchName, 530);
1208                 name_len++;     /* trailing null */
1209                 strncpy(pSMB->FileName, searchName, name_len);
1210         }
1211
1212         pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
1213             name_len /* includes null */ ;
1214         pSMB->TotalDataCount = 0;
1215         pSMB->MaxParameterCount = cpu_to_le16(2);
1216         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1217         pSMB->MaxSetupCount = 0;
1218         pSMB->Reserved = 0;
1219         pSMB->Flags = 0;
1220         pSMB->Timeout = 0;
1221         pSMB->Reserved2 = 0;
1222         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1223         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1224         pSMB->DataCount = 0;
1225         pSMB->DataOffset = 0;
1226         pSMB->SetupCount = 1;
1227         pSMB->Reserved3 = 0;
1228         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1229         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1230         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1231         pSMB->ParameterCount = pSMB->TotalParameterCount;
1232         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1233         pSMB->Reserved4 = 0;
1234         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1235         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1236
1237         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1238                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1239         if (rc) {
1240                 cFYI(1, ("Send error in QPathInfo = %d", rc));
1241         } else {                /* decode response */
1242                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1243                 /* BB also check enough total bytes returned */
1244                 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512)) 
1245                         rc = -EIO;      /* bad smb */
1246                 else if (pFindData){
1247                         memcpy((char *) pFindData,
1248                                (char *) &pSMBr->hdr.Protocol +
1249                                pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
1250                 } else
1251                     rc = -ENOMEM;
1252         }
1253         if (pSMB)
1254                 buf_release(pSMB);
1255         return rc;
1256 }
1257
1258 int
1259 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1260                      const unsigned char *searchName,
1261                      FILE_UNIX_BASIC_INFO * pFindData,
1262                      const struct nls_table *nls_codepage)
1263 {
1264 /* SMB_QUERY_FILE_UNIX_BASIC */
1265         TRANSACTION2_QPI_REQ *pSMB = NULL;
1266         TRANSACTION2_QPI_RSP *pSMBr = NULL;
1267         int rc = 0;
1268         int bytes_returned;
1269         int name_len;
1270
1271         cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1272         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1273                       (void **) &pSMBr);
1274         if (rc)
1275                 return rc;
1276
1277         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1278                 name_len =
1279                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1280                                   /* find define for this maxpathcomponent */
1281                                   , nls_codepage);
1282                 name_len++;     /* trailing null */
1283                 name_len *= 2;
1284         } else {                /* BB improve the check for buffer overruns BB */
1285                 name_len = strnlen(searchName, 530);
1286                 name_len++;     /* trailing null */
1287                 strncpy(pSMB->FileName, searchName, name_len);
1288         }
1289
1290         pSMB->TotalParameterCount = 2 /* level */  + 4 /* reserved */  +
1291             name_len /* includes null */ ;
1292         pSMB->TotalDataCount = 0;
1293         pSMB->MaxParameterCount = cpu_to_le16(2);
1294         /* BB find exact max SMB PDU from sess structure BB */
1295         pSMB->MaxDataCount = cpu_to_le16(4000); 
1296         pSMB->MaxSetupCount = 0;
1297         pSMB->Reserved = 0;
1298         pSMB->Flags = 0;
1299         pSMB->Timeout = 0;
1300         pSMB->Reserved2 = 0;
1301         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1302         struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1303         pSMB->DataCount = 0;
1304         pSMB->DataOffset = 0;
1305         pSMB->SetupCount = 1;
1306         pSMB->Reserved3 = 0;
1307         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1308         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1309         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1310         pSMB->ParameterCount = pSMB->TotalParameterCount;
1311         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1312         pSMB->Reserved4 = 0;
1313         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1314         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1315
1316         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1317                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1318         if (rc) {
1319                 cFYI(1, ("Send error in QPathInfo = %d", rc));
1320         } else {                /* decode response */
1321                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1322                 /* BB also check if enough total bytes returned */
1323                 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1324                         rc = -EIO;      /* bad smb */
1325                 else {
1326                         memcpy((char *) pFindData,
1327                                (char *) &pSMBr->hdr.Protocol +
1328                                pSMBr->DataOffset,
1329                                sizeof (FILE_UNIX_BASIC_INFO));
1330                 }
1331         }
1332         if (pSMB)
1333                 buf_release(pSMB);
1334         return rc;
1335 }
1336
1337 int
1338 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1339                const char *searchName, FILE_ALL_INFO * findData,
1340                const struct nls_table *nls_codepage)
1341 {
1342 /* level 257 SMB_ */
1343         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1344         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1345         int rc = 0;
1346         int bytes_returned;
1347         int name_len;
1348
1349         cFYI(1, ("In FindUnique"));
1350         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1351                       (void **) &pSMBr);
1352         if (rc)
1353                 return rc;
1354
1355         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1356                 name_len =
1357                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1358                                   /* find define for this maxpathcomponent */
1359                                   , nls_codepage);
1360                 name_len++;     /* trailing null */
1361                 name_len *= 2;
1362         } else {                /* BB improve the check for buffer overruns BB */
1363                 name_len = strnlen(searchName, 530);
1364                 name_len++;     /* trailing null */
1365                 strncpy(pSMB->FileName, searchName, name_len);
1366         }
1367
1368         pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1369         pSMB->TotalDataCount = 0;       /* no EAs */
1370         pSMB->MaxParameterCount = cpu_to_le16(2);
1371         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1372         pSMB->MaxSetupCount = 0;
1373         pSMB->Reserved = 0;
1374         pSMB->Flags = 0;
1375         pSMB->Timeout = 0;
1376         pSMB->Reserved2 = 0;
1377         pSMB->ParameterOffset = cpu_to_le16(
1378         offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1379         pSMB->DataCount = 0;
1380         pSMB->DataOffset = 0;
1381         pSMB->SetupCount = 1;   /* one byte, no need to le convert */
1382         pSMB->Reserved3 = 0;
1383         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1384         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1385         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
1386         pSMB->ParameterCount = pSMB->TotalParameterCount;
1387         pSMB->SearchAttributes =
1388             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1389                         ATTR_DIRECTORY);
1390         pSMB->SearchCount = cpu_to_le16(16);    /* BB increase */
1391         pSMB->SearchFlags = cpu_to_le16(1);
1392         pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1393         pSMB->SearchStorageType = 0;    /* BB what should we set this to? BB */
1394         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1395         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1396
1397         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1398                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1399
1400         if (rc) {
1401                 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1402         } else {                /* decode response */
1403
1404                 /* BB fill in */
1405         }
1406         if (pSMB)
1407                 buf_release(pSMB);
1408         return rc;
1409 }
1410
1411 int
1412 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1413               const char *searchName, FILE_DIRECTORY_INFO * findData,
1414               T2_FFIRST_RSP_PARMS * findParms,
1415               const struct nls_table *nls_codepage, int *pUnicodeFlag,
1416               int *pUnixFlag)
1417 {
1418 /* level 257 SMB_ */
1419         TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1420         TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1421         char *response_data;
1422         int rc = 0;
1423         int bytes_returned;
1424         int name_len;
1425
1426         cFYI(1, ("In FindFirst"));
1427         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1428                       (void **) &pSMBr);
1429         if (rc)
1430                 return rc;
1431
1432         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1433                 name_len =
1434                     cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1435                                   /* find define for this maxpathcomponent */
1436                                   , nls_codepage);
1437                 name_len++;     /* trailing null */
1438                 name_len *= 2;
1439         } else {                /* BB improve the check for buffer overruns BB */
1440                 name_len = strnlen(searchName, 530);
1441                 name_len++;     /* trailing null */
1442                 strncpy(pSMB->FileName, searchName, name_len);
1443         }
1444
1445         pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1446         pSMB->TotalDataCount = 0;       /* no EAs */
1447         pSMB->MaxParameterCount = cpu_to_le16(10);
1448         pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1449                                           MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1450         pSMB->MaxSetupCount = 0;
1451         pSMB->Reserved = 0;
1452         pSMB->Flags = 0;
1453         pSMB->Timeout = 0;
1454         pSMB->Reserved2 = 0;
1455         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1456         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1457         pSMB->ParameterCount = pSMB->TotalParameterCount;
1458         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
1459         smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1460         pSMB->DataCount = 0;
1461         pSMB->DataOffset = 0;
1462         pSMB->SetupCount = 1;   /* one byte no need to make endian neutral */
1463         pSMB->Reserved3 = 0;
1464         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1465         pSMB->SearchAttributes =
1466             cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1467                         ATTR_DIRECTORY);
1468         pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));       /* should this be shrunk even more ? */
1469         pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1470
1471         /* test for Unix extensions */
1472         if (tcon->ses->capabilities & CAP_UNIX) {
1473                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1474                 *pUnixFlag = TRUE;
1475         } else {
1476                 pSMB->InformationLevel =
1477                     cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1478                 *pUnixFlag = FALSE;
1479         }
1480         pSMB->SearchStorageType = 0;    /* BB what should we set this to? It is not clear if it matters BB */
1481         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1482         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1483
1484         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1485                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1486
1487         if (rc) {               /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1488                 cFYI(1, ("Error in FindFirst = %d", rc));
1489         } else {                /* decode response */
1490                 /* BB add safety checks for these memcpys */
1491                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1492                         *pUnicodeFlag = TRUE;
1493                 else
1494                         *pUnicodeFlag = FALSE;
1495                 memcpy(findParms,
1496                        (char *) &pSMBr->hdr.Protocol +
1497                        le16_to_cpu(pSMBr->ParameterOffset),
1498                        sizeof (T2_FFIRST_RSP_PARMS));
1499                 /* search handle can stay LE and EAoffset not needed so not converted */
1500                 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1501                 findParms->LastNameOffset =
1502                     le16_to_cpu(findParms->LastNameOffset);
1503                 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1504                 response_data =
1505                     (char *) &pSMBr->hdr.Protocol +
1506                     le16_to_cpu(pSMBr->DataOffset);
1507                 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1508         }
1509         if (pSMB)
1510                 buf_release(pSMB);
1511         return rc;
1512 }
1513
1514 int
1515 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1516                 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1517                 const __u16 searchHandle, char * resume_file_name, int name_len,
1518                 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1519 {
1520 /* level 257 SMB_ */
1521         TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1522         TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1523         char *response_data;
1524         int rc = 0;
1525         int bytes_returned;
1526
1527         cFYI(1, ("In FindNext"));
1528         if(resume_file_name == NULL) {
1529                 return -EIO;
1530         }
1531         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1532                       (void **) &pSMBr);
1533         if (rc)
1534                 return rc;
1535
1536         pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
1537         pSMB->TotalDataCount = 0;       /* no EAs */
1538         pSMB->MaxParameterCount = cpu_to_le16(8);
1539         pSMB->MaxDataCount =
1540             cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1541         pSMB->MaxSetupCount = 0;
1542         pSMB->Reserved = 0;
1543         pSMB->Flags = 0;
1544         pSMB->Timeout = 0;
1545         pSMB->Reserved2 = 0;
1546         pSMB->ParameterOffset =  cpu_to_le16(offsetof(
1547         struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1548         pSMB->DataCount = 0;
1549         pSMB->DataOffset = 0;
1550         pSMB->SetupCount = 1;
1551         pSMB->Reserved3 = 0;
1552         pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1553         pSMB->SearchHandle = searchHandle;      /* always kept as le */
1554         findParms->SearchCount = 0;     /* set to zero in case of error */
1555         pSMB->SearchCount =
1556             cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1557         /* test for Unix extensions */
1558         if (tcon->ses->capabilities & CAP_UNIX) {
1559                 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1560                 *pUnixFlag = TRUE;
1561         } else {
1562                 pSMB->InformationLevel =
1563                     cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1564                 *pUnixFlag = FALSE;
1565         }
1566         pSMB->ResumeKey = resume_key;
1567         pSMB->SearchFlags =
1568             cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1569         /* BB add check to make sure we do not cross end of smb */
1570         if(name_len < CIFS_MAX_MSGSIZE) {
1571                 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1572                 pSMB->ByteCount += name_len;
1573         }
1574         pSMB->TotalParameterCount += name_len;
1575         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1576         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1577         pSMB->ParameterCount = pSMB->TotalParameterCount;
1578         /* BB improve error handling here */
1579         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1580         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1581
1582         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1583                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1584
1585         if (rc) {
1586                 if (rc == -EBADF)
1587                         rc = 0; /* search probably was closed at end of search above */
1588                 else
1589                         cFYI(1, ("FindNext returned = %d", rc));
1590         } else {                /* decode response */
1591                 /* BB add safety checks for these memcpys */
1592                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1593                         *pUnicodeFlag = TRUE;
1594                 else
1595                         *pUnicodeFlag = FALSE;
1596                 memcpy(findParms,
1597                        (char *) &pSMBr->hdr.Protocol +
1598                        le16_to_cpu(pSMBr->ParameterOffset),
1599                        sizeof (T2_FNEXT_RSP_PARMS));
1600                 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1601                 findParms->LastNameOffset =
1602                     le16_to_cpu(findParms->LastNameOffset);
1603                 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1604                 response_data =
1605                     (char *) &pSMBr->hdr.Protocol +
1606                     le16_to_cpu(pSMBr->DataOffset);
1607                 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1608         }
1609         if (pSMB)
1610                 buf_release(pSMB);
1611         return rc;
1612 }
1613
1614 int
1615 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
1616 {
1617         int rc = 0;
1618         FINDCLOSE_REQ *pSMB = NULL;
1619         CLOSE_RSP *pSMBr = NULL;
1620         int bytes_returned;
1621         cFYI(1, ("In CIFSSMBFindClose"));
1622
1623         rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
1624                       (void **) &pSMBr);
1625         if (rc)
1626                 return rc;
1627
1628         pSMB->FileID = searchHandle;
1629         pSMB->ByteCount = 0;
1630         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1631                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1632         if (rc) {
1633                 cERROR(1, ("Send error in FindClose = %d", rc));
1634         }
1635         if (pSMB)
1636                 buf_release(pSMB);
1637
1638         return rc;
1639 }
1640
1641 int
1642 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
1643                 const unsigned char *searchName,
1644                 unsigned char **targetUNCs,
1645                 unsigned int *number_of_UNC_in_array,
1646                 const struct nls_table *nls_codepage)
1647 {
1648 /* TRANS2_GET_DFS_REFERRAL */
1649         TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
1650         TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
1651         struct dfs_referral_level_3 * referrals = NULL;
1652         int rc = 0;
1653         int bytes_returned;
1654         int name_len;
1655         unsigned int i;
1656         char * temp;
1657         *number_of_UNC_in_array = 0;
1658         *targetUNCs = NULL;
1659
1660         cFYI(1, ("In GetDFSRefer the path %s", searchName));
1661         if (ses == NULL)
1662                 return -ENODEV;
1663
1664         rc = smb_init(SMB_COM_TRANSACTION2, 15, 0, (void **) &pSMB,
1665                       (void **) &pSMBr);
1666         if (rc)
1667                 return rc;
1668
1669         pSMB->hdr.Tid = ses->ipc_tid;
1670         pSMB->hdr.Uid = ses->Suid;
1671         if (ses->capabilities & CAP_STATUS32) {
1672                 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
1673         }
1674         if (ses->capabilities & CAP_DFS) {
1675                 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
1676         }
1677
1678         if (ses->capabilities & CAP_UNICODE) {
1679                 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
1680                 name_len =
1681                     cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
1682                                   searchName, 530
1683                                   /* find define for this maxpathcomponent */
1684                                   , nls_codepage);
1685                 name_len++;     /* trailing null */
1686                 name_len *= 2;
1687         } else {                /* BB improve the check for buffer overruns BB */
1688                 name_len = strnlen(searchName, 530);
1689                 name_len++;     /* trailing null */
1690                 strncpy(pSMB->RequestFileName, searchName, name_len);
1691         }
1692
1693         pSMB->ParameterCount = 2 /* level */  + name_len /*includes null */ ;
1694         pSMB->TotalDataCount = 0;
1695         pSMB->DataCount = 0;
1696         pSMB->DataOffset = 0;
1697         pSMB->MaxParameterCount = 0;
1698         pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1699         pSMB->MaxSetupCount = 0;
1700         pSMB->Reserved = 0;
1701         pSMB->Flags = 0;
1702         pSMB->Timeout = 0;
1703         pSMB->Reserved2 = 0;
1704         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1705         struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1706         pSMB->SetupCount = 1;
1707         pSMB->Reserved3 = 0;
1708         pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
1709         pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
1710         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1711         pSMB->TotalParameterCount = pSMB->ParameterCount;
1712         pSMB->MaxReferralLevel = cpu_to_le16(3);
1713         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1714         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1715
1716         rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
1717                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1718         if (rc) {
1719                 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
1720         } else {                /* decode response */
1721 /* BB Add logic to parse referrals here */
1722                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1723                 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1724                 cFYI(1,
1725                      ("Decoding GetDFSRefer response.  BCC: %d  Offset %d",
1726                       pSMBr->ByteCount, pSMBr->DataOffset));
1727                 if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512))       /* BB also check enough total bytes returned */
1728                         rc = -EIO;      /* bad smb */
1729                 else {
1730                         referrals = 
1731                             (struct dfs_referral_level_3 *) 
1732                                         (8 /* sizeof start of data block */ +
1733                                         pSMBr->DataOffset +
1734                                         (char *) &pSMBr->hdr.Protocol); 
1735                         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));
1736                         /* BB This field is actually two bytes in from start of
1737                            data block so we could do safety check that DataBlock
1738                            begins at address of pSMBr->NumberOfReferrals */
1739                         *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
1740
1741                         /* BB Fix below so can return more than one referral */
1742                         if(*number_of_UNC_in_array > 1)
1743                                 *number_of_UNC_in_array = 1;
1744
1745                         /* get the length of the strings describing refs */
1746                         name_len = 0;
1747                         for(i=0;i<*number_of_UNC_in_array;i++) {
1748                                 /* make sure that DfsPathOffset not past end */
1749                                 referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
1750                                 if(referrals->DfsPathOffset > pSMBr->DataCount) {
1751                                         /* if invalid referral, stop here and do 
1752                                         not try to copy any more */
1753                                         *number_of_UNC_in_array = i;
1754                                         break;
1755                                 } 
1756                                 temp = ((char *)referrals) + referrals->DfsPathOffset;
1757
1758                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1759                                         name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
1760                                 } else {
1761                                         name_len += strnlen(temp,pSMBr->DataCount);
1762                                 }
1763                                 referrals++;
1764                                 /* BB add check that referral pointer does not fall off end PDU */
1765                                 
1766                         }
1767                         /* BB add check for name_len bigger than bcc */
1768                         *targetUNCs = 
1769                                 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
1770                         /* copy the ref strings */
1771                         referrals =  
1772                             (struct dfs_referral_level_3 *) 
1773                                         (8 /* sizeof data hdr */ +
1774                                         pSMBr->DataOffset + 
1775                                         (char *) &pSMBr->hdr.Protocol);
1776
1777                         for(i=0;i<*number_of_UNC_in_array;i++) {
1778                                 temp = ((char *)referrals) + referrals->DfsPathOffset;
1779                                 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1780                                         cifs_strfromUCS_le(*targetUNCs,
1781                                                 (wchar_t *) temp, name_len, nls_codepage);
1782                                 } else {
1783                                         strncpy(*targetUNCs,temp,name_len);
1784                                 }
1785                                 /*  BB update target_uncs pointers */
1786                                 referrals++;
1787                         }
1788                         temp = *targetUNCs;
1789                         temp[name_len] = 0;
1790                 }
1791
1792         }
1793         if (pSMB)
1794                 buf_release(pSMB);
1795         return rc;
1796 }
1797
1798 int
1799 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
1800                struct kstatfs *FSData, const struct nls_table *nls_codepage)
1801 {
1802 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
1803         TRANSACTION2_QFSI_REQ *pSMB = NULL;
1804         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1805         FILE_SYSTEM_INFO *response_data;
1806         int rc = 0;
1807         int bytes_returned = 0;
1808
1809         cFYI(1, ("In QFSInfo"));
1810
1811         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1812                       (void **) &pSMBr);
1813         if (rc)
1814                 return rc;
1815
1816         pSMB->TotalParameterCount = 2;  /* level */
1817         pSMB->TotalDataCount = 0;
1818         pSMB->MaxParameterCount = cpu_to_le16(2);
1819         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1820         pSMB->MaxSetupCount = 0;
1821         pSMB->Reserved = 0;
1822         pSMB->Flags = 0;
1823         pSMB->Timeout = 0;
1824         pSMB->Reserved2 = 0;
1825         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1826         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1827         pSMB->ParameterCount = pSMB->TotalParameterCount;
1828         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1829         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1830         pSMB->DataCount = 0;
1831         pSMB->DataOffset = 0;
1832         pSMB->SetupCount = 1;
1833         pSMB->Reserved3 = 0;
1834         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1835         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
1836         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1837         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1838
1839         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1840                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1841         if (rc) {
1842                 cERROR(1, ("Send error in QFSInfo = %d", rc));
1843         } else {                /* decode response */
1844                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1845                 cFYI(1,
1846                      ("Decoding qfsinfo response.  BCC: %d  Offset %d",
1847                       pSMBr->ByteCount, pSMBr->DataOffset));
1848                 if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512))       /* BB also check enough total bytes returned */
1849                         rc = -EIO;      /* bad smb */
1850                 else {
1851                         response_data =
1852                             (FILE_SYSTEM_INFO
1853                              *) (((char *) &pSMBr->hdr.Protocol) +
1854                                  pSMBr->DataOffset);
1855                         FSData->f_bsize =
1856                             le32_to_cpu(response_data->BytesPerSector) *
1857                             le32_to_cpu(response_data->
1858                                         SectorsPerAllocationUnit);
1859                         FSData->f_blocks =
1860                             le64_to_cpu(response_data->TotalAllocationUnits);
1861                         FSData->f_bfree = FSData->f_bavail =
1862                             le64_to_cpu(response_data->FreeAllocationUnits);
1863                         cFYI(1,
1864                              ("Blocks: %lld  Free: %lld Block size %ld",
1865                               (unsigned long long)FSData->f_blocks,
1866                               (unsigned long long)FSData->f_bfree,
1867                               FSData->f_bsize));
1868                 }
1869         }
1870         if (pSMB)
1871                 buf_release(pSMB);
1872         return rc;
1873 }
1874
1875 int
1876 CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
1877                         const struct nls_table *nls_codepage)
1878 {
1879 /* level 0x105  SMB_QUERY_FILE_SYSTEM_INFO */
1880         TRANSACTION2_QFSI_REQ *pSMB = NULL;
1881         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1882         FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
1883         int rc = 0;
1884         int bytes_returned = 0;
1885
1886         cFYI(1, ("In QFSAttributeInfo"));
1887         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1888                       (void **) &pSMBr);
1889         if (rc)
1890                 return rc;
1891
1892         pSMB->TotalParameterCount = 2;  /* level */
1893         pSMB->TotalDataCount = 0;
1894         pSMB->MaxParameterCount = cpu_to_le16(2);
1895         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1896         pSMB->MaxSetupCount = 0;
1897         pSMB->Reserved = 0;
1898         pSMB->Flags = 0;
1899         pSMB->Timeout = 0;
1900         pSMB->Reserved2 = 0;
1901         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1902         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1903         pSMB->ParameterCount = pSMB->TotalParameterCount;
1904         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1905         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1906         pSMB->DataCount = 0;
1907         pSMB->DataOffset = 0;
1908         pSMB->SetupCount = 1;
1909         pSMB->Reserved3 = 0;
1910         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1911         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
1912         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1913         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1914
1915         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1916                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1917         if (rc) {
1918                 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
1919         } else {                /* decode response */
1920                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1921                 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {     /* BB also check enough bytes returned */
1922                         rc = -EIO;      /* bad smb */
1923                 } else {
1924                         response_data =
1925                             (FILE_SYSTEM_ATTRIBUTE_INFO
1926                              *) (((char *) &pSMBr->hdr.Protocol) +
1927                                  pSMBr->DataOffset);
1928                         memcpy(&tcon->fsAttrInfo, response_data,
1929                                sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
1930                 }
1931         }
1932         if (pSMB)
1933                 buf_release(pSMB);
1934         return rc;
1935 }
1936
1937 int
1938 CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
1939                      const struct nls_table *nls_codepage)
1940 {
1941 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
1942         TRANSACTION2_QFSI_REQ *pSMB = NULL;
1943         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1944         FILE_SYSTEM_DEVICE_INFO *response_data;
1945         int rc = 0;
1946         int bytes_returned = 0;
1947
1948         cFYI(1, ("In QFSDeviceInfo"));
1949
1950         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1951                       (void **) &pSMBr);
1952         if (rc)
1953                 return rc;
1954
1955         pSMB->TotalParameterCount = 2;  /* level */
1956         pSMB->TotalDataCount = 0;
1957         pSMB->MaxParameterCount = cpu_to_le16(2);
1958         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1959         pSMB->MaxSetupCount = 0;
1960         pSMB->Reserved = 0;
1961         pSMB->Flags = 0;
1962         pSMB->Timeout = 0;
1963         pSMB->Reserved2 = 0;
1964         pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1965         pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1966         pSMB->ParameterCount = pSMB->TotalParameterCount;
1967         pSMB->ParameterOffset = cpu_to_le16(offsetof(
1968         struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1969
1970         pSMB->DataCount = 0;
1971         pSMB->DataOffset = 0;
1972         pSMB->SetupCount = 1;
1973         pSMB->Reserved3 = 0;
1974         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1975         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
1976         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1977         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1978
1979         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1980                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1981         if (rc) {
1982                 cERROR(1, ("Send error in QFSDeviceInfo = %d", rc));
1983         } else {                /* decode response */
1984                 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1985                 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
1986                  || (pSMBr->DataOffset > 512))
1987                         rc = -EIO;      /* bad smb */
1988                 else {
1989                         response_data =
1990                             (FILE_SYSTEM_DEVICE_INFO
1991                              *) (((char *) &pSMBr->hdr.Protocol) +
1992                                  pSMBr->DataOffset);
1993                         memcpy(&tcon->fsDevInfo, response_data,
1994                                sizeof (FILE_SYSTEM_DEVICE_INFO));
1995                 }
1996         }
1997         if (pSMB)
1998                 buf_release(pSMB);
1999         return rc;
2000 }
2001
2002 int
2003 CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
2004                    const struct nls_table *nls_codepage)
2005 {
2006 /* level 0x200  SMB_QUERY_CIFS_UNIX_INFO */
2007         TRANSACTION2_QFSI_REQ *pSMB = NULL;
2008         TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2009         FILE_SYSTEM_UNIX_INFO *response_data;
2010         int rc = 0;
2011         int bytes_returned = 0;
2012
2013         cFYI(1, ("In QFSUnixInfo"));
2014         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2015                       (void **) &pSMBr);
2016         if (rc)
2017                 return rc;
2018
2019         pSMB->ParameterCount = 2;       /* level */
2020         pSMB->TotalDataCount = 0;
2021         pSMB->DataCount = 0;
2022         pSMB->DataOffset = 0;
2023         pSMB->MaxParameterCount = cpu_to_le16(2);
2024         pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
2025         pSMB->MaxSetupCount = 0;
2026         pSMB->Reserved = 0;
2027         pSMB->Flags = 0;
2028         pSMB->Timeout = 0;
2029         pSMB->Reserved2 = 0;
2030         pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
2031         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2032         pSMB->TotalParameterCount = pSMB->ParameterCount;
2033         pSMB->ParameterOffset = cpu_to_le16(offsetof(struct 
2034         smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2035         pSMB->SetupCount = 1;
2036         pSMB->Reserved3 = 0;
2037         pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2038         pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2039         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2040         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2041
2042         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2043                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2044         if (rc) {
2045                 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2046         } else {                /* decode response */
2047                 pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
2048                 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
2049                         rc = -EIO;      /* bad smb */
2050                 } else {
2051                         response_data =
2052                             (FILE_SYSTEM_UNIX_INFO
2053                              *) (((char *) &pSMBr->hdr.Protocol) +
2054                                  pSMBr->DataOffset);
2055                         memcpy(&tcon->fsUnixInfo, response_data,
2056                                sizeof (FILE_SYSTEM_UNIX_INFO));
2057                 }
2058         }
2059         if (pSMB)
2060                 buf_release(pSMB);
2061         return rc;
2062 }
2063
2064 /* We can not use write of zero bytes trick to 
2065    set file size due to need for large file support.  Also note that 
2066    this SetPathInfo is preferred to SetFileInfo based method in next 
2067    routine which is only needed to work around a sharing violation bug
2068    in Samba which this routine can run into */
2069
2070 int
2071 CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
2072               __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2073 {
2074         struct smb_com_transaction2_spi_req *pSMB = NULL;
2075         struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2076         struct file_end_of_file_info *parm_data;
2077         int name_len;
2078         int rc = 0;
2079         int bytes_returned = 0;
2080
2081         cFYI(1, ("In SetEOF"));
2082
2083         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2084                       (void **) &pSMBr);
2085         if (rc)
2086                 return rc;
2087
2088         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2089                 name_len =
2090                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2091                                   /* find define for this maxpathcomponent */
2092                                   , nls_codepage);
2093                 name_len++;     /* trailing null */
2094                 name_len *= 2;
2095         } else {                /* BB improve the check for buffer overruns BB */
2096                 name_len = strnlen(fileName, 530);
2097                 name_len++;     /* trailing null */
2098                 strncpy(pSMB->FileName, fileName, name_len);
2099         }
2100         pSMB->ParameterCount = 6 + name_len;
2101         pSMB->DataCount = sizeof (struct file_end_of_file_info);
2102         pSMB->MaxParameterCount = cpu_to_le16(2);
2103         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2104         pSMB->MaxSetupCount = 0;
2105         pSMB->Reserved = 0;
2106         pSMB->Flags = 0;
2107         pSMB->Timeout = 0;
2108         pSMB->Reserved2 = 0;
2109         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2110                                      InformationLevel) - 4;
2111         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2112         if(SetAllocation) {
2113                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2114                     pSMB->InformationLevel =
2115                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2116                 else
2117                     pSMB->InformationLevel =
2118                         cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2119         } else /* Set File Size */  {    
2120             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2121                     pSMB->InformationLevel =
2122                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2123             else
2124                     pSMB->InformationLevel =
2125                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2126         }
2127
2128         parm_data =
2129             (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2130                                        pSMB->DataOffset);
2131         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2132         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2133         pSMB->SetupCount = 1;
2134         pSMB->Reserved3 = 0;
2135         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2136         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2137         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2138         pSMB->TotalDataCount = pSMB->DataCount;
2139         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2140         pSMB->TotalParameterCount = pSMB->ParameterCount;
2141         pSMB->Reserved4 = 0;
2142         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2143         parm_data->FileSize = cpu_to_le64(size);
2144         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2145         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2146                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2147         if (rc) {
2148                 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2149         }
2150
2151         if (pSMB)
2152                 buf_release(pSMB);
2153         return rc;
2154 }
2155
2156 int
2157 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, 
2158                    __u16 fid, __u32 pid_of_opener, int SetAllocation)
2159 {
2160         struct smb_com_transaction2_sfi_req *pSMB  = NULL;
2161         struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2162         char *data_offset;
2163         struct file_end_of_file_info *parm_data;
2164         int rc = 0;
2165         int bytes_returned = 0;
2166         __u32 tmp;
2167
2168         cFYI(1, ("SetFileSize (via SetFileInfo)"));
2169
2170         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2171                       (void **) &pSMBr);
2172         if (rc)
2173                 return rc;
2174
2175         tmp = cpu_to_le32(pid_of_opener);  /* override pid of current process
2176                                          so network fid will be valid */
2177         pSMB->hdr.Pid = tmp & 0xFFFF;
2178         tmp >>= 16;
2179         pSMB->hdr.PidHigh = tmp & 0xFFFF;
2180     
2181         pSMB->ParameterCount = 6;
2182         pSMB->MaxSetupCount = 0;
2183         pSMB->Reserved = 0;
2184         pSMB->Flags = 0;
2185         pSMB->Timeout = 0;
2186         pSMB->Reserved2 = 0;
2187         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
2188                                      Fid) - 4;
2189         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2190
2191         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;        
2192
2193         pSMB->DataCount = sizeof(struct file_end_of_file_info);
2194         pSMB->MaxParameterCount = cpu_to_le16(2);
2195         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2196         pSMB->SetupCount = 1;
2197         pSMB->Reserved3 = 0;
2198         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2199         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2200         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2201         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2202         pSMB->TotalDataCount = pSMB->DataCount;
2203         pSMB->TotalParameterCount = pSMB->ParameterCount;
2204         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2205         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2206         parm_data =
2207                 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2208                         pSMB->DataOffset);
2209         parm_data->FileSize = size;
2210         pSMB->Fid = fid;
2211         if(SetAllocation) {
2212                 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2213                         pSMB->InformationLevel =
2214                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2215                 else
2216                         pSMB->InformationLevel =
2217                                 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2218         } else /* Set File Size */  {    
2219             if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2220                     pSMB->InformationLevel =
2221                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2222             else
2223                     pSMB->InformationLevel =
2224                         cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2225         }
2226         pSMB->Reserved4 = 0;
2227         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2228         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2229         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2230                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2231         if (rc) {
2232                 cFYI(1,
2233                      ("Send error in SetFileInfo (SetFileSize) = %d",
2234                       rc));
2235         }
2236
2237         if (pSMB)
2238                 buf_release(pSMB);
2239         return rc;
2240 }
2241
2242 int
2243 CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
2244                 FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
2245 {
2246         TRANSACTION2_SPI_REQ *pSMB = NULL;
2247         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2248         int name_len;
2249         int rc = 0;
2250         int bytes_returned = 0;
2251         char *data_offset;
2252
2253         cFYI(1, ("In SetTimes"));
2254
2255         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2256                       (void **) &pSMBr);
2257         if (rc)
2258                 return rc;
2259
2260         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2261                 name_len =
2262                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2263                                   /* find define for this maxpathcomponent */
2264                                   , nls_codepage);
2265                 name_len++;     /* trailing null */
2266                 name_len *= 2;
2267         } else {                /* BB improve the check for buffer overruns BB */
2268                 name_len = strnlen(fileName, 530);
2269                 name_len++;     /* trailing null */
2270                 strncpy(pSMB->FileName, fileName, name_len);
2271         }
2272
2273         pSMB->ParameterCount = 6 + name_len;
2274         pSMB->DataCount = sizeof (FILE_BASIC_INFO);
2275         pSMB->MaxParameterCount = cpu_to_le16(2);
2276         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2277         pSMB->MaxSetupCount = 0;
2278         pSMB->Reserved = 0;
2279         pSMB->Flags = 0;
2280         pSMB->Timeout = 0;
2281         pSMB->Reserved2 = 0;
2282         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2283                                      InformationLevel) - 4;
2284         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2285         data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2286         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2287         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2288         pSMB->SetupCount = 1;
2289         pSMB->Reserved3 = 0;
2290         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2291         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2292
2293         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2294         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2295         pSMB->TotalDataCount = pSMB->DataCount;
2296         pSMB->TotalParameterCount = pSMB->ParameterCount;
2297         if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2298                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2299         else
2300                 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2301         pSMB->Reserved4 = 0;
2302         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2303         memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2304         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2305         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2306                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2307         if (rc) {
2308                 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2309         }
2310
2311         if (pSMB)
2312                 buf_release(pSMB);
2313         return rc;
2314 }
2315
2316 int
2317 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2318                     char *fileName, __u64 mode, __u64 uid, __u64 gid,
2319                     dev_t device, const struct nls_table *nls_codepage)
2320 {
2321         TRANSACTION2_SPI_REQ *pSMB = NULL;
2322         TRANSACTION2_SPI_RSP *pSMBr = NULL;
2323         int name_len;
2324         int rc = 0;
2325         int bytes_returned = 0;
2326         FILE_UNIX_BASIC_INFO *data_offset;
2327
2328         cFYI(1, ("In SetUID/GID/Mode"));
2329
2330         rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2331                       (void **) &pSMBr);
2332         if (rc)
2333                 return rc;
2334
2335         if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2336                 name_len =
2337                     cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2338                                   /* find define for this maxpathcomponent */
2339                                   , nls_codepage);
2340                 name_len++;     /* trailing null */
2341                 name_len *= 2;
2342         } else {                /* BB improve the check for buffer overruns BB */
2343                 name_len = strnlen(fileName, 530);
2344                 name_len++;     /* trailing null */
2345                 strncpy(pSMB->FileName, fileName, name_len);
2346         }
2347
2348         pSMB->ParameterCount = 6 + name_len;
2349         pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
2350         pSMB->MaxParameterCount = cpu_to_le16(2);
2351         pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2352         pSMB->MaxSetupCount = 0;
2353         pSMB->Reserved = 0;
2354         pSMB->Flags = 0;
2355         pSMB->Timeout = 0;
2356         pSMB->Reserved2 = 0;
2357         pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2358                                      InformationLevel) - 4;
2359         pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2360         data_offset =
2361             (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2362                                       pSMB->DataOffset);
2363         pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2364         pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2365         pSMB->SetupCount = 1;
2366         pSMB->Reserved3 = 0;
2367         pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2368         pSMB->ByteCount = 3 /* pad */  + pSMB->ParameterCount + pSMB->DataCount;
2369         pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2370         pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2371         pSMB->TotalParameterCount = pSMB->ParameterCount;
2372         pSMB->TotalDataCount = pSMB->DataCount;
2373         pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2374         pSMB->Reserved4 = 0;
2375         pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2376         data_offset->Uid = cpu_to_le64(uid);
2377         data_offset->Gid = cpu_to_le64(gid);
2378         /* better to leave device as zero when it is  */
2379         data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2380         data_offset->DevMinor = cpu_to_le64(MINOR(device));
2381         data_offset->Permissions = cpu_to_le64(mode);
2382         pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2383         rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2384                          (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2385         if (rc) {
2386                 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2387         }
2388
2389         if (pSMB)
2390                 buf_release(pSMB);
2391         return rc;
2392 }