4 * Copyright (C) International Business Machines Corp., 2002,2003
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
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.
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.
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
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 */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <asm/uaccess.h>
36 #include "cifsproto.h"
37 #include "cifs_unicode.h"
38 #include "cifs_debug.h"
40 #ifdef CONFIG_CIFS_POSIX
45 {CIFS_PROT, "\2NT LM 0.12"},
46 {CIFS_PROT, "\2POSIX 2"},
54 {CIFS_PROT, "\2NT LM 0.12"},
60 /* Mark as invalid, all open files on tree connections since they
61 were closed when session to server was lost */
62 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
64 struct cifsFileInfo *open_file = NULL;
65 struct list_head * tmp;
66 struct list_head * tmp1;
68 /* list all files open on tree connection and mark them invalid */
69 write_lock(&GlobalSMBSeslock);
70 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
71 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
73 open_file->invalidHandle = TRUE;
76 write_unlock(&GlobalSMBSeslock);
77 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
81 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
82 void **request_buf /* returned */ ,
83 void **response_buf /* returned */ )
87 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
88 check for tcp and smb session status done differently
89 for those three - in the calling routine */
91 if((tcon->ses) && (tcon->ses->server)){
92 struct nls_table *nls_codepage;
93 /* Give Demultiplex thread up to 10 seconds to
94 reconnect, should be greater than cifs socket
95 timeout which is 7 seconds */
96 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
97 wait_event_interruptible_timeout(tcon->ses->server->response_q,
98 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
99 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100 /* on "soft" mounts we wait once */
101 if((tcon->retry == FALSE) ||
102 (tcon->ses->status == CifsExiting)) {
103 cFYI(1,("gave up waiting on reconnect in smb_init"));
105 } /* else "hard" mount - keep retrying until
106 process is killed or server comes back up */
107 } else /* TCP session is reestablished now */
112 nls_codepage = load_nls_default();
113 /* need to prevent multiple threads trying to
114 simultaneously reconnect the same SMB session */
115 down(&tcon->ses->sesSem);
116 if(tcon->ses->status == CifsNeedReconnect)
117 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
118 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
119 mark_open_files_invalid(tcon);
120 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
122 up(&tcon->ses->sesSem);
124 atomic_inc(&tconInfoReconnectCount);
126 cFYI(1, ("reconnect tcon rc = %d", rc));
127 /* Removed call to reopen open files here -
128 it is safer (and faster) to reopen files
129 one at a time as needed in read and write */
131 /* Check if handle based operation so we
132 know whether we can continue or not without
133 returning to caller to reset file handle */
134 switch(smb_command) {
135 case SMB_COM_READ_ANDX:
136 case SMB_COM_WRITE_ANDX:
138 case SMB_COM_FIND_CLOSE2:
139 case SMB_COM_LOCKING_ANDX: {
140 unload_nls(nls_codepage);
145 up(&tcon->ses->sesSem);
147 unload_nls(nls_codepage);
156 *request_buf = cifs_buf_get();
157 if (*request_buf == 0) {
158 /* BB should we add a retry in here if not a writepage? */
161 /* Although the original thought was we needed the response buf for */
162 /* potential retries of smb operations it turns out we can determine */
163 /* from the mid flags when the request buffer can be resent without */
164 /* having to use a second distinct buffer for the response */
165 *response_buf = *request_buf;
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
170 #ifdef CONFIG_CIFS_STATS
172 atomic_inc(&tcon->num_smbs_sent);
179 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
182 NEGOTIATE_RSP *pSMBr;
185 struct TCP_Server_Info * server;
188 server = ses->server;
193 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
194 (void **) &pSMB, (void **) &pSMBr);
198 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
199 if (extended_security)
200 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
202 pSMB->ByteCount = strlen(protocols[0].name) + 1;
203 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
204 /* null guaranteed to be at end of source and target buffers anyway */
206 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
207 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
209 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
210 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
212 server->secMode = pSMBr->SecurityMode;
213 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
214 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
215 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
216 /* probably no need to store and check maxvcs */
218 min(le32_to_cpu(pSMBr->MaxBufferSize),
219 (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
220 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
221 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
222 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
223 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
224 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
225 /* BB with UTC do we ever need to be using srvr timezone? */
226 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
227 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
228 CIFS_CRYPTO_KEY_SIZE);
229 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
230 && (pSMBr->EncryptionKeyLength == 0)) {
231 /* decode security blob */
235 /* BB might be helpful to save off the domain of server here */
237 if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
238 if (pSMBr->ByteCount < 16)
240 else if (pSMBr->ByteCount == 16) {
241 server->secType = RawNTLMSSP;
242 if (server->socketUseCount.counter > 1) {
244 (server->server_GUID,
245 pSMBr->u.extended_response.
248 ("UID of server does not match previous connection to same ip address"));
256 memcpy(server->server_GUID,
257 pSMBr->u.extended_response.
260 rc = decode_negTokenInit(pSMBr->u.
264 16, &server->secType);
267 server->capabilities &= ~CAP_EXTENDED_SECURITY;
268 if(sign_CIFS_PDUs == FALSE) {
269 if(server->secMode & SECMODE_SIGN_REQUIRED)
271 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
272 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
273 } else if(sign_CIFS_PDUs == 1) {
274 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
275 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
280 cifs_buf_release(pSMB);
285 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
287 struct smb_hdr *smb_buffer;
288 struct smb_hdr *smb_buffer_response;
292 cFYI(1, ("In tree disconnect"));
294 * If last user of the connection and
295 * connection alive - disconnect it
296 * If this is the last connection on the server session disconnect it
297 * (and inside session disconnect we should check if tcp socket needs
298 * to be freed and kernel thread woken up).
301 down(&tcon->tconSem);
305 atomic_dec(&tcon->useCount);
306 if (atomic_read(&tcon->useCount) > 0) {
311 /* No need to return error on this operation if tid invalidated and
312 closed on server already e.g. due to tcp session crashing */
313 if(tcon->tidStatus == CifsNeedReconnect) {
318 if((tcon->ses == 0) || (tcon->ses->server == 0)) {
323 rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
324 (void **) &smb_buffer, (void **) &smb_buffer_response);
329 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
332 cFYI(1, (" Tree disconnect failed %d", rc));
335 cifs_buf_release(smb_buffer);
338 /* No need to return error on this operation if tid invalidated and
339 closed on server already e.g. due to tcp session crashing */
347 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
349 struct smb_hdr *smb_buffer_response;
350 LOGOFF_ANDX_REQ *pSMB;
354 cFYI(1, ("In SMBLogoff for session disconnect"));
360 atomic_dec(&ses->inUse);
361 if (atomic_read(&ses->inUse) > 0) {
366 rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL /* no tcon anymore */,
367 (void **) &pSMB, (void **) &smb_buffer_response);
369 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
370 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
377 pSMB->hdr.Uid = ses->Suid;
379 pSMB->AndXCommand = 0xFF;
380 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
381 smb_buffer_response, &length, 0);
383 atomic_dec(&ses->server->socketUseCount);
384 if (atomic_read(&ses->server->socketUseCount) == 0) {
385 spin_lock(&GlobalMid_Lock);
386 ses->server->tcpStatus = CifsExiting;
387 spin_unlock(&GlobalMid_Lock);
392 cifs_buf_release(pSMB);
395 /* if session dead then we do not need to do ulogoff,
396 since server closed smb session, no sense reporting
404 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
405 const char *fileName, const struct nls_table *nls_codepage)
407 DELETE_FILE_REQ *pSMB = NULL;
408 DELETE_FILE_RSP *pSMBr = NULL;
414 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
419 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
421 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
422 /* find define for this maxpathcomponent */
424 name_len++; /* trailing null */
426 } else { /* BB improve the check for buffer overruns BB */
427 name_len = strnlen(fileName, 530);
428 name_len++; /* trailing null */
429 strncpy(pSMB->fileName, fileName, name_len);
431 pSMB->SearchAttributes =
432 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
433 pSMB->ByteCount = name_len + 1;
434 pSMB->BufferFormat = 0x04;
435 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
436 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
437 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
438 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
440 cFYI(1, ("Error in RMFile = %d", rc));
442 #ifdef CONFIG_CIFS_STATS
444 atomic_inc(&tcon->num_deletes);
449 cifs_buf_release(pSMB);
457 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
458 const char *dirName, const struct nls_table *nls_codepage)
460 DELETE_DIRECTORY_REQ *pSMB = NULL;
461 DELETE_DIRECTORY_RSP *pSMBr = NULL;
466 cFYI(1, ("In CIFSSMBRmDir"));
468 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
473 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
474 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
475 /* find define for this maxpathcomponent */
477 name_len++; /* trailing null */
479 } else { /* BB improve the check for buffer overruns BB */
480 name_len = strnlen(dirName, 530);
481 name_len++; /* trailing null */
482 strncpy(pSMB->DirName, dirName, name_len);
485 pSMB->ByteCount = name_len + 1;
486 pSMB->BufferFormat = 0x04;
487 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
488 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
489 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
490 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
492 cFYI(1, ("Error in RMDir = %d", rc));
494 #ifdef CONFIG_CIFS_STATS
496 atomic_inc(&tcon->num_rmdirs);
501 cifs_buf_release(pSMB);
508 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
509 const char *name, const struct nls_table *nls_codepage)
512 CREATE_DIRECTORY_REQ *pSMB = NULL;
513 CREATE_DIRECTORY_RSP *pSMBr = NULL;
517 cFYI(1, ("In CIFSSMBMkDir"));
519 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
524 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
525 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
526 /* find define for this maxpathcomponent */
528 name_len++; /* trailing null */
530 } else { /* BB improve the check for buffer overruns BB */
531 name_len = strnlen(name, 530);
532 name_len++; /* trailing null */
533 strncpy(pSMB->DirName, name, name_len);
536 pSMB->ByteCount = name_len + 1 /* for buf format */ ;
537 pSMB->BufferFormat = 0x04;
538 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
539 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
540 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
541 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
543 cFYI(1, ("Error in Mkdir = %d", rc));
545 #ifdef CONFIG_CIFS_STATS
547 atomic_inc(&tcon->num_mkdirs);
551 cifs_buf_release(pSMB);
558 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
559 const char *fileName, const int openDisposition,
560 const int access_flags, const int create_options, __u16 * netfid,
561 int *pOplock, FILE_ALL_INFO * pfile_info,
562 const struct nls_table *nls_codepage)
565 OPEN_REQ *pSMB = NULL;
566 OPEN_RSP *pSMBr = NULL;
571 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
576 pSMB->AndXCommand = 0xFF; /* none */
578 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
579 pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
581 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
583 /* find define for this maxpathcomponent */
585 name_len++; /* trailing null */
587 pSMB->NameLength = cpu_to_le16(name_len);
588 } else { /* BB improve the check for buffer overruns BB */
589 pSMB->ByteCount = 0; /* no pad */
590 name_len = strnlen(fileName, 530);
591 name_len++; /* trailing null */
592 pSMB->NameLength = cpu_to_le16(name_len);
593 strncpy(pSMB->fileName, fileName, name_len);
595 if (*pOplock & REQ_OPLOCK)
596 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
597 else if (*pOplock & REQ_BATCHOPLOCK) {
598 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
600 pSMB->DesiredAccess = cpu_to_le32(access_flags);
601 pSMB->AllocationSize = 0;
602 pSMB->FileAttributes = ATTR_NORMAL;
603 /* XP does not handle ATTR_POSIX_SEMANTICS */
604 /* but it helps speed up case sensitive checks for other
605 servers such as Samba */
606 if (tcon->ses->capabilities & CAP_UNIX)
607 pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
609 /* if ((omode & S_IWUGO) == 0)
610 pSMB->FileAttributes |= ATTR_READONLY;*/
611 /* Above line causes problems due to vfs splitting create into two
612 pieces - need to set mode after file created not while it is
614 pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
615 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
616 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
617 pSMB->CreateOptions = cpu_to_le32(create_options);
618 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
619 pSMB->SecurityFlags =
620 cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
622 pSMB->ByteCount += name_len;
623 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
625 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
626 /* long_op set to 1 to allow for oplock break timeouts */
627 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
628 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
630 cFYI(1, ("Error in Open = %d", rc));
632 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
633 *netfid = pSMBr->Fid; /* cifs fid stays in le */
634 /* Let caller know file was created so we can set the mode. */
635 /* Do we care about the CreateAction in any other cases? */
636 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
637 *pOplock |= CIFS_CREATE_ACTION;
639 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
640 36 /* CreationTime to Attributes */);
641 /* the file_info buf is endian converted by caller */
642 pfile_info->AllocationSize = pSMBr->AllocationSize;
643 pfile_info->EndOfFile = pSMBr->EndOfFile;
644 pfile_info->NumberOfLinks = cpu_to_le32(1);
647 #ifdef CONFIG_CIFS_STATS
648 atomic_inc(&tcon->num_opens);
652 cifs_buf_release(pSMB);
658 /* If no buffer passed in, then caller wants to do the copy
659 as in the case of readpages so the SMB buffer must be
660 freed by the caller */
663 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
664 const int netfid, const unsigned int count,
665 const __u64 lseek, unsigned int *nbytes, char **buf)
668 READ_REQ *pSMB = NULL;
669 READ_RSP *pSMBr = NULL;
670 char *pReadData = NULL;
674 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
679 /* tcon and ses pointer are checked in smb_init */
680 if (tcon->ses->server == NULL)
681 return -ECONNABORTED;
683 pSMB->AndXCommand = 0xFF; /* none */
685 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
686 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
688 pSMB->MaxCount = cpu_to_le16(count);
689 pSMB->MaxCountHigh = 0;
690 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
692 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
693 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
695 cERROR(1, ("Send error in read = %d", rc));
697 pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
698 *nbytes = pSMBr->DataLength;
699 /*check that DataLength would not go beyond end of SMB */
700 if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
701 || (pSMBr->DataLength > count)) {
702 cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
707 (char *) (&pSMBr->hdr.Protocol) +
708 le16_to_cpu(pSMBr->DataOffset);
709 /* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
710 cERROR(1,("Faulting on read rc = %d",rc));
712 }*/ /* can not use copy_to_user when using page cache*/
714 memcpy(*buf,pReadData,pSMBr->DataLength);
719 cifs_buf_release(pSMB);
724 /* Note: On -EAGAIN error only caller can retry on handle based calls
725 since file handle passed in no longer valid */
730 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
731 const int netfid, const unsigned int count,
732 const __u64 offset, unsigned int *nbytes, const char *buf,
736 WRITE_REQ *pSMB = NULL;
737 WRITE_RSP *pSMBr = NULL;
740 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
744 /* tcon and ses pointer are checked in smb_init */
745 if (tcon->ses->server == NULL)
746 return -ECONNABORTED;
748 pSMB->AndXCommand = 0xFF; /* none */
750 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
751 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
753 if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
754 pSMB->DataLengthLow =
755 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
757 pSMB->DataLengthLow = count;
758 pSMB->DataLengthHigh = 0;
760 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
762 memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
764 pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
765 pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
766 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
767 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
769 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
770 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
772 cFYI(1, ("Send error in write = %d", rc));
775 *nbytes = le16_to_cpu(pSMBr->Count);
778 cifs_buf_release(pSMB);
780 /* Note: On -EAGAIN error only caller can retry on handle based calls
781 since file handle passed in no longer valid */
787 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
788 const __u16 smb_file_id, const __u64 len,
789 const __u64 offset, const __u32 numUnlock,
790 const __u32 numLock, const __u8 lockType, const int waitFlag)
793 LOCK_REQ *pSMB = NULL;
794 LOCK_RSP *pSMBr = NULL;
799 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
800 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
805 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
806 timeout = -1; /* no response expected */
808 } else if (waitFlag == TRUE) {
809 timeout = 3; /* blocking operation, no timeout */
810 pSMB->Timeout = -1; /* blocking - do not time out */
815 pSMB->NumberOfLocks = cpu_to_le32(numLock);
816 pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
817 pSMB->LockType = lockType;
818 pSMB->AndXCommand = 0xFF; /* none */
819 pSMB->Fid = smb_file_id; /* netfid stays le */
822 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
823 /* BB where to store pid high? */
824 temp = cpu_to_le64(len);
825 pSMB->Locks[0].LengthLow = (__u32)(temp & 0xFFFFFFFF);
826 pSMB->Locks[0].LengthHigh = (__u32)(temp>>32);
827 temp = cpu_to_le64(offset);
828 pSMB->Locks[0].OffsetLow = (__u32)(temp & 0xFFFFFFFF);
829 pSMB->Locks[0].OffsetHigh = (__u32)(temp>>32);
830 pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
835 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
836 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
838 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
839 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
842 cFYI(1, ("Send error in Lock = %d", rc));
845 cifs_buf_release(pSMB);
847 /* Note: On -EAGAIN error only caller can retry on handle based calls
848 since file handle passed in no longer valid */
853 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
856 CLOSE_REQ *pSMB = NULL;
857 CLOSE_RSP *pSMBr = NULL;
859 cFYI(1, ("In CIFSSMBClose"));
861 /* do not retry on dead session on close */
862 rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
869 pSMB->FileID = (__u16) smb_file_id;
870 pSMB->LastWriteTime = 0;
872 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
873 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
876 /* EINTR is expected when user ctl-c to kill app */
877 cERROR(1, ("Send error in Close = %d", rc));
881 cifs_buf_release(pSMB);
883 /* Since session is dead, file will be closed on server already */
891 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
892 const char *fromName, const char *toName,
893 const struct nls_table *nls_codepage)
896 RENAME_REQ *pSMB = NULL;
897 RENAME_RSP *pSMBr = NULL;
899 int name_len, name_len2;
901 cFYI(1, ("In CIFSSMBRename"));
903 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
908 pSMB->BufferFormat = 0x04;
909 pSMB->SearchAttributes =
910 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
913 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
915 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
916 /* find define for this maxpathcomponent */
918 name_len++; /* trailing null */
920 pSMB->OldFileName[name_len] = 0x04; /* pad */
921 /* protocol requires ASCII signature byte on Unicode string */
922 pSMB->OldFileName[name_len + 1] = 0x00;
924 cifs_strtoUCS((wchar_t *) & pSMB->
925 OldFileName[name_len + 2], toName, 530,
927 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
928 name_len2 *= 2; /* convert to bytes */
929 } else { /* BB improve the check for buffer overruns BB */
930 name_len = strnlen(fromName, 530);
931 name_len++; /* trailing null */
932 strncpy(pSMB->OldFileName, fromName, name_len);
933 name_len2 = strnlen(toName, 530);
934 name_len2++; /* trailing null */
935 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
936 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
937 name_len2++; /* trailing null */
938 name_len2++; /* signature byte */
941 pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
942 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
943 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
945 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
946 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
948 cFYI(1, ("Send error in rename = %d", rc));
951 #ifdef CONFIG_CIFS_STATS
953 atomic_inc(&tcon->num_renames);
958 cifs_buf_release(pSMB);
966 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
967 int netfid, char * target_name, const struct nls_table * nls_codepage)
969 struct smb_com_transaction2_sfi_req *pSMB = NULL;
970 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
971 struct set_file_rename * rename_info;
973 char dummy_string[30];
975 int bytes_returned = 0;
978 cFYI(1, ("Rename to File by handle"));
979 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
984 pSMB->ParameterCount = 6;
985 pSMB->MaxSetupCount = 0;
990 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
992 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
994 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
995 rename_info = (struct set_file_rename *) data_offset;
996 pSMB->MaxParameterCount = cpu_to_le16(2);
997 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
998 pSMB->SetupCount = 1;
1000 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1001 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
1002 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1003 pSMB->TotalParameterCount = pSMB->ParameterCount;
1004 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1005 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1006 /* construct random name ".cifs_tmp<inodenum><mid>" */
1007 rename_info->overwrite = cpu_to_le32(1);
1008 rename_info->root_fid = 0;
1009 /* unicode only call */
1010 if(target_name == NULL) {
1011 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1012 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
1014 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
1016 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1017 pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1018 pSMB->ByteCount += pSMB->DataCount;
1019 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1020 pSMB->TotalDataCount = pSMB->DataCount;
1022 pSMB->InformationLevel =
1023 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1024 pSMB->Reserved4 = 0;
1025 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1026 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1027 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1028 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1030 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1032 #ifdef CONFIG_CIFS_STATS
1034 atomic_inc(&pTcon->num_t2renames);
1038 cifs_buf_release(pSMB);
1040 /* Note: On -EAGAIN error only caller can retry on handle based calls
1041 since file handle passed in no longer valid */
1047 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1048 const __u16 target_tid, const char *toName, const int flags,
1049 const struct nls_table *nls_codepage)
1052 COPY_REQ *pSMB = NULL;
1053 COPY_RSP *pSMBr = NULL;
1055 int name_len, name_len2;
1057 cFYI(1, ("In CIFSSMBCopy"));
1059 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1064 pSMB->BufferFormat = 0x04;
1065 pSMB->Tid2 = target_tid;
1067 if(flags & COPY_TREE)
1068 pSMB->Flags |= COPY_TREE;
1069 pSMB->Flags = cpu_to_le16(pSMB->Flags);
1071 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1072 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
1074 530 /* find define for this maxpathcomponent */,
1076 name_len++; /* trailing null */
1078 pSMB->OldFileName[name_len] = 0x04; /* pad */
1079 /* protocol requires ASCII signature byte on Unicode string */
1080 pSMB->OldFileName[name_len + 1] = 0x00;
1081 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1082 OldFileName[name_len + 2], toName, 530,
1084 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1085 name_len2 *= 2; /* convert to bytes */
1086 } else { /* BB improve the check for buffer overruns BB */
1087 name_len = strnlen(fromName, 530);
1088 name_len++; /* trailing null */
1089 strncpy(pSMB->OldFileName, fromName, name_len);
1090 name_len2 = strnlen(toName, 530);
1091 name_len2++; /* trailing null */
1092 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1093 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1094 name_len2++; /* trailing null */
1095 name_len2++; /* signature byte */
1098 pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
1099 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1100 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1102 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1103 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1105 cFYI(1, ("Send error in copy = %d with %d files copied",
1106 rc, pSMBr->CopyCount));
1109 cifs_buf_release(pSMB);
1118 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1119 const char *fromName, const char *toName,
1120 const struct nls_table *nls_codepage)
1122 TRANSACTION2_SPI_REQ *pSMB = NULL;
1123 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1126 int name_len_target;
1128 int bytes_returned = 0;
1130 cFYI(1, ("In Symlink Unix style"));
1132 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1137 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1139 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
1140 /* find define for this maxpathcomponent */
1142 name_len++; /* trailing null */
1145 } else { /* BB improve the check for buffer overruns BB */
1146 name_len = strnlen(fromName, 530);
1147 name_len++; /* trailing null */
1148 strncpy(pSMB->FileName, fromName, name_len);
1150 pSMB->ParameterCount = 6 + name_len;
1151 pSMB->MaxSetupCount = 0;
1155 pSMB->Reserved2 = 0;
1156 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1157 InformationLevel) - 4;
1158 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1160 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1161 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1163 cifs_strtoUCS((wchar_t *) data_offset, toName, 530
1164 /* find define for this maxpathcomponent */
1166 name_len_target++; /* trailing null */
1167 name_len_target *= 2;
1168 } else { /* BB improve the check for buffer overruns BB */
1169 name_len_target = strnlen(toName, 530);
1170 name_len_target++; /* trailing null */
1171 strncpy(data_offset, toName, name_len_target);
1174 pSMB->DataCount = name_len_target;
1175 pSMB->MaxParameterCount = cpu_to_le16(2);
1176 /* BB find exact max on data count below from sess */
1177 pSMB->MaxDataCount = cpu_to_le16(1000);
1178 pSMB->SetupCount = 1;
1179 pSMB->Reserved3 = 0;
1180 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1181 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
1182 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1183 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1184 pSMB->TotalDataCount = pSMB->DataCount;
1185 pSMB->TotalParameterCount = pSMB->ParameterCount;
1186 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1187 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1188 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1189 pSMB->Reserved4 = 0;
1190 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1191 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1192 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1193 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1196 ("Send error in SetPathInfo (create symlink) = %d",
1201 cifs_buf_release(pSMB);
1204 goto createSymLinkRetry;
1210 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1211 const char *fromName, const char *toName,
1212 const struct nls_table *nls_codepage)
1214 TRANSACTION2_SPI_REQ *pSMB = NULL;
1215 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1218 int name_len_target;
1220 int bytes_returned = 0;
1222 cFYI(1, ("In Create Hard link Unix style"));
1223 createHardLinkRetry:
1224 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1229 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1230 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
1231 /* find define for this maxpathcomponent */
1233 name_len++; /* trailing null */
1236 } else { /* BB improve the check for buffer overruns BB */
1237 name_len = strnlen(toName, 530);
1238 name_len++; /* trailing null */
1239 strncpy(pSMB->FileName, toName, name_len);
1241 pSMB->ParameterCount = 6 + name_len;
1242 pSMB->MaxSetupCount = 0;
1246 pSMB->Reserved2 = 0;
1247 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1248 InformationLevel) - 4;
1249 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1251 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1252 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1254 cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
1255 /* find define for this maxpathcomponent */
1257 name_len_target++; /* trailing null */
1258 name_len_target *= 2;
1259 } else { /* BB improve the check for buffer overruns BB */
1260 name_len_target = strnlen(fromName, 530);
1261 name_len_target++; /* trailing null */
1262 strncpy(data_offset, fromName, name_len_target);
1265 pSMB->DataCount = name_len_target;
1266 pSMB->MaxParameterCount = cpu_to_le16(2);
1267 /* BB find exact max on data count below from sess*/
1268 pSMB->MaxDataCount = cpu_to_le16(1000);
1269 pSMB->SetupCount = 1;
1270 pSMB->Reserved3 = 0;
1271 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1272 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
1273 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1274 pSMB->TotalParameterCount = pSMB->ParameterCount;
1275 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1276 pSMB->TotalDataCount = pSMB->DataCount;
1277 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1278 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1279 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1280 pSMB->Reserved4 = 0;
1281 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1282 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1283 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1284 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1286 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1290 cifs_buf_release(pSMB);
1292 goto createHardLinkRetry;
1298 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1299 const char *fromName, const char *toName,
1300 const struct nls_table *nls_codepage)
1303 NT_RENAME_REQ *pSMB = NULL;
1304 RENAME_RSP *pSMBr = NULL;
1306 int name_len, name_len2;
1308 cFYI(1, ("In CIFSCreateHardLink"));
1309 winCreateHardLinkRetry:
1311 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1316 pSMB->SearchAttributes =
1317 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1319 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1320 pSMB->ClusterCount = 0;
1322 pSMB->BufferFormat = 0x04;
1324 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1326 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
1327 /* find define for this maxpathcomponent */
1329 name_len++; /* trailing null */
1331 pSMB->OldFileName[name_len] = 0; /* pad */
1332 pSMB->OldFileName[name_len + 1] = 0x04;
1334 cifs_strtoUCS((wchar_t *) & pSMB->
1335 OldFileName[name_len + 2], toName, 530,
1337 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1338 name_len2 *= 2; /* convert to bytes */
1339 } else { /* BB improve the check for buffer overruns BB */
1340 name_len = strnlen(fromName, 530);
1341 name_len++; /* trailing null */
1342 strncpy(pSMB->OldFileName, fromName, name_len);
1343 name_len2 = strnlen(toName, 530);
1344 name_len2++; /* trailing null */
1345 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1346 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1347 name_len2++; /* trailing null */
1348 name_len2++; /* signature byte */
1351 pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
1352 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1353 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1355 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1356 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1358 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1361 cifs_buf_release(pSMB);
1363 goto winCreateHardLinkRetry;
1369 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1370 const unsigned char *searchName,
1371 char *symlinkinfo, const int buflen,
1372 const struct nls_table *nls_codepage)
1374 /* SMB_QUERY_FILE_UNIX_LINK */
1375 TRANSACTION2_QPI_REQ *pSMB = NULL;
1376 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1381 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1384 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1389 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1391 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1392 /* find define for this maxpathcomponent */
1394 name_len++; /* trailing null */
1396 } else { /* BB improve the check for buffer overruns BB */
1397 name_len = strnlen(searchName, 530);
1398 name_len++; /* trailing null */
1399 strncpy(pSMB->FileName, searchName, name_len);
1402 pSMB->TotalParameterCount =
1403 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1404 pSMB->TotalDataCount = 0;
1405 pSMB->MaxParameterCount = cpu_to_le16(2);
1406 /* BB find exact max data count below from sess structure BB */
1407 pSMB->MaxDataCount = cpu_to_le16(4000);
1408 pSMB->MaxSetupCount = 0;
1412 pSMB->Reserved2 = 0;
1413 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1414 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1415 pSMB->DataCount = 0;
1416 pSMB->DataOffset = 0;
1417 pSMB->SetupCount = 1;
1418 pSMB->Reserved3 = 0;
1419 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1420 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1421 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1422 pSMB->ParameterCount = pSMB->TotalParameterCount;
1423 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1424 pSMB->Reserved4 = 0;
1425 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1426 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1428 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1429 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1431 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1432 } else { /* decode response */
1433 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1434 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1435 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1436 /* BB also check enough total bytes returned */
1437 rc = -EIO; /* bad smb */
1439 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1440 name_len = UniStrnlen((wchar_t *) ((char *)
1441 &pSMBr->hdr.Protocol +pSMBr->DataOffset),
1442 min_t(const int, buflen,pSMBr->DataCount) / 2);
1443 cifs_strfromUCS_le(symlinkinfo,
1444 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1446 name_len, nls_codepage);
1448 strncpy(symlinkinfo,
1449 (char *) &pSMBr->hdr.Protocol +
1451 min_t(const int, buflen, pSMBr->DataCount));
1453 symlinkinfo[buflen] = 0;
1454 /* just in case so calling code does not go off the end of buffer */
1458 cifs_buf_release(pSMB);
1460 goto querySymLinkRetry;
1467 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1468 const unsigned char *searchName,
1469 char *symlinkinfo, const int buflen,__u16 fid,
1470 const struct nls_table *nls_codepage)
1475 struct smb_com_transaction_ioctl_req * pSMB;
1476 struct smb_com_transaction_ioctl_rsp * pSMBr;
1478 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1479 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1484 pSMB->TotalParameterCount = 0 ;
1485 pSMB->TotalDataCount = 0;
1486 pSMB->MaxParameterCount = cpu_to_le32(2);
1487 /* BB find exact data count max from sess structure BB */
1488 pSMB->MaxDataCount = cpu_to_le32(4000);
1489 pSMB->MaxSetupCount = 4;
1491 pSMB->ParameterOffset = 0;
1492 pSMB->DataCount = 0;
1493 pSMB->DataOffset = 0;
1494 pSMB->SetupCount = 4;
1495 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1496 pSMB->ParameterCount = pSMB->TotalParameterCount;
1497 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1498 pSMB->IsFsctl = 1; /* FSCTL */
1499 pSMB->IsRootFlag = 0;
1500 pSMB->Fid = fid; /* file handle always le */
1501 pSMB->ByteCount = 0;
1503 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1504 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1506 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1507 } else { /* decode response */
1508 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1509 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1510 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1511 /* BB also check enough total bytes returned */
1512 rc = -EIO; /* bad smb */
1514 if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
1515 /* could also validate reparse tag && better check name length */
1516 struct reparse_data * reparse_buf = (struct reparse_data *)
1517 ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
1518 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1519 name_len = UniStrnlen((wchar_t *)
1520 (reparse_buf->LinkNamesBuf +
1521 reparse_buf->TargetNameOffset),
1522 min(buflen/2, reparse_buf->TargetNameLen / 2));
1523 cifs_strfromUCS_le(symlinkinfo,
1524 (wchar_t *) (reparse_buf->LinkNamesBuf +
1525 reparse_buf->TargetNameOffset),
1526 name_len, nls_codepage);
1527 } else { /* ASCII names */
1528 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1529 reparse_buf->TargetNameOffset,
1530 min_t(const int, buflen, reparse_buf->TargetNameLen));
1534 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1536 symlinkinfo[buflen] = 0; /* just in case so the caller
1537 does not go off the end of the buffer */
1538 cFYI(1,("readlink result - %s ",symlinkinfo));
1542 cifs_buf_release(pSMB);
1544 /* Note: On -EAGAIN error only caller can retry on handle based calls
1545 since file handle passed in no longer valid */
1551 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1552 const unsigned char *searchName,
1553 FILE_ALL_INFO * pFindData,
1554 const struct nls_table *nls_codepage)
1556 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1557 TRANSACTION2_QPI_REQ *pSMB = NULL;
1558 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1563 cFYI(1, ("In QPathInfo path %s", searchName));
1565 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1570 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1572 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1573 /* find define for this maxpathcomponent */
1575 name_len++; /* trailing null */
1577 } else { /* BB improve the check for buffer overruns BB */
1578 name_len = strnlen(searchName, 530);
1579 name_len++; /* trailing null */
1580 strncpy(pSMB->FileName, searchName, name_len);
1583 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1584 name_len /* includes null */ ;
1585 pSMB->TotalDataCount = 0;
1586 pSMB->MaxParameterCount = cpu_to_le16(2);
1587 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1588 pSMB->MaxSetupCount = 0;
1592 pSMB->Reserved2 = 0;
1593 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1594 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1595 pSMB->DataCount = 0;
1596 pSMB->DataOffset = 0;
1597 pSMB->SetupCount = 1;
1598 pSMB->Reserved3 = 0;
1599 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1600 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1601 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1602 pSMB->ParameterCount = pSMB->TotalParameterCount;
1603 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1604 pSMB->Reserved4 = 0;
1605 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1606 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1608 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1609 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1611 cFYI(1, ("Send error in QPathInfo = %d", rc));
1612 } else { /* decode response */
1613 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1614 /* BB also check enough total bytes returned */
1615 /* BB we need to improve the validity checking
1616 of these trans2 responses */
1617 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1618 rc = -EIO; /* bad smb */
1619 else if (pFindData){
1620 memcpy((char *) pFindData,
1621 (char *) &pSMBr->hdr.Protocol +
1622 pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
1627 cifs_buf_release(pSMB);
1629 goto QPathInfoRetry;
1635 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1636 const unsigned char *searchName,
1637 FILE_UNIX_BASIC_INFO * pFindData,
1638 const struct nls_table *nls_codepage)
1640 /* SMB_QUERY_FILE_UNIX_BASIC */
1641 TRANSACTION2_QPI_REQ *pSMB = NULL;
1642 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1644 int bytes_returned = 0;
1647 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1649 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1654 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1656 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1657 /* find define for this maxpathcomponent */
1659 name_len++; /* trailing null */
1661 } else { /* BB improve the check for buffer overruns BB */
1662 name_len = strnlen(searchName, 530);
1663 name_len++; /* trailing null */
1664 strncpy(pSMB->FileName, searchName, name_len);
1667 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1668 name_len /* includes null */ ;
1669 pSMB->TotalDataCount = 0;
1670 pSMB->MaxParameterCount = cpu_to_le16(2);
1671 /* BB find exact max SMB PDU from sess structure BB */
1672 pSMB->MaxDataCount = cpu_to_le16(4000);
1673 pSMB->MaxSetupCount = 0;
1677 pSMB->Reserved2 = 0;
1678 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1679 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1680 pSMB->DataCount = 0;
1681 pSMB->DataOffset = 0;
1682 pSMB->SetupCount = 1;
1683 pSMB->Reserved3 = 0;
1684 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1685 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1686 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1687 pSMB->ParameterCount = pSMB->TotalParameterCount;
1688 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1689 pSMB->Reserved4 = 0;
1690 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1691 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1693 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1694 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1696 cFYI(1, ("Send error in QPathInfo = %d", rc));
1697 } else { /* decode response */
1698 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1699 /* BB also check if enough total bytes returned */
1700 if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
1701 (pSMBr->DataOffset > 512) ||
1702 (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
1703 cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
1704 (int)pSMBr->DataOffset,bytes_returned));
1705 rc = -EIO; /* bad smb */
1707 memcpy((char *) pFindData,
1708 (char *) &pSMBr->hdr.Protocol +
1710 sizeof (FILE_UNIX_BASIC_INFO));
1714 cifs_buf_release(pSMB);
1716 goto UnixQPathInfoRetry;
1722 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1723 const char *searchName, FILE_ALL_INFO * findData,
1724 const struct nls_table *nls_codepage)
1726 /* level 257 SMB_ */
1727 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1728 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1733 cFYI(1, ("In FindUnique"));
1735 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1740 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1742 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1743 /* find define for this maxpathcomponent */
1745 name_len++; /* trailing null */
1747 } else { /* BB improve the check for buffer overruns BB */
1748 name_len = strnlen(searchName, 530);
1749 name_len++; /* trailing null */
1750 strncpy(pSMB->FileName, searchName, name_len);
1753 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1754 pSMB->TotalDataCount = 0; /* no EAs */
1755 pSMB->MaxParameterCount = cpu_to_le16(2);
1756 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1757 pSMB->MaxSetupCount = 0;
1761 pSMB->Reserved2 = 0;
1762 pSMB->ParameterOffset = cpu_to_le16(
1763 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1764 pSMB->DataCount = 0;
1765 pSMB->DataOffset = 0;
1766 pSMB->SetupCount = 1; /* one byte, no need to le convert */
1767 pSMB->Reserved3 = 0;
1768 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1769 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1770 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
1771 pSMB->ParameterCount = pSMB->TotalParameterCount;
1772 pSMB->SearchAttributes =
1773 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1775 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
1776 pSMB->SearchFlags = cpu_to_le16(1);
1777 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1778 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
1779 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1780 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1782 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1783 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1786 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1787 } else { /* decode response */
1792 cifs_buf_release(pSMB);
1794 goto findUniqueRetry;
1800 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1801 const char *searchName, FILE_DIRECTORY_INFO * findData,
1802 T2_FFIRST_RSP_PARMS * findParms,
1803 const struct nls_table *nls_codepage, int *pUnicodeFlag,
1806 /* level 257 SMB_ */
1807 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1808 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1809 char *response_data;
1814 cFYI(1, ("In FindFirst"));
1816 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1821 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1823 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1824 /* find define for this maxpathcomponent */
1826 name_len++; /* trailing null */
1828 } else { /* BB improve the check for buffer overruns BB */
1829 name_len = strnlen(searchName, 530);
1830 name_len++; /* trailing null */
1831 strncpy(pSMB->FileName, searchName, name_len);
1834 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1835 pSMB->TotalDataCount = 0; /* no EAs */
1836 pSMB->MaxParameterCount = cpu_to_le16(10);
1837 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1838 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1839 pSMB->MaxSetupCount = 0;
1843 pSMB->Reserved2 = 0;
1844 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1845 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1846 pSMB->ParameterCount = pSMB->TotalParameterCount;
1847 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
1848 smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1849 pSMB->DataCount = 0;
1850 pSMB->DataOffset = 0;
1851 pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
1852 pSMB->Reserved3 = 0;
1853 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1854 pSMB->SearchAttributes =
1855 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1857 pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
1858 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1860 /* test for Unix extensions */
1861 if (tcon->ses->capabilities & CAP_UNIX) {
1862 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1865 pSMB->InformationLevel =
1866 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1869 pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
1870 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1871 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1873 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1874 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1876 if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1877 cFYI(1, ("Error in FindFirst = %d", rc));
1878 } else { /* decode response */
1879 /* BB add safety checks for these memcpys */
1880 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1881 *pUnicodeFlag = TRUE;
1883 *pUnicodeFlag = FALSE;
1885 (char *) &pSMBr->hdr.Protocol +
1886 le16_to_cpu(pSMBr->ParameterOffset),
1887 sizeof (T2_FFIRST_RSP_PARMS));
1888 /* search handle can stay LE and EAoffset not needed so not converted */
1889 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1890 findParms->LastNameOffset =
1891 le16_to_cpu(findParms->LastNameOffset);
1892 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1894 (char *) &pSMBr->hdr.Protocol +
1895 le16_to_cpu(pSMBr->DataOffset);
1896 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1899 cifs_buf_release(pSMB);
1902 goto findFirstRetry;
1908 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1909 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1910 const __u16 searchHandle, char * resume_file_name, int name_len,
1911 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1913 /* level 257 SMB_ */
1914 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1915 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1916 char *response_data;
1920 cFYI(1, ("In FindNext"));
1922 if(resume_file_name == NULL) {
1925 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1930 pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
1931 pSMB->TotalDataCount = 0; /* no EAs */
1932 pSMB->MaxParameterCount = cpu_to_le16(8);
1933 pSMB->MaxDataCount =
1934 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1935 pSMB->MaxSetupCount = 0;
1939 pSMB->Reserved2 = 0;
1940 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1941 struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1942 pSMB->DataCount = 0;
1943 pSMB->DataOffset = 0;
1944 pSMB->SetupCount = 1;
1945 pSMB->Reserved3 = 0;
1946 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1947 pSMB->SearchHandle = searchHandle; /* always kept as le */
1948 findParms->SearchCount = 0; /* set to zero in case of error */
1950 cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1951 /* test for Unix extensions */
1952 if (tcon->ses->capabilities & CAP_UNIX) {
1953 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1956 pSMB->InformationLevel =
1957 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1960 pSMB->ResumeKey = resume_key;
1962 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1963 /* BB add check to make sure we do not cross end of smb */
1964 if(name_len < CIFS_MAX_MSGSIZE) {
1965 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1966 pSMB->ByteCount += name_len;
1968 pSMB->TotalParameterCount += name_len;
1969 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1970 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1971 pSMB->ParameterCount = pSMB->TotalParameterCount;
1972 /* BB improve error handling here */
1973 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1974 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1976 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1977 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1981 rc = 0; /* search probably was closed at end of search above */
1983 cFYI(1, ("FindNext returned = %d", rc));
1984 } else { /* decode response */
1985 /* BB add safety checks for these memcpys */
1986 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1987 *pUnicodeFlag = TRUE;
1989 *pUnicodeFlag = FALSE;
1991 (char *) &pSMBr->hdr.Protocol +
1992 le16_to_cpu(pSMBr->ParameterOffset),
1993 sizeof (T2_FNEXT_RSP_PARMS));
1994 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1995 findParms->LastNameOffset =
1996 le16_to_cpu(findParms->LastNameOffset);
1997 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1999 (char *) &pSMBr->hdr.Protocol +
2000 le16_to_cpu(pSMBr->DataOffset);
2001 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
2004 cifs_buf_release(pSMB);
2006 /* Note: On -EAGAIN error only caller can retry on handle based calls
2007 since file handle passed in no longer valid */
2013 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2016 FINDCLOSE_REQ *pSMB = NULL;
2017 CLOSE_RSP *pSMBr = NULL;
2020 cFYI(1, ("In CIFSSMBFindClose"));
2021 rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
2023 /* no sense returning error if session restarted
2024 file handle has been closed */
2030 pSMB->FileID = searchHandle;
2031 pSMB->ByteCount = 0;
2032 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2033 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2035 cERROR(1, ("Send error in FindClose = %d", rc));
2038 cifs_buf_release(pSMB);
2040 /* Since session is dead, search handle closed on server already */
2048 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2049 const unsigned char *searchName,
2050 unsigned char **targetUNCs,
2051 unsigned int *number_of_UNC_in_array,
2052 const struct nls_table *nls_codepage)
2054 /* TRANS2_GET_DFS_REFERRAL */
2055 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2056 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2057 struct dfs_referral_level_3 * referrals = NULL;
2063 *number_of_UNC_in_array = 0;
2066 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2070 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2075 pSMB->hdr.Tid = ses->ipc_tid;
2076 pSMB->hdr.Uid = ses->Suid;
2077 if (ses->capabilities & CAP_STATUS32) {
2078 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2080 if (ses->capabilities & CAP_DFS) {
2081 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2084 if (ses->capabilities & CAP_UNICODE) {
2085 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2087 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2089 /* find define for this maxpathcomponent */
2091 name_len++; /* trailing null */
2093 } else { /* BB improve the check for buffer overruns BB */
2094 name_len = strnlen(searchName, 530);
2095 name_len++; /* trailing null */
2096 strncpy(pSMB->RequestFileName, searchName, name_len);
2099 pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
2100 pSMB->TotalDataCount = 0;
2101 pSMB->DataCount = 0;
2102 pSMB->DataOffset = 0;
2103 pSMB->MaxParameterCount = 0;
2104 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2105 pSMB->MaxSetupCount = 0;
2109 pSMB->Reserved2 = 0;
2110 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2111 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2112 pSMB->SetupCount = 1;
2113 pSMB->Reserved3 = 0;
2114 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2115 pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
2116 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2117 pSMB->TotalParameterCount = pSMB->ParameterCount;
2118 pSMB->MaxReferralLevel = cpu_to_le16(3);
2119 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2120 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2122 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2123 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2125 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2126 } else { /* decode response */
2127 /* BB Add logic to parse referrals here */
2128 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2129 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
2131 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2132 pSMBr->ByteCount, pSMBr->DataOffset));
2133 if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
2134 rc = -EIO; /* bad smb */
2137 (struct dfs_referral_level_3 *)
2138 (8 /* sizeof start of data block */ +
2140 (char *) &pSMBr->hdr.Protocol);
2141 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
2142 /* BB This field is actually two bytes in from start of
2143 data block so we could do safety check that DataBlock
2144 begins at address of pSMBr->NumberOfReferrals */
2145 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2147 /* BB Fix below so can return more than one referral */
2148 if(*number_of_UNC_in_array > 1)
2149 *number_of_UNC_in_array = 1;
2151 /* get the length of the strings describing refs */
2153 for(i=0;i<*number_of_UNC_in_array;i++) {
2154 /* make sure that DfsPathOffset not past end */
2155 referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
2156 if(referrals->DfsPathOffset > pSMBr->DataCount) {
2157 /* if invalid referral, stop here and do
2158 not try to copy any more */
2159 *number_of_UNC_in_array = i;
2162 temp = ((char *)referrals) + referrals->DfsPathOffset;
2164 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2165 name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
2167 name_len += strnlen(temp,pSMBr->DataCount);
2170 /* BB add check that referral pointer does not fall off end PDU */
2173 /* BB add check for name_len bigger than bcc */
2175 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2176 /* copy the ref strings */
2178 (struct dfs_referral_level_3 *)
2179 (8 /* sizeof data hdr */ +
2181 (char *) &pSMBr->hdr.Protocol);
2183 for(i=0;i<*number_of_UNC_in_array;i++) {
2184 temp = ((char *)referrals) + referrals->DfsPathOffset;
2185 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2186 cifs_strfromUCS_le(*targetUNCs,
2187 (wchar_t *) temp, name_len, nls_codepage);
2189 strncpy(*targetUNCs,temp,name_len);
2191 /* BB update target_uncs pointers */
2200 cifs_buf_release(pSMB);
2209 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2210 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2212 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2213 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2214 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2215 FILE_SYSTEM_INFO *response_data;
2217 int bytes_returned = 0;
2219 cFYI(1, ("In QFSInfo"));
2221 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2226 pSMB->TotalParameterCount = 2; /* level */
2227 pSMB->TotalDataCount = 0;
2228 pSMB->MaxParameterCount = cpu_to_le16(2);
2229 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2230 pSMB->MaxSetupCount = 0;
2234 pSMB->Reserved2 = 0;
2235 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2236 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2237 pSMB->ParameterCount = pSMB->TotalParameterCount;
2238 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2239 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2240 pSMB->DataCount = 0;
2241 pSMB->DataOffset = 0;
2242 pSMB->SetupCount = 1;
2243 pSMB->Reserved3 = 0;
2244 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2245 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2246 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2247 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2249 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2250 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2252 cERROR(1, ("Send error in QFSInfo = %d", rc));
2253 } else { /* decode response */
2254 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2256 ("Decoding qfsinfo response. BCC: %d Offset %d",
2257 pSMBr->ByteCount, pSMBr->DataOffset));
2258 if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
2259 rc = -EIO; /* bad smb */
2263 *) (((char *) &pSMBr->hdr.Protocol) +
2266 le32_to_cpu(response_data->BytesPerSector) *
2267 le32_to_cpu(response_data->
2268 SectorsPerAllocationUnit);
2270 le64_to_cpu(response_data->TotalAllocationUnits);
2271 FSData->f_bfree = FSData->f_bavail =
2272 le64_to_cpu(response_data->FreeAllocationUnits);
2274 ("Blocks: %lld Free: %lld Block size %ld",
2275 (unsigned long long)FSData->f_blocks,
2276 (unsigned long long)FSData->f_bfree,
2281 cifs_buf_release(pSMB);
2290 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
2291 const struct nls_table *nls_codepage)
2293 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
2294 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2295 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2296 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
2298 int bytes_returned = 0;
2300 cFYI(1, ("In QFSAttributeInfo"));
2302 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2307 pSMB->TotalParameterCount = 2; /* level */
2308 pSMB->TotalDataCount = 0;
2309 pSMB->MaxParameterCount = cpu_to_le16(2);
2310 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2311 pSMB->MaxSetupCount = 0;
2315 pSMB->Reserved2 = 0;
2316 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2317 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2318 pSMB->ParameterCount = pSMB->TotalParameterCount;
2319 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2320 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2321 pSMB->DataCount = 0;
2322 pSMB->DataOffset = 0;
2323 pSMB->SetupCount = 1;
2324 pSMB->Reserved3 = 0;
2325 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2326 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
2327 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2328 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2330 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2331 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2333 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
2334 } else { /* decode response */
2335 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2336 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
2337 rc = -EIO; /* bad smb */
2340 (FILE_SYSTEM_ATTRIBUTE_INFO
2341 *) (((char *) &pSMBr->hdr.Protocol) +
2343 response_data->Attributes = le32_to_cpu(response_data->Attributes);
2344 response_data->MaxPathNameComponentLength =
2345 le32_to_cpu(response_data->MaxPathNameComponentLength);
2346 response_data->FileSystemNameLen =
2347 le32_to_cpu(response_data->FileSystemNameLen);
2348 memcpy(&tcon->fsAttrInfo, response_data,
2349 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
2353 cifs_buf_release(pSMB);
2356 goto QFSAttributeRetry;
2362 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
2363 const struct nls_table *nls_codepage)
2365 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
2366 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2367 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2368 FILE_SYSTEM_DEVICE_INFO *response_data;
2370 int bytes_returned = 0;
2372 cFYI(1, ("In QFSDeviceInfo"));
2374 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2379 pSMB->TotalParameterCount = 2; /* level */
2380 pSMB->TotalDataCount = 0;
2381 pSMB->MaxParameterCount = cpu_to_le16(2);
2382 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2383 pSMB->MaxSetupCount = 0;
2387 pSMB->Reserved2 = 0;
2388 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2389 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2390 pSMB->ParameterCount = pSMB->TotalParameterCount;
2391 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2392 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2394 pSMB->DataCount = 0;
2395 pSMB->DataOffset = 0;
2396 pSMB->SetupCount = 1;
2397 pSMB->Reserved3 = 0;
2398 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2399 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
2400 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2401 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2403 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2404 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2406 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
2407 } else { /* decode response */
2408 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2409 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
2410 || (pSMBr->DataOffset > 512))
2411 rc = -EIO; /* bad smb */
2414 (FILE_SYSTEM_DEVICE_INFO
2415 *) (((char *) &pSMBr->hdr.Protocol) +
2417 response_data->DeviceType =
2418 le32_to_cpu(response_data->DeviceType);
2419 response_data->DeviceCharacteristics =
2420 le32_to_cpu(response_data->DeviceCharacteristics);
2421 memcpy(&tcon->fsDevInfo, response_data,
2422 sizeof (FILE_SYSTEM_DEVICE_INFO));
2426 cifs_buf_release(pSMB);
2429 goto QFSDeviceRetry;
2435 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
2436 const struct nls_table *nls_codepage)
2438 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
2439 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2440 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2441 FILE_SYSTEM_UNIX_INFO *response_data;
2443 int bytes_returned = 0;
2445 cFYI(1, ("In QFSUnixInfo"));
2447 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2452 pSMB->ParameterCount = 2; /* level */
2453 pSMB->TotalDataCount = 0;
2454 pSMB->DataCount = 0;
2455 pSMB->DataOffset = 0;
2456 pSMB->MaxParameterCount = cpu_to_le16(2);
2457 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
2458 pSMB->MaxSetupCount = 0;
2462 pSMB->Reserved2 = 0;
2463 pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
2464 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2465 pSMB->TotalParameterCount = pSMB->ParameterCount;
2466 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
2467 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2468 pSMB->SetupCount = 1;
2469 pSMB->Reserved3 = 0;
2470 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2471 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2472 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2473 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2475 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2476 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2478 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2479 } else { /* decode response */
2480 pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
2481 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
2482 rc = -EIO; /* bad smb */
2485 (FILE_SYSTEM_UNIX_INFO
2486 *) (((char *) &pSMBr->hdr.Protocol) +
2488 response_data->MajorVersionNumber =
2489 le16_to_cpu(response_data->MajorVersionNumber);
2490 response_data->MinorVersionNumber =
2491 le16_to_cpu(response_data->MinorVersionNumber);
2492 response_data->Capability =
2493 le64_to_cpu(response_data->Capability);
2494 memcpy(&tcon->fsUnixInfo, response_data,
2495 sizeof (FILE_SYSTEM_UNIX_INFO));
2499 cifs_buf_release(pSMB);
2508 /* We can not use write of zero bytes trick to
2509 set file size due to need for large file support. Also note that
2510 this SetPathInfo is preferred to SetFileInfo based method in next
2511 routine which is only needed to work around a sharing violation bug
2512 in Samba which this routine can run into */
2515 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
2516 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2518 struct smb_com_transaction2_spi_req *pSMB = NULL;
2519 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2520 struct file_end_of_file_info *parm_data;
2523 int bytes_returned = 0;
2525 cFYI(1, ("In SetEOF"));
2527 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2532 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2534 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2535 /* find define for this maxpathcomponent */
2537 name_len++; /* trailing null */
2539 } else { /* BB improve the check for buffer overruns BB */
2540 name_len = strnlen(fileName, 530);
2541 name_len++; /* trailing null */
2542 strncpy(pSMB->FileName, fileName, name_len);
2544 pSMB->ParameterCount = 6 + name_len;
2545 pSMB->DataCount = sizeof (struct file_end_of_file_info);
2546 pSMB->MaxParameterCount = cpu_to_le16(2);
2547 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2548 pSMB->MaxSetupCount = 0;
2552 pSMB->Reserved2 = 0;
2553 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2554 InformationLevel) - 4;
2555 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2557 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2558 pSMB->InformationLevel =
2559 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2561 pSMB->InformationLevel =
2562 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2563 } else /* Set File Size */ {
2564 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2565 pSMB->InformationLevel =
2566 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2568 pSMB->InformationLevel =
2569 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2573 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2575 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2576 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2577 pSMB->SetupCount = 1;
2578 pSMB->Reserved3 = 0;
2579 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2580 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2581 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2582 pSMB->TotalDataCount = pSMB->DataCount;
2583 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2584 pSMB->TotalParameterCount = pSMB->ParameterCount;
2585 pSMB->Reserved4 = 0;
2586 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2587 parm_data->FileSize = cpu_to_le64(size);
2588 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2589 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2590 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2592 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2596 cifs_buf_release(pSMB);
2605 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
2606 __u16 fid, __u32 pid_of_opener, int SetAllocation)
2608 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2609 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2611 struct file_end_of_file_info *parm_data;
2613 int bytes_returned = 0;
2616 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
2618 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2623 tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
2624 so network fid will be valid */
2625 pSMB->hdr.Pid = tmp & 0xFFFF;
2627 pSMB->hdr.PidHigh = tmp & 0xFFFF;
2629 pSMB->ParameterCount = 6;
2630 pSMB->MaxSetupCount = 0;
2634 pSMB->Reserved2 = 0;
2635 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
2637 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2639 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2641 pSMB->DataCount = sizeof(struct file_end_of_file_info);
2642 pSMB->MaxParameterCount = cpu_to_le16(2);
2643 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2644 pSMB->SetupCount = 1;
2645 pSMB->Reserved3 = 0;
2646 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2647 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2648 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2649 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2650 pSMB->TotalDataCount = pSMB->DataCount;
2651 pSMB->TotalParameterCount = pSMB->ParameterCount;
2652 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2654 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2656 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
2657 parm_data->FileSize = cpu_to_le64(size);
2660 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2661 pSMB->InformationLevel =
2662 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2664 pSMB->InformationLevel =
2665 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2666 } else /* Set File Size */ {
2667 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2668 pSMB->InformationLevel =
2669 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2671 pSMB->InformationLevel =
2672 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2674 pSMB->Reserved4 = 0;
2675 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2676 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2677 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2678 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2681 ("Send error in SetFileInfo (SetFileSize) = %d",
2686 cifs_buf_release(pSMB);
2688 /* Note: On -EAGAIN error only caller can retry on handle based calls
2689 since file handle passed in no longer valid */
2695 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
2696 const FILE_BASIC_INFO * data,
2697 const struct nls_table *nls_codepage)
2699 TRANSACTION2_SPI_REQ *pSMB = NULL;
2700 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2703 int bytes_returned = 0;
2706 cFYI(1, ("In SetTimes"));
2709 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2714 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2716 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2717 /* find define for this maxpathcomponent */
2719 name_len++; /* trailing null */
2721 } else { /* BB improve the check for buffer overruns BB */
2722 name_len = strnlen(fileName, 530);
2723 name_len++; /* trailing null */
2724 strncpy(pSMB->FileName, fileName, name_len);
2727 pSMB->ParameterCount = 6 + name_len;
2728 pSMB->DataCount = sizeof (FILE_BASIC_INFO);
2729 pSMB->MaxParameterCount = cpu_to_le16(2);
2730 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2731 pSMB->MaxSetupCount = 0;
2735 pSMB->Reserved2 = 0;
2736 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2737 InformationLevel) - 4;
2738 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2739 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2740 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2741 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2742 pSMB->SetupCount = 1;
2743 pSMB->Reserved3 = 0;
2744 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2745 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2747 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2748 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2749 pSMB->TotalDataCount = pSMB->DataCount;
2750 pSMB->TotalParameterCount = pSMB->ParameterCount;
2751 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2752 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2754 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2755 pSMB->Reserved4 = 0;
2756 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2757 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2758 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2759 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2760 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2762 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2766 cifs_buf_release(pSMB);
2776 CIFSSMBSetTimesLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
2777 FILE_INFO_STANDARD * data, const struct nls_table *nls_codepage)
2779 TRANSACTION2_SPI_REQ *pSMB = NULL;
2780 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2783 int bytes_returned = 0;
2786 cFYI(1, ("In SetTimesLegacy"));
2788 SetTimesRetryLegacy:
2789 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2794 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2796 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2797 /* find define for this maxpathcomponent */
2799 name_len++; /* trailing null */
2801 } else { /* BB improve the check for buffer overruns BB */
2802 name_len = strnlen(fileName, 530);
2803 name_len++; /* trailing null */
2804 strncpy(pSMB->FileName, fileName, name_len);
2806 /* BB fixme - we have to map to FILE_STANDARD_INFO (level 1 info
2807 in parent function, from the better and ususal FILE_BASIC_INFO */
2808 pSMB->ParameterCount = 6 + name_len;
2809 pSMB->DataCount = sizeof (FILE_INFO_STANDARD);
2810 pSMB->MaxParameterCount = cpu_to_le16(2);
2811 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2812 pSMB->MaxSetupCount = 0;
2816 pSMB->Reserved2 = 0;
2817 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2818 InformationLevel) - 4;
2819 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2820 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2821 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2822 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2823 pSMB->SetupCount = 1;
2824 pSMB->Reserved3 = 0;
2825 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2826 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2828 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2829 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2830 pSMB->TotalDataCount = pSMB->DataCount;
2831 pSMB->TotalParameterCount = pSMB->ParameterCount;
2832 /* I doubt that passthrough levels apply to this old
2834 /* if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2835 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2837 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_STANDARD);
2838 pSMB->Reserved4 = 0;
2839 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2840 memcpy(data_offset, data, sizeof (FILE_INFO_STANDARD));
2841 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2842 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2843 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2845 cFYI(1, ("SetPathInfo (times legacy) returned %d", rc));
2849 cifs_buf_release(pSMB);
2852 goto SetTimesRetryLegacy;
2858 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2859 char *fileName, __u64 mode, __u64 uid, __u64 gid,
2860 dev_t device, const struct nls_table *nls_codepage)
2862 TRANSACTION2_SPI_REQ *pSMB = NULL;
2863 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2866 int bytes_returned = 0;
2867 FILE_UNIX_BASIC_INFO *data_offset;
2869 cFYI(1, ("In SetUID/GID/Mode"));
2871 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2876 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2878 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2879 /* find define for this maxpathcomponent */
2881 name_len++; /* trailing null */
2883 } else { /* BB improve the check for buffer overruns BB */
2884 name_len = strnlen(fileName, 530);
2885 name_len++; /* trailing null */
2886 strncpy(pSMB->FileName, fileName, name_len);
2889 pSMB->ParameterCount = 6 + name_len;
2890 pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
2891 pSMB->MaxParameterCount = cpu_to_le16(2);
2892 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2893 pSMB->MaxSetupCount = 0;
2897 pSMB->Reserved2 = 0;
2898 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2899 InformationLevel) - 4;
2900 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2902 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2904 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2905 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2906 pSMB->SetupCount = 1;
2907 pSMB->Reserved3 = 0;
2908 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2909 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2910 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2911 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2912 pSMB->TotalParameterCount = pSMB->ParameterCount;
2913 pSMB->TotalDataCount = pSMB->DataCount;
2914 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2915 pSMB->Reserved4 = 0;
2916 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2917 data_offset->Uid = cpu_to_le64(uid);
2918 data_offset->Gid = cpu_to_le64(gid);
2919 /* better to leave device as zero when it is */
2920 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2921 data_offset->DevMinor = cpu_to_le64(MINOR(device));
2922 data_offset->Permissions = cpu_to_le64(mode);
2925 data_offset->Type = cpu_to_le32(UNIX_FILE);
2926 else if(S_ISDIR(mode))
2927 data_offset->Type = cpu_to_le32(UNIX_DIR);
2928 else if(S_ISLNK(mode))
2929 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
2930 else if(S_ISCHR(mode))
2931 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
2932 else if(S_ISBLK(mode))
2933 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
2934 else if(S_ISFIFO(mode))
2935 data_offset->Type = cpu_to_le32(UNIX_FIFO);
2936 else if(S_ISSOCK(mode))
2937 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
2940 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2941 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2942 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2944 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2948 cifs_buf_release(pSMB);
2954 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
2955 const int notify_subdirs, const __u16 netfid,
2956 __u32 filter, const struct nls_table *nls_codepage)
2959 struct smb_com_transaction_change_notify_req * pSMB = NULL;
2960 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
2963 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
2964 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
2969 pSMB->TotalParameterCount = 0 ;
2970 pSMB->TotalDataCount = 0;
2971 pSMB->MaxParameterCount = cpu_to_le32(2);
2972 /* BB find exact data count max from sess structure BB */
2973 pSMB->MaxDataCount = 0; /* same in little endian or be */
2974 pSMB->MaxSetupCount = 4;
2976 pSMB->ParameterOffset = 0;
2977 pSMB->DataCount = 0;
2978 pSMB->DataOffset = 0;
2979 pSMB->SetupCount = 4; /* single byte does not need le conversion */
2980 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
2981 pSMB->ParameterCount = pSMB->TotalParameterCount;
2983 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
2984 pSMB->Reserved2 = 0;
2985 pSMB->CompletionFilter = cpu_to_le32(filter);
2986 pSMB->Fid = netfid; /* file handle always le */
2987 pSMB->ByteCount = 0;
2989 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2990 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2991 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2993 cFYI(1, ("Error in Notify = %d", rc));
2996 cifs_buf_release(pSMB);
2997 /* if (rc == -EAGAIN)
2998 goto NotifyRetry; */
3001 #ifdef CONFIG_CIFS_XATTR
3003 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3004 const unsigned char *searchName,
3005 char * EAData, size_t buf_size,
3006 const struct nls_table *nls_codepage)
3008 /* BB assumes one setup word */
3009 TRANSACTION2_QPI_REQ *pSMB = NULL;
3010 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3014 struct fea * temp_fea;
3017 cFYI(1, ("In Query All EAs path %s", searchName));
3019 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3024 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3026 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
3027 /* find define for this maxpathcomponent */
3029 name_len++; /* trailing null */
3031 } else { /* BB improve the check for buffer overruns BB */
3032 name_len = strnlen(searchName, 530);
3033 name_len++; /* trailing null */
3034 strncpy(pSMB->FileName, searchName, name_len);
3037 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
3038 name_len /* includes null */ ;
3039 pSMB->TotalDataCount = 0;
3040 pSMB->MaxParameterCount = cpu_to_le16(2);
3041 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3042 pSMB->MaxSetupCount = 0;
3046 pSMB->Reserved2 = 0;
3047 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3048 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3049 pSMB->DataCount = 0;
3050 pSMB->DataOffset = 0;
3051 pSMB->SetupCount = 1;
3052 pSMB->Reserved3 = 0;
3053 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3054 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
3055 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
3056 pSMB->ParameterCount = pSMB->TotalParameterCount;
3057 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3058 pSMB->Reserved4 = 0;
3059 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
3060 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
3062 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3063 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3065 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
3066 } else { /* decode response */
3067 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
3068 /* BB also check enough total bytes returned */
3069 /* BB we need to improve the validity checking
3070 of these trans2 responses */
3071 if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
3072 rc = -EIO; /* bad smb */
3073 /* else if (pFindData){
3074 memcpy((char *) pFindData,
3075 (char *) &pSMBr->hdr.Protocol +
3076 pSMBr->DataOffset, kl);
3078 /* check that length of list is not more than bcc */
3079 /* check that each entry does not go beyond length
3081 /* check that each element of each entry does not
3082 go beyond end of list */
3083 struct fealist * ea_response_data;
3085 /* validate_trans2_offsets() */
3086 /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
3087 ea_response_data = (struct fealist *)
3088 (((char *) &pSMBr->hdr.Protocol) +
3090 ea_response_data->list_len =
3091 cpu_to_le32(ea_response_data->list_len);
3092 cFYI(1,("ea length %d",ea_response_data->list_len));
3093 name_len = ea_response_data->list_len;
3095 /* returned EA size zeroed at top of function */
3096 cFYI(1,("empty EA list returned from server"));
3098 /* account for ea list len */
3100 temp_fea = ea_response_data->list;
3101 temp_ptr = (char *)temp_fea;
3102 while(name_len > 0) {
3105 rc += temp_fea->name_len;
3106 /* account for prefix user. and trailing null */
3109 memcpy(EAData,"user.",5);
3111 memcpy(EAData,temp_ptr,temp_fea->name_len);
3112 EAData+=temp_fea->name_len;
3113 /* null terminate name */
3115 EAData = EAData + 1;
3116 } else if(buf_size == 0) {
3117 /* skip copy - calc size only */
3119 /* stop before overrun buffer */
3123 name_len -= temp_fea->name_len;
3124 temp_ptr += temp_fea->name_len;
3125 /* account for trailing null */
3128 temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
3129 name_len -= temp_fea->value_len;
3130 temp_ptr += temp_fea->value_len;
3131 /* BB check that temp_ptr is still within smb BB*/
3132 /* no trailing null to account for in value len */
3133 /* go on to next EA */
3134 temp_fea = (struct fea *)temp_ptr;
3140 cifs_buf_release(pSMB);
3147 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
3148 const unsigned char * searchName,const unsigned char * ea_name,
3149 unsigned char * ea_value, size_t buf_size,
3150 const struct nls_table *nls_codepage)
3152 TRANSACTION2_QPI_REQ *pSMB = NULL;
3153 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3157 struct fea * temp_fea;
3160 cFYI(1, ("In Query EA path %s", searchName));
3162 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3167 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3169 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
3170 /* find define for this maxpathcomponent */
3172 name_len++; /* trailing null */
3174 } else { /* BB improve the check for buffer overruns BB */
3175 name_len = strnlen(searchName, 530);
3176 name_len++; /* trailing null */
3177 strncpy(pSMB->FileName, searchName, name_len);
3180 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
3181 name_len /* includes null */ ;
3182 pSMB->TotalDataCount = 0;
3183 pSMB->MaxParameterCount = cpu_to_le16(2);
3184 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3185 pSMB->MaxSetupCount = 0;
3189 pSMB->Reserved2 = 0;
3190 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3191 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3192 pSMB->DataCount = 0;
3193 pSMB->DataOffset = 0;
3194 pSMB->SetupCount = 1;
3195 pSMB->Reserved3 = 0;
3196 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3197 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
3198 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
3199 pSMB->ParameterCount = pSMB->TotalParameterCount;
3200 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3201 pSMB->Reserved4 = 0;
3202 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
3203 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
3205 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3206 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3208 cFYI(1, ("Send error in Query EA = %d", rc));
3209 } else { /* decode response */
3210 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
3211 /* BB also check enough total bytes returned */
3212 /* BB we need to improve the validity checking
3213 of these trans2 responses */
3214 if ((pSMBr->ByteCount < 4) || (pSMBr->DataOffset > 512))
3215 rc = -EIO; /* bad smb */
3216 /* else if (pFindData){
3217 memcpy((char *) pFindData,
3218 (char *) &pSMBr->hdr.Protocol +
3219 pSMBr->DataOffset, kl);
3221 /* check that length of list is not more than bcc */
3222 /* check that each entry does not go beyond length
3224 /* check that each element of each entry does not
3225 go beyond end of list */
3226 struct fealist * ea_response_data;
3228 /* validate_trans2_offsets() */
3229 /* BB to check if(start of smb + pSMBr->DataOffset > &bcc+ bcc)*/
3230 ea_response_data = (struct fealist *)
3231 (((char *) &pSMBr->hdr.Protocol) +
3233 ea_response_data->list_len =
3234 cpu_to_le32(ea_response_data->list_len);
3235 cFYI(1,("ea length %d",ea_response_data->list_len));
3236 name_len = ea_response_data->list_len;
3238 /* returned EA size zeroed at top of function */
3239 cFYI(1,("empty EA list returned from server"));
3241 /* account for ea list len */
3243 temp_fea = ea_response_data->list;
3244 temp_ptr = (char *)temp_fea;
3245 /* loop through checking if we have a matching
3246 name and then return the associated value */
3247 while(name_len > 0) {
3250 temp_fea->value_len = cpu_to_le16(temp_fea->value_len);
3251 /* BB validate that value_len falls within SMB,
3252 even though maximum for name_len is 255 */
3253 if(memcmp(temp_fea->name,ea_name,
3254 temp_fea->name_len) == 0) {
3256 rc = temp_fea->value_len;
3257 /* account for prefix user. and trailing null */
3260 temp_fea->name+temp_fea->name_len+1,
3262 /* ea values, unlike ea names,
3263 are not null terminated */
3264 } else if(buf_size == 0) {
3265 /* skip copy - calc size only */
3267 /* stop before overrun buffer */
3272 name_len -= temp_fea->name_len;
3273 temp_ptr += temp_fea->name_len;
3274 /* account for trailing null */
3277 name_len -= temp_fea->value_len;
3278 temp_ptr += temp_fea->value_len;
3279 /* no trailing null to account for in value len */
3280 /* go on to next EA */
3281 temp_fea = (struct fea *)temp_ptr;
3287 cifs_buf_release(pSMB);
3295 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3296 const char * ea_name, const void * ea_value,
3297 const __u16 ea_value_len, const struct nls_table *nls_codepage)
3299 struct smb_com_transaction2_spi_req *pSMB = NULL;
3300 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3301 struct fealist *parm_data;
3304 int bytes_returned = 0;
3306 cFYI(1, ("In SetEA"));
3308 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3313 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3315 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
3316 /* find define for this maxpathcomponent */
3318 name_len++; /* trailing null */
3320 } else { /* BB improve the check for buffer overruns BB */
3321 name_len = strnlen(fileName, 530);
3322 name_len++; /* trailing null */
3323 strncpy(pSMB->FileName, fileName, name_len);
3326 pSMB->ParameterCount = 6 + name_len;
3328 /* done calculating parms using name_len of file name,
3329 now use name_len to calculate length of ea name
3330 we are going to create in the inode xattrs */
3334 name_len = strnlen(ea_name,255);
3336 pSMB->DataCount = sizeof(*parm_data) + ea_value_len + name_len + 1;
3337 pSMB->MaxParameterCount = cpu_to_le16(2);
3338 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3339 pSMB->MaxSetupCount = 0;
3343 pSMB->Reserved2 = 0;
3344 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
3345 InformationLevel) - 4;
3346 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
3347 pSMB->InformationLevel =
3348 cpu_to_le16(SMB_SET_FILE_EA);
3351 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
3353 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
3354 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
3355 pSMB->SetupCount = 1;
3356 pSMB->Reserved3 = 0;
3357 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3358 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
3359 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
3360 parm_data->list_len = (__u32)(pSMB->DataCount);
3361 parm_data->list[0].EA_flags = 0;
3362 /* we checked above that name len is less than 255 */
3363 parm_data->list[0].name_len = (__u8)name_len;;
3364 /* EA names are always ASCII */
3365 strncpy(parm_data->list[0].name,ea_name,name_len);
3366 parm_data->list[0].name[name_len] = 0;
3367 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
3368 /* caller ensures that ea_value_len is less than 64K but
3369 we need to ensure that it fits within the smb */
3371 /*BB add length check that it would fit in negotiated SMB buffer size BB */
3372 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
3374 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
3376 pSMB->TotalDataCount = pSMB->DataCount;
3377 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
3378 pSMB->TotalParameterCount = pSMB->ParameterCount;
3379 pSMB->Reserved4 = 0;
3380 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
3381 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
3382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3385 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
3389 cifs_buf_release(pSMB);