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