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, 0 /* 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 /* BB remove (from server) list of shares - but with smp safety BB */
319 /* BB is ses active - do we need to check here - but how? BB */
320 if((tcon->ses == 0) || (tcon->ses->server == 0)) {
325 rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
326 (void **) &smb_buffer, (void **) &smb_buffer_response);
331 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
334 cFYI(1, (" Tree disconnect failed %d", rc));
337 cifs_buf_release(smb_buffer);
340 /* No need to return error on this operation if tid invalidated and
341 closed on server already e.g. due to tcp session crashing */
349 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
351 struct smb_hdr *smb_buffer_response;
352 LOGOFF_ANDX_REQ *pSMB;
356 cFYI(1, ("In SMBLogoff for session disconnect"));
362 atomic_dec(&ses->inUse);
363 if (atomic_read(&ses->inUse) > 0) {
368 rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
369 (void **) &pSMB, (void **) &smb_buffer_response);
371 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
372 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
379 pSMB->hdr.Uid = ses->Suid;
381 pSMB->AndXCommand = 0xFF;
382 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
383 smb_buffer_response, &length, 0);
385 atomic_dec(&ses->server->socketUseCount);
386 if (atomic_read(&ses->server->socketUseCount) == 0)
387 ses->server->tcpStatus = CifsExiting;
390 cifs_buf_release(pSMB);
393 /* if session dead then we do not need to do ulogoff,
394 since server closed smb session, no sense reporting
402 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
403 const char *fileName, const struct nls_table *nls_codepage)
405 DELETE_FILE_REQ *pSMB = NULL;
406 DELETE_FILE_RSP *pSMBr = NULL;
412 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
417 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
419 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
420 /* find define for this maxpathcomponent */
422 name_len++; /* trailing null */
424 } else { /* BB improve the check for buffer overruns BB */
425 name_len = strnlen(fileName, 530);
426 name_len++; /* trailing null */
427 strncpy(pSMB->fileName, fileName, name_len);
429 pSMB->SearchAttributes =
430 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
431 pSMB->ByteCount = name_len + 1;
432 pSMB->BufferFormat = 0x04;
433 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
434 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
435 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
436 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
438 cFYI(1, ("Error in RMFile = %d", rc));
440 #ifdef CONFIG_CIFS_STATS
442 atomic_inc(&tcon->num_deletes);
447 cifs_buf_release(pSMB);
455 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
456 const char *dirName, const struct nls_table *nls_codepage)
458 DELETE_DIRECTORY_REQ *pSMB = NULL;
459 DELETE_DIRECTORY_RSP *pSMBr = NULL;
464 cFYI(1, ("In CIFSSMBRmDir"));
466 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
471 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
472 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
473 /* find define for this maxpathcomponent */
475 name_len++; /* trailing null */
477 } else { /* BB improve the check for buffer overruns BB */
478 name_len = strnlen(dirName, 530);
479 name_len++; /* trailing null */
480 strncpy(pSMB->DirName, dirName, name_len);
483 pSMB->ByteCount = name_len + 1;
484 pSMB->BufferFormat = 0x04;
485 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
486 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
487 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
488 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
490 cFYI(1, ("Error in RMDir = %d", rc));
492 #ifdef CONFIG_CIFS_STATS
494 atomic_inc(&tcon->num_rmdirs);
499 cifs_buf_release(pSMB);
506 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
507 const char *name, const struct nls_table *nls_codepage)
510 CREATE_DIRECTORY_REQ *pSMB = NULL;
511 CREATE_DIRECTORY_RSP *pSMBr = NULL;
515 cFYI(1, ("In CIFSSMBMkDir"));
517 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
522 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
523 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
524 /* find define for this maxpathcomponent */
526 name_len++; /* trailing null */
528 } else { /* BB improve the check for buffer overruns BB */
529 name_len = strnlen(name, 530);
530 name_len++; /* trailing null */
531 strncpy(pSMB->DirName, name, name_len);
534 pSMB->ByteCount = name_len + 1 /* for buf format */ ;
535 pSMB->BufferFormat = 0x04;
536 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
537 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
538 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
539 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
541 cFYI(1, ("Error in Mkdir = %d", rc));
543 #ifdef CONFIG_CIFS_STATS
545 atomic_inc(&tcon->num_mkdirs);
549 cifs_buf_release(pSMB);
556 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
557 const char *fileName, const int openDisposition,
558 const int access_flags, const int create_options, __u16 * netfid,
559 int *pOplock, FILE_ALL_INFO * pfile_info,
560 const struct nls_table *nls_codepage)
563 OPEN_REQ *pSMB = NULL;
564 OPEN_RSP *pSMBr = NULL;
569 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
574 pSMB->AndXCommand = 0xFF; /* none */
576 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
577 pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
579 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
581 /* find define for this maxpathcomponent */
583 name_len++; /* trailing null */
585 pSMB->NameLength = cpu_to_le16(name_len);
586 } else { /* BB improve the check for buffer overruns BB */
587 pSMB->ByteCount = 0; /* no pad */
588 name_len = strnlen(fileName, 530);
589 name_len++; /* trailing null */
590 pSMB->NameLength = cpu_to_le16(name_len);
591 strncpy(pSMB->fileName, fileName, name_len);
593 if (*pOplock & REQ_OPLOCK)
594 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
595 else if (*pOplock & REQ_BATCHOPLOCK) {
596 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
598 pSMB->DesiredAccess = cpu_to_le32(access_flags);
599 pSMB->AllocationSize = 0;
600 pSMB->FileAttributes = ATTR_NORMAL;
601 /* XP does not handle ATTR_POSIX_SEMANTICS */
602 /* but it helps speed up case sensitive checks for other
603 servers such as Samba */
604 if (tcon->ses->capabilities & CAP_UNIX)
605 pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
607 /* if ((omode & S_IWUGO) == 0)
608 pSMB->FileAttributes |= ATTR_READONLY;*/
609 /* Above line causes problems due to vfs splitting create into two
610 pieces - need to set mode after file created not while it is
612 pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
613 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
614 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
615 pSMB->CreateOptions = cpu_to_le32(create_options);
616 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
617 pSMB->SecurityFlags =
618 cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
620 pSMB->ByteCount += name_len;
621 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
623 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
624 /* long_op set to 1 to allow for oplock break timeouts */
625 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
626 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
628 cFYI(1, ("Error in Open = %d", rc));
630 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
631 *netfid = pSMBr->Fid; /* cifs fid stays in le */
632 /* Let caller know file was created so we can set the mode. */
633 /* Do we care about the CreateAction in any other cases? */
634 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
635 *pOplock |= CIFS_CREATE_ACTION;
637 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
638 36 /* CreationTime to Attributes */);
639 /* the file_info buf is endian converted by caller */
640 pfile_info->AllocationSize = pSMBr->AllocationSize;
641 pfile_info->EndOfFile = pSMBr->EndOfFile;
642 pfile_info->NumberOfLinks = cpu_to_le32(1);
645 #ifdef CONFIG_CIFS_STATS
646 atomic_inc(&tcon->num_opens);
650 cifs_buf_release(pSMB);
656 /* If no buffer passed in, then caller wants to do the copy
657 as in the case of readpages so the SMB buffer must be
658 freed by the caller */
661 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
662 const int netfid, const unsigned int count,
663 const __u64 lseek, unsigned int *nbytes, char **buf)
666 READ_REQ *pSMB = NULL;
667 READ_RSP *pSMBr = NULL;
668 char *pReadData = NULL;
672 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
677 /* tcon and ses pointer are checked in smb_init */
678 if (tcon->ses->server == NULL)
679 return -ECONNABORTED;
681 pSMB->AndXCommand = 0xFF; /* none */
683 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
684 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
686 pSMB->MaxCount = cpu_to_le16(count);
687 pSMB->MaxCountHigh = 0;
688 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
690 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
691 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
693 cERROR(1, ("Send error in read = %d", rc));
695 pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
696 *nbytes = pSMBr->DataLength;
697 /*check that DataLength would not go beyond end of SMB */
698 if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
699 || (pSMBr->DataLength > count)) {
700 cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
705 (char *) (&pSMBr->hdr.Protocol) +
706 le16_to_cpu(pSMBr->DataOffset);
707 /* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
708 cERROR(1,("Faulting on read rc = %d",rc));
710 }*/ /* can not use copy_to_user when using page cache*/
712 memcpy(*buf,pReadData,pSMBr->DataLength);
717 cifs_buf_release(pSMB);
722 /* Note: On -EAGAIN error only caller can retry on handle based calls
723 since file handle passed in no longer valid */
728 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
729 const int netfid, const unsigned int count,
730 const __u64 offset, unsigned int *nbytes, const char *buf,
734 WRITE_REQ *pSMB = NULL;
735 WRITE_RSP *pSMBr = NULL;
738 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
742 /* tcon and ses pointer are checked in smb_init */
743 if (tcon->ses->server == NULL)
744 return -ECONNABORTED;
746 pSMB->AndXCommand = 0xFF; /* none */
748 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
749 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
751 if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
752 pSMB->DataLengthLow =
753 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
755 pSMB->DataLengthLow = count;
756 pSMB->DataLengthHigh = 0;
758 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
760 memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
762 pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
763 pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
764 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
765 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
767 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
768 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
770 cFYI(1, ("Send error in write = %d", rc));
773 *nbytes = le16_to_cpu(pSMBr->Count);
776 cifs_buf_release(pSMB);
778 /* Note: On -EAGAIN error only caller can retry on handle based calls
779 since file handle passed in no longer valid */
785 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
786 const __u16 smb_file_id, const __u64 len,
787 const __u64 offset, const __u32 numUnlock,
788 const __u32 numLock, const __u8 lockType, const int waitFlag)
791 LOCK_REQ *pSMB = NULL;
792 LOCK_RSP *pSMBr = NULL;
797 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
798 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
803 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
804 timeout = -1; /* no response expected */
806 } else if (waitFlag == TRUE) {
807 timeout = 3; /* blocking operation, no timeout */
808 pSMB->Timeout = -1; /* blocking - do not time out */
813 pSMB->NumberOfLocks = cpu_to_le32(numLock);
814 pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
815 pSMB->LockType = lockType;
816 pSMB->AndXCommand = 0xFF; /* none */
817 pSMB->Fid = smb_file_id; /* netfid stays le */
819 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
820 temp = cpu_to_le64(len);
821 pSMB->Locks[0].LengthLow = (__u32)(len & 0xFFFFFFFF);
822 pSMB->Locks[0].LengthHigh = (__u32)(len>>32);
823 temp = cpu_to_le64(offset);
824 pSMB->Locks[0].OffsetLow = (__u32)(offset & 0xFFFFFFFF);
825 pSMB->Locks[0].OffsetHigh = (__u32)(offset>>32);
826 pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
827 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
828 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
830 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
831 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
834 cFYI(1, ("Send error in Lock = %d", rc));
837 cifs_buf_release(pSMB);
839 /* Note: On -EAGAIN error only caller can retry on handle based calls
840 since file handle passed in no longer valid */
845 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
848 CLOSE_REQ *pSMB = NULL;
849 CLOSE_RSP *pSMBr = NULL;
851 cFYI(1, ("In CIFSSMBClose"));
853 /* do not retry on dead session on close */
854 rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
861 pSMB->FileID = (__u16) smb_file_id;
862 pSMB->LastWriteTime = 0;
864 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
865 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
868 /* EINTR is expected when user ctl-c to kill app */
869 cERROR(1, ("Send error in Close = %d", rc));
873 cifs_buf_release(pSMB);
875 /* Since session is dead, file will be closed on server already */
883 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
884 const char *fromName, const char *toName,
885 const struct nls_table *nls_codepage)
888 RENAME_REQ *pSMB = NULL;
889 RENAME_RSP *pSMBr = NULL;
891 int name_len, name_len2;
893 cFYI(1, ("In CIFSSMBRename"));
895 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
900 pSMB->BufferFormat = 0x04;
901 pSMB->SearchAttributes =
902 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
905 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
907 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
908 /* find define for this maxpathcomponent */
910 name_len++; /* trailing null */
912 pSMB->OldFileName[name_len] = 0x04; /* pad */
913 /* protocol requires ASCII signature byte on Unicode string */
914 pSMB->OldFileName[name_len + 1] = 0x00;
916 cifs_strtoUCS((wchar_t *) & pSMB->
917 OldFileName[name_len + 2], toName, 530,
919 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
920 name_len2 *= 2; /* convert to bytes */
921 } else { /* BB improve the check for buffer overruns BB */
922 name_len = strnlen(fromName, 530);
923 name_len++; /* trailing null */
924 strncpy(pSMB->OldFileName, fromName, name_len);
925 name_len2 = strnlen(toName, 530);
926 name_len2++; /* trailing null */
927 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
928 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
929 name_len2++; /* trailing null */
930 name_len2++; /* signature byte */
933 pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
934 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
935 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
937 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
940 cFYI(1, ("Send error in rename = %d", rc));
943 cifs_buf_release(pSMB);
951 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
952 int netfid, char * target_name, const struct nls_table * nls_codepage)
954 struct smb_com_transaction2_sfi_req *pSMB = NULL;
955 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
956 struct set_file_rename * rename_info;
958 char dummy_string[30];
960 int bytes_returned = 0;
963 cFYI(1, ("Rename to File by handle"));
964 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
969 pSMB->ParameterCount = 6;
970 pSMB->MaxSetupCount = 0;
975 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
977 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
979 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
980 rename_info = (struct set_file_rename *) data_offset;
981 pSMB->MaxParameterCount = cpu_to_le16(2);
982 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
983 pSMB->SetupCount = 1;
985 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
986 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
987 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
988 pSMB->TotalParameterCount = pSMB->ParameterCount;
989 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
990 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
991 /* construct random name ".cifs_tmp<inodenum><mid>" */
992 rename_info->overwrite = cpu_to_le32(1);
993 rename_info->root_fid = 0;
994 /* unicode only call */
995 if(target_name == NULL) {
996 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
997 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
999 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
1001 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1002 pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1003 pSMB->ByteCount += pSMB->DataCount;
1004 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1005 pSMB->TotalDataCount = pSMB->DataCount;
1007 pSMB->InformationLevel =
1008 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1009 pSMB->Reserved4 = 0;
1010 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1011 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1012 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1013 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1015 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1019 cifs_buf_release(pSMB);
1021 /* Note: On -EAGAIN error only caller can retry on handle based calls
1022 since file handle passed in no longer valid */
1028 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1029 const __u16 target_tid, const char *toName, const int flags,
1030 const struct nls_table *nls_codepage)
1033 COPY_REQ *pSMB = NULL;
1034 COPY_RSP *pSMBr = NULL;
1036 int name_len, name_len2;
1038 cFYI(1, ("In CIFSSMBCopy"));
1040 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1045 pSMB->BufferFormat = 0x04;
1046 pSMB->Tid2 = target_tid;
1048 if(flags & COPY_TREE)
1049 pSMB->Flags |= COPY_TREE;
1050 pSMB->Flags = cpu_to_le16(pSMB->Flags);
1052 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1053 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
1055 530 /* find define for this maxpathcomponent */,
1057 name_len++; /* trailing null */
1059 pSMB->OldFileName[name_len] = 0x04; /* pad */
1060 /* protocol requires ASCII signature byte on Unicode string */
1061 pSMB->OldFileName[name_len + 1] = 0x00;
1062 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1063 OldFileName[name_len + 2], toName, 530,
1065 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1066 name_len2 *= 2; /* convert to bytes */
1067 } else { /* BB improve the check for buffer overruns BB */
1068 name_len = strnlen(fromName, 530);
1069 name_len++; /* trailing null */
1070 strncpy(pSMB->OldFileName, fromName, name_len);
1071 name_len2 = strnlen(toName, 530);
1072 name_len2++; /* trailing null */
1073 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1074 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1075 name_len2++; /* trailing null */
1076 name_len2++; /* signature byte */
1079 pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
1080 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1081 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1083 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1084 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1086 cFYI(1, ("Send error in copy = %d with %d files copied",
1087 rc, pSMBr->CopyCount));
1090 cifs_buf_release(pSMB);
1099 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1100 const char *fromName, const char *toName,
1101 const struct nls_table *nls_codepage)
1103 TRANSACTION2_SPI_REQ *pSMB = NULL;
1104 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1107 int name_len_target;
1109 int bytes_returned = 0;
1111 cFYI(1, ("In Symlink Unix style"));
1113 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1118 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1120 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
1121 /* find define for this maxpathcomponent */
1123 name_len++; /* trailing null */
1126 } else { /* BB improve the check for buffer overruns BB */
1127 name_len = strnlen(fromName, 530);
1128 name_len++; /* trailing null */
1129 strncpy(pSMB->FileName, fromName, name_len);
1131 pSMB->ParameterCount = 6 + name_len;
1132 pSMB->MaxSetupCount = 0;
1136 pSMB->Reserved2 = 0;
1137 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1138 InformationLevel) - 4;
1139 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1141 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1142 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1144 cifs_strtoUCS((wchar_t *) data_offset, toName, 530
1145 /* find define for this maxpathcomponent */
1147 name_len_target++; /* trailing null */
1148 name_len_target *= 2;
1149 } else { /* BB improve the check for buffer overruns BB */
1150 name_len_target = strnlen(toName, 530);
1151 name_len_target++; /* trailing null */
1152 strncpy(data_offset, toName, name_len_target);
1155 pSMB->DataCount = name_len_target;
1156 pSMB->MaxParameterCount = cpu_to_le16(2);
1157 /* BB find exact max on data count below from sess */
1158 pSMB->MaxDataCount = cpu_to_le16(1000);
1159 pSMB->SetupCount = 1;
1160 pSMB->Reserved3 = 0;
1161 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1162 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
1163 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1164 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1165 pSMB->TotalDataCount = pSMB->DataCount;
1166 pSMB->TotalParameterCount = pSMB->ParameterCount;
1167 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1168 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1169 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1170 pSMB->Reserved4 = 0;
1171 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1172 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1173 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1174 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1177 ("Send error in SetPathInfo (create symlink) = %d",
1182 cifs_buf_release(pSMB);
1185 goto createSymLinkRetry;
1191 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1192 const char *fromName, const char *toName,
1193 const struct nls_table *nls_codepage)
1195 TRANSACTION2_SPI_REQ *pSMB = NULL;
1196 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1199 int name_len_target;
1201 int bytes_returned = 0;
1203 cFYI(1, ("In Create Hard link Unix style"));
1204 createHardLinkRetry:
1205 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1210 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1211 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
1212 /* find define for this maxpathcomponent */
1214 name_len++; /* trailing null */
1217 } else { /* BB improve the check for buffer overruns BB */
1218 name_len = strnlen(toName, 530);
1219 name_len++; /* trailing null */
1220 strncpy(pSMB->FileName, toName, name_len);
1222 pSMB->ParameterCount = 6 + name_len;
1223 pSMB->MaxSetupCount = 0;
1227 pSMB->Reserved2 = 0;
1228 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1229 InformationLevel) - 4;
1230 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1232 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1233 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1235 cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
1236 /* find define for this maxpathcomponent */
1238 name_len_target++; /* trailing null */
1239 name_len_target *= 2;
1240 } else { /* BB improve the check for buffer overruns BB */
1241 name_len_target = strnlen(fromName, 530);
1242 name_len_target++; /* trailing null */
1243 strncpy(data_offset, fromName, name_len_target);
1246 pSMB->DataCount = name_len_target;
1247 pSMB->MaxParameterCount = cpu_to_le16(2);
1248 /* BB find exact max on data count below from sess*/
1249 pSMB->MaxDataCount = cpu_to_le16(1000);
1250 pSMB->SetupCount = 1;
1251 pSMB->Reserved3 = 0;
1252 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1253 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
1254 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1255 pSMB->TotalParameterCount = pSMB->ParameterCount;
1256 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1257 pSMB->TotalDataCount = pSMB->DataCount;
1258 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1259 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1260 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1261 pSMB->Reserved4 = 0;
1262 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1263 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1264 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1265 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1267 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1271 cifs_buf_release(pSMB);
1273 goto createHardLinkRetry;
1279 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1280 const char *fromName, const char *toName,
1281 const struct nls_table *nls_codepage)
1284 NT_RENAME_REQ *pSMB = NULL;
1285 RENAME_RSP *pSMBr = NULL;
1287 int name_len, name_len2;
1289 cFYI(1, ("In CIFSCreateHardLink"));
1290 winCreateHardLinkRetry:
1292 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1297 pSMB->SearchAttributes =
1298 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1300 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1301 pSMB->ClusterCount = 0;
1303 pSMB->BufferFormat = 0x04;
1305 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1307 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
1308 /* find define for this maxpathcomponent */
1310 name_len++; /* trailing null */
1312 pSMB->OldFileName[name_len] = 0; /* pad */
1313 pSMB->OldFileName[name_len + 1] = 0x04;
1315 cifs_strtoUCS((wchar_t *) & pSMB->
1316 OldFileName[name_len + 2], toName, 530,
1318 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1319 name_len2 *= 2; /* convert to bytes */
1320 } else { /* BB improve the check for buffer overruns BB */
1321 name_len = strnlen(fromName, 530);
1322 name_len++; /* trailing null */
1323 strncpy(pSMB->OldFileName, fromName, name_len);
1324 name_len2 = strnlen(toName, 530);
1325 name_len2++; /* trailing null */
1326 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1327 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1328 name_len2++; /* trailing null */
1329 name_len2++; /* signature byte */
1332 pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
1333 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1334 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1336 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1337 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1339 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1342 cifs_buf_release(pSMB);
1344 goto winCreateHardLinkRetry;
1350 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1351 const unsigned char *searchName,
1352 char *symlinkinfo, const int buflen,
1353 const struct nls_table *nls_codepage)
1355 /* SMB_QUERY_FILE_UNIX_LINK */
1356 TRANSACTION2_QPI_REQ *pSMB = NULL;
1357 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1362 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1365 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1370 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1372 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1373 /* find define for this maxpathcomponent */
1375 name_len++; /* trailing null */
1377 } else { /* BB improve the check for buffer overruns BB */
1378 name_len = strnlen(searchName, 530);
1379 name_len++; /* trailing null */
1380 strncpy(pSMB->FileName, searchName, name_len);
1383 pSMB->TotalParameterCount =
1384 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1385 pSMB->TotalDataCount = 0;
1386 pSMB->MaxParameterCount = cpu_to_le16(2);
1387 /* BB find exact max data count below from sess structure BB */
1388 pSMB->MaxDataCount = cpu_to_le16(4000);
1389 pSMB->MaxSetupCount = 0;
1393 pSMB->Reserved2 = 0;
1394 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1395 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1396 pSMB->DataCount = 0;
1397 pSMB->DataOffset = 0;
1398 pSMB->SetupCount = 1;
1399 pSMB->Reserved3 = 0;
1400 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1401 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1402 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1403 pSMB->ParameterCount = pSMB->TotalParameterCount;
1404 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1405 pSMB->Reserved4 = 0;
1406 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1407 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1409 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1410 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1412 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1413 } else { /* decode response */
1414 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1415 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1416 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1417 /* BB also check enough total bytes returned */
1418 rc = -EIO; /* bad smb */
1420 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1421 name_len = UniStrnlen((wchar_t *) ((char *)
1422 &pSMBr->hdr.Protocol +pSMBr->DataOffset),
1423 min_t(const int, buflen,pSMBr->DataCount) / 2);
1424 cifs_strfromUCS_le(symlinkinfo,
1425 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1427 name_len, nls_codepage);
1429 strncpy(symlinkinfo,
1430 (char *) &pSMBr->hdr.Protocol +
1432 min_t(const int, buflen, pSMBr->DataCount));
1434 symlinkinfo[buflen] = 0;
1435 /* just in case so calling code does not go off the end of buffer */
1439 cifs_buf_release(pSMB);
1441 goto querySymLinkRetry;
1448 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1449 const unsigned char *searchName,
1450 char *symlinkinfo, const int buflen,__u16 fid,
1451 const struct nls_table *nls_codepage)
1456 struct smb_com_transaction_ioctl_req * pSMB;
1457 struct smb_com_transaction_ioctl_rsp * pSMBr;
1459 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1460 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1465 pSMB->TotalParameterCount = 0 ;
1466 pSMB->TotalDataCount = 0;
1467 pSMB->MaxParameterCount = cpu_to_le16(2);
1468 /* BB find exact data count max from sess structure BB */
1469 pSMB->MaxDataCount = cpu_to_le16(4000);
1470 pSMB->MaxSetupCount = 4;
1472 pSMB->ParameterOffset = 0;
1473 pSMB->DataCount = 0;
1474 pSMB->DataOffset = 0;
1475 pSMB->SetupCount = 4;
1476 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1477 pSMB->ParameterCount = pSMB->TotalParameterCount;
1478 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1479 pSMB->IsFsctl = 1; /* FSCTL */
1480 pSMB->IsRootFlag = 0;
1481 pSMB->Fid = fid; /* file handle always le */
1482 pSMB->ByteCount = 0;
1484 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1485 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1487 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1488 } else { /* decode response */
1489 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1490 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1491 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1492 /* BB also check enough total bytes returned */
1493 rc = -EIO; /* bad smb */
1495 if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
1496 /* could also validate reparse tag && better check name length */
1497 struct reparse_data * reparse_buf = (struct reparse_data *)
1498 ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
1499 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1500 name_len = UniStrnlen((wchar_t *)
1501 (reparse_buf->LinkNamesBuf +
1502 reparse_buf->TargetNameOffset),
1503 min(buflen/2, reparse_buf->TargetNameLen / 2));
1504 cifs_strfromUCS_le(symlinkinfo,
1505 (wchar_t *) (reparse_buf->LinkNamesBuf +
1506 reparse_buf->TargetNameOffset),
1507 name_len, nls_codepage);
1508 } else { /* ASCII names */
1509 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1510 reparse_buf->TargetNameOffset,
1511 min_t(const int, buflen, reparse_buf->TargetNameLen));
1515 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1517 symlinkinfo[buflen] = 0; /* just in case so the caller
1518 does not go off the end of the buffer */
1519 cFYI(1,("readlink result - %s ",symlinkinfo));
1523 cifs_buf_release(pSMB);
1525 /* Note: On -EAGAIN error only caller can retry on handle based calls
1526 since file handle passed in no longer valid */
1532 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1533 const unsigned char *searchName,
1534 FILE_ALL_INFO * pFindData,
1535 const struct nls_table *nls_codepage)
1537 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1538 TRANSACTION2_QPI_REQ *pSMB = NULL;
1539 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1544 cFYI(1, ("In QPathInfo path %s", searchName));
1546 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1551 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1553 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1554 /* find define for this maxpathcomponent */
1556 name_len++; /* trailing null */
1558 } else { /* BB improve the check for buffer overruns BB */
1559 name_len = strnlen(searchName, 530);
1560 name_len++; /* trailing null */
1561 strncpy(pSMB->FileName, searchName, name_len);
1564 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1565 name_len /* includes null */ ;
1566 pSMB->TotalDataCount = 0;
1567 pSMB->MaxParameterCount = cpu_to_le16(2);
1568 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1569 pSMB->MaxSetupCount = 0;
1573 pSMB->Reserved2 = 0;
1574 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1575 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1576 pSMB->DataCount = 0;
1577 pSMB->DataOffset = 0;
1578 pSMB->SetupCount = 1;
1579 pSMB->Reserved3 = 0;
1580 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1581 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1582 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1583 pSMB->ParameterCount = pSMB->TotalParameterCount;
1584 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1585 pSMB->Reserved4 = 0;
1586 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1587 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1589 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1590 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1592 cFYI(1, ("Send error in QPathInfo = %d", rc));
1593 } else { /* decode response */
1594 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1595 /* BB also check enough total bytes returned */
1596 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1597 rc = -EIO; /* bad smb */
1598 else if (pFindData){
1599 memcpy((char *) pFindData,
1600 (char *) &pSMBr->hdr.Protocol +
1601 pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
1606 cifs_buf_release(pSMB);
1608 goto QPathInfoRetry;
1614 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1615 const unsigned char *searchName,
1616 FILE_UNIX_BASIC_INFO * pFindData,
1617 const struct nls_table *nls_codepage)
1619 /* SMB_QUERY_FILE_UNIX_BASIC */
1620 TRANSACTION2_QPI_REQ *pSMB = NULL;
1621 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1623 int bytes_returned = 0;
1626 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1628 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1633 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1635 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1636 /* find define for this maxpathcomponent */
1638 name_len++; /* trailing null */
1640 } else { /* BB improve the check for buffer overruns BB */
1641 name_len = strnlen(searchName, 530);
1642 name_len++; /* trailing null */
1643 strncpy(pSMB->FileName, searchName, name_len);
1646 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1647 name_len /* includes null */ ;
1648 pSMB->TotalDataCount = 0;
1649 pSMB->MaxParameterCount = cpu_to_le16(2);
1650 /* BB find exact max SMB PDU from sess structure BB */
1651 pSMB->MaxDataCount = cpu_to_le16(4000);
1652 pSMB->MaxSetupCount = 0;
1656 pSMB->Reserved2 = 0;
1657 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1658 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1659 pSMB->DataCount = 0;
1660 pSMB->DataOffset = 0;
1661 pSMB->SetupCount = 1;
1662 pSMB->Reserved3 = 0;
1663 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1664 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1665 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1666 pSMB->ParameterCount = pSMB->TotalParameterCount;
1667 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1668 pSMB->Reserved4 = 0;
1669 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1670 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1672 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1673 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1675 cFYI(1, ("Send error in QPathInfo = %d", rc));
1676 } else { /* decode response */
1677 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1678 /* BB also check if enough total bytes returned */
1679 if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
1680 (pSMBr->DataOffset > 512) ||
1681 (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
1682 cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
1683 (int)pSMBr->DataOffset,bytes_returned));
1684 rc = -EIO; /* bad smb */
1686 memcpy((char *) pFindData,
1687 (char *) &pSMBr->hdr.Protocol +
1689 sizeof (FILE_UNIX_BASIC_INFO));
1693 cifs_buf_release(pSMB);
1695 goto UnixQPathInfoRetry;
1701 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1702 const char *searchName, FILE_ALL_INFO * findData,
1703 const struct nls_table *nls_codepage)
1705 /* level 257 SMB_ */
1706 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1707 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1712 cFYI(1, ("In FindUnique"));
1714 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1719 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1721 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1722 /* find define for this maxpathcomponent */
1724 name_len++; /* trailing null */
1726 } else { /* BB improve the check for buffer overruns BB */
1727 name_len = strnlen(searchName, 530);
1728 name_len++; /* trailing null */
1729 strncpy(pSMB->FileName, searchName, name_len);
1732 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1733 pSMB->TotalDataCount = 0; /* no EAs */
1734 pSMB->MaxParameterCount = cpu_to_le16(2);
1735 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1736 pSMB->MaxSetupCount = 0;
1740 pSMB->Reserved2 = 0;
1741 pSMB->ParameterOffset = cpu_to_le16(
1742 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1743 pSMB->DataCount = 0;
1744 pSMB->DataOffset = 0;
1745 pSMB->SetupCount = 1; /* one byte, no need to le convert */
1746 pSMB->Reserved3 = 0;
1747 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1748 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1749 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
1750 pSMB->ParameterCount = pSMB->TotalParameterCount;
1751 pSMB->SearchAttributes =
1752 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1754 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
1755 pSMB->SearchFlags = cpu_to_le16(1);
1756 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1757 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
1758 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1759 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1761 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1762 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1765 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1766 } else { /* decode response */
1771 cifs_buf_release(pSMB);
1773 goto findUniqueRetry;
1779 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1780 const char *searchName, FILE_DIRECTORY_INFO * findData,
1781 T2_FFIRST_RSP_PARMS * findParms,
1782 const struct nls_table *nls_codepage, int *pUnicodeFlag,
1785 /* level 257 SMB_ */
1786 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1787 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1788 char *response_data;
1793 cFYI(1, ("In FindFirst"));
1795 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1800 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1802 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1803 /* find define for this maxpathcomponent */
1805 name_len++; /* trailing null */
1807 } else { /* BB improve the check for buffer overruns BB */
1808 name_len = strnlen(searchName, 530);
1809 name_len++; /* trailing null */
1810 strncpy(pSMB->FileName, searchName, name_len);
1813 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1814 pSMB->TotalDataCount = 0; /* no EAs */
1815 pSMB->MaxParameterCount = cpu_to_le16(10);
1816 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1817 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1818 pSMB->MaxSetupCount = 0;
1822 pSMB->Reserved2 = 0;
1823 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1824 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1825 pSMB->ParameterCount = pSMB->TotalParameterCount;
1826 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
1827 smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1828 pSMB->DataCount = 0;
1829 pSMB->DataOffset = 0;
1830 pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
1831 pSMB->Reserved3 = 0;
1832 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1833 pSMB->SearchAttributes =
1834 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1836 pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
1837 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1839 /* test for Unix extensions */
1840 if (tcon->ses->capabilities & CAP_UNIX) {
1841 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1844 pSMB->InformationLevel =
1845 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1848 pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
1849 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1850 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1852 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1853 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1855 if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1856 cFYI(1, ("Error in FindFirst = %d", rc));
1857 } else { /* decode response */
1858 /* BB add safety checks for these memcpys */
1859 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1860 *pUnicodeFlag = TRUE;
1862 *pUnicodeFlag = FALSE;
1864 (char *) &pSMBr->hdr.Protocol +
1865 le16_to_cpu(pSMBr->ParameterOffset),
1866 sizeof (T2_FFIRST_RSP_PARMS));
1867 /* search handle can stay LE and EAoffset not needed so not converted */
1868 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1869 findParms->LastNameOffset =
1870 le16_to_cpu(findParms->LastNameOffset);
1871 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1873 (char *) &pSMBr->hdr.Protocol +
1874 le16_to_cpu(pSMBr->DataOffset);
1875 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1878 cifs_buf_release(pSMB);
1881 goto findFirstRetry;
1887 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1888 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1889 const __u16 searchHandle, char * resume_file_name, int name_len,
1890 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1892 /* level 257 SMB_ */
1893 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1894 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1895 char *response_data;
1899 cFYI(1, ("In FindNext"));
1901 if(resume_file_name == NULL) {
1904 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1909 pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
1910 pSMB->TotalDataCount = 0; /* no EAs */
1911 pSMB->MaxParameterCount = cpu_to_le16(8);
1912 pSMB->MaxDataCount =
1913 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1914 pSMB->MaxSetupCount = 0;
1918 pSMB->Reserved2 = 0;
1919 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1920 struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1921 pSMB->DataCount = 0;
1922 pSMB->DataOffset = 0;
1923 pSMB->SetupCount = 1;
1924 pSMB->Reserved3 = 0;
1925 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1926 pSMB->SearchHandle = searchHandle; /* always kept as le */
1927 findParms->SearchCount = 0; /* set to zero in case of error */
1929 cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1930 /* test for Unix extensions */
1931 if (tcon->ses->capabilities & CAP_UNIX) {
1932 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1935 pSMB->InformationLevel =
1936 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1939 pSMB->ResumeKey = resume_key;
1941 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1942 /* BB add check to make sure we do not cross end of smb */
1943 if(name_len < CIFS_MAX_MSGSIZE) {
1944 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1945 pSMB->ByteCount += name_len;
1947 pSMB->TotalParameterCount += name_len;
1948 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1949 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1950 pSMB->ParameterCount = pSMB->TotalParameterCount;
1951 /* BB improve error handling here */
1952 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1953 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1955 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1956 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1960 rc = 0; /* search probably was closed at end of search above */
1962 cFYI(1, ("FindNext returned = %d", rc));
1963 } else { /* decode response */
1964 /* BB add safety checks for these memcpys */
1965 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1966 *pUnicodeFlag = TRUE;
1968 *pUnicodeFlag = FALSE;
1970 (char *) &pSMBr->hdr.Protocol +
1971 le16_to_cpu(pSMBr->ParameterOffset),
1972 sizeof (T2_FNEXT_RSP_PARMS));
1973 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1974 findParms->LastNameOffset =
1975 le16_to_cpu(findParms->LastNameOffset);
1976 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1978 (char *) &pSMBr->hdr.Protocol +
1979 le16_to_cpu(pSMBr->DataOffset);
1980 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1983 cifs_buf_release(pSMB);
1985 /* Note: On -EAGAIN error only caller can retry on handle based calls
1986 since file handle passed in no longer valid */
1992 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
1995 FINDCLOSE_REQ *pSMB = NULL;
1996 CLOSE_RSP *pSMBr = NULL;
1999 cFYI(1, ("In CIFSSMBFindClose"));
2000 rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
2002 /* no sense returning error if session restarted
2003 file handle has been closed */
2009 pSMB->FileID = searchHandle;
2010 pSMB->ByteCount = 0;
2011 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2012 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2014 cERROR(1, ("Send error in FindClose = %d", rc));
2017 cifs_buf_release(pSMB);
2019 /* Since session is dead, search handle closed on server already */
2027 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2028 const unsigned char *searchName,
2029 unsigned char **targetUNCs,
2030 unsigned int *number_of_UNC_in_array,
2031 const struct nls_table *nls_codepage)
2033 /* TRANS2_GET_DFS_REFERRAL */
2034 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2035 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2036 struct dfs_referral_level_3 * referrals = NULL;
2042 *number_of_UNC_in_array = 0;
2045 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2049 rc = smb_init(SMB_COM_TRANSACTION2, 15, 0, (void **) &pSMB,
2054 pSMB->hdr.Tid = ses->ipc_tid;
2055 pSMB->hdr.Uid = ses->Suid;
2056 if (ses->capabilities & CAP_STATUS32) {
2057 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2059 if (ses->capabilities & CAP_DFS) {
2060 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2063 if (ses->capabilities & CAP_UNICODE) {
2064 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2066 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2068 /* find define for this maxpathcomponent */
2070 name_len++; /* trailing null */
2072 } else { /* BB improve the check for buffer overruns BB */
2073 name_len = strnlen(searchName, 530);
2074 name_len++; /* trailing null */
2075 strncpy(pSMB->RequestFileName, searchName, name_len);
2078 pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
2079 pSMB->TotalDataCount = 0;
2080 pSMB->DataCount = 0;
2081 pSMB->DataOffset = 0;
2082 pSMB->MaxParameterCount = 0;
2083 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2084 pSMB->MaxSetupCount = 0;
2088 pSMB->Reserved2 = 0;
2089 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2090 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2091 pSMB->SetupCount = 1;
2092 pSMB->Reserved3 = 0;
2093 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2094 pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
2095 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2096 pSMB->TotalParameterCount = pSMB->ParameterCount;
2097 pSMB->MaxReferralLevel = cpu_to_le16(3);
2098 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2099 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2101 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2102 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2104 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2105 } else { /* decode response */
2106 /* BB Add logic to parse referrals here */
2107 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2108 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
2110 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2111 pSMBr->ByteCount, pSMBr->DataOffset));
2112 if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
2113 rc = -EIO; /* bad smb */
2116 (struct dfs_referral_level_3 *)
2117 (8 /* sizeof start of data block */ +
2119 (char *) &pSMBr->hdr.Protocol);
2120 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
2121 /* BB This field is actually two bytes in from start of
2122 data block so we could do safety check that DataBlock
2123 begins at address of pSMBr->NumberOfReferrals */
2124 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2126 /* BB Fix below so can return more than one referral */
2127 if(*number_of_UNC_in_array > 1)
2128 *number_of_UNC_in_array = 1;
2130 /* get the length of the strings describing refs */
2132 for(i=0;i<*number_of_UNC_in_array;i++) {
2133 /* make sure that DfsPathOffset not past end */
2134 referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
2135 if(referrals->DfsPathOffset > pSMBr->DataCount) {
2136 /* if invalid referral, stop here and do
2137 not try to copy any more */
2138 *number_of_UNC_in_array = i;
2141 temp = ((char *)referrals) + referrals->DfsPathOffset;
2143 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2144 name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
2146 name_len += strnlen(temp,pSMBr->DataCount);
2149 /* BB add check that referral pointer does not fall off end PDU */
2152 /* BB add check for name_len bigger than bcc */
2154 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2155 /* copy the ref strings */
2157 (struct dfs_referral_level_3 *)
2158 (8 /* sizeof data hdr */ +
2160 (char *) &pSMBr->hdr.Protocol);
2162 for(i=0;i<*number_of_UNC_in_array;i++) {
2163 temp = ((char *)referrals) + referrals->DfsPathOffset;
2164 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2165 cifs_strfromUCS_le(*targetUNCs,
2166 (wchar_t *) temp, name_len, nls_codepage);
2168 strncpy(*targetUNCs,temp,name_len);
2170 /* BB update target_uncs pointers */
2179 cifs_buf_release(pSMB);
2188 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2189 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2191 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2192 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2193 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2194 FILE_SYSTEM_INFO *response_data;
2196 int bytes_returned = 0;
2198 cFYI(1, ("In QFSInfo"));
2200 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2205 pSMB->TotalParameterCount = 2; /* level */
2206 pSMB->TotalDataCount = 0;
2207 pSMB->MaxParameterCount = cpu_to_le16(2);
2208 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2209 pSMB->MaxSetupCount = 0;
2213 pSMB->Reserved2 = 0;
2214 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2215 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2216 pSMB->ParameterCount = pSMB->TotalParameterCount;
2217 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2218 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2219 pSMB->DataCount = 0;
2220 pSMB->DataOffset = 0;
2221 pSMB->SetupCount = 1;
2222 pSMB->Reserved3 = 0;
2223 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2224 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2225 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2226 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2228 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2229 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2231 cERROR(1, ("Send error in QFSInfo = %d", rc));
2232 } else { /* decode response */
2233 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2235 ("Decoding qfsinfo response. BCC: %d Offset %d",
2236 pSMBr->ByteCount, pSMBr->DataOffset));
2237 if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
2238 rc = -EIO; /* bad smb */
2242 *) (((char *) &pSMBr->hdr.Protocol) +
2245 le32_to_cpu(response_data->BytesPerSector) *
2246 le32_to_cpu(response_data->
2247 SectorsPerAllocationUnit);
2249 le64_to_cpu(response_data->TotalAllocationUnits);
2250 FSData->f_bfree = FSData->f_bavail =
2251 le64_to_cpu(response_data->FreeAllocationUnits);
2253 ("Blocks: %lld Free: %lld Block size %ld",
2254 (unsigned long long)FSData->f_blocks,
2255 (unsigned long long)FSData->f_bfree,
2260 cifs_buf_release(pSMB);
2269 CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
2270 const struct nls_table *nls_codepage)
2272 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
2273 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2274 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2275 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
2277 int bytes_returned = 0;
2279 cFYI(1, ("In QFSAttributeInfo"));
2281 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2286 pSMB->TotalParameterCount = 2; /* level */
2287 pSMB->TotalDataCount = 0;
2288 pSMB->MaxParameterCount = cpu_to_le16(2);
2289 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2290 pSMB->MaxSetupCount = 0;
2294 pSMB->Reserved2 = 0;
2295 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2296 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2297 pSMB->ParameterCount = pSMB->TotalParameterCount;
2298 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2299 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2300 pSMB->DataCount = 0;
2301 pSMB->DataOffset = 0;
2302 pSMB->SetupCount = 1;
2303 pSMB->Reserved3 = 0;
2304 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2305 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
2306 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2307 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2309 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2310 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2312 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
2313 } else { /* decode response */
2314 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2315 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
2316 rc = -EIO; /* bad smb */
2319 (FILE_SYSTEM_ATTRIBUTE_INFO
2320 *) (((char *) &pSMBr->hdr.Protocol) +
2322 response_data->Attributes = le32_to_cpu(response_data->Attributes);
2323 response_data->MaxPathNameComponentLength =
2324 le32_to_cpu(response_data->MaxPathNameComponentLength);
2325 response_data->FileSystemNameLen =
2326 le32_to_cpu(response_data->FileSystemNameLen);
2327 memcpy(&tcon->fsAttrInfo, response_data,
2328 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
2332 cifs_buf_release(pSMB);
2335 goto QFSAttributeRetry;
2341 CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
2342 const struct nls_table *nls_codepage)
2344 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
2345 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2346 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2347 FILE_SYSTEM_DEVICE_INFO *response_data;
2349 int bytes_returned = 0;
2351 cFYI(1, ("In QFSDeviceInfo"));
2353 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2358 pSMB->TotalParameterCount = 2; /* level */
2359 pSMB->TotalDataCount = 0;
2360 pSMB->MaxParameterCount = cpu_to_le16(2);
2361 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2362 pSMB->MaxSetupCount = 0;
2366 pSMB->Reserved2 = 0;
2367 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2368 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2369 pSMB->ParameterCount = pSMB->TotalParameterCount;
2370 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2371 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2373 pSMB->DataCount = 0;
2374 pSMB->DataOffset = 0;
2375 pSMB->SetupCount = 1;
2376 pSMB->Reserved3 = 0;
2377 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2378 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
2379 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2380 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2382 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2383 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2385 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
2386 } else { /* decode response */
2387 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2388 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
2389 || (pSMBr->DataOffset > 512))
2390 rc = -EIO; /* bad smb */
2393 (FILE_SYSTEM_DEVICE_INFO
2394 *) (((char *) &pSMBr->hdr.Protocol) +
2396 response_data->DeviceType =
2397 le32_to_cpu(response_data->DeviceType);
2398 response_data->DeviceCharacteristics =
2399 le32_to_cpu(response_data->DeviceCharacteristics);
2400 memcpy(&tcon->fsDevInfo, response_data,
2401 sizeof (FILE_SYSTEM_DEVICE_INFO));
2405 cifs_buf_release(pSMB);
2408 goto QFSDeviceRetry;
2414 CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
2415 const struct nls_table *nls_codepage)
2417 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
2418 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2419 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2420 FILE_SYSTEM_UNIX_INFO *response_data;
2422 int bytes_returned = 0;
2424 cFYI(1, ("In QFSUnixInfo"));
2426 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2431 pSMB->ParameterCount = 2; /* level */
2432 pSMB->TotalDataCount = 0;
2433 pSMB->DataCount = 0;
2434 pSMB->DataOffset = 0;
2435 pSMB->MaxParameterCount = cpu_to_le16(2);
2436 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
2437 pSMB->MaxSetupCount = 0;
2441 pSMB->Reserved2 = 0;
2442 pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
2443 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2444 pSMB->TotalParameterCount = pSMB->ParameterCount;
2445 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
2446 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2447 pSMB->SetupCount = 1;
2448 pSMB->Reserved3 = 0;
2449 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2450 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2451 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2452 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2454 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2455 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2457 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2458 } else { /* decode response */
2459 pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
2460 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
2461 rc = -EIO; /* bad smb */
2464 (FILE_SYSTEM_UNIX_INFO
2465 *) (((char *) &pSMBr->hdr.Protocol) +
2467 response_data->MajorVersionNumber =
2468 le16_to_cpu(response_data->MajorVersionNumber);
2469 response_data->MinorVersionNumber =
2470 le16_to_cpu(response_data->MinorVersionNumber);
2471 response_data->Capability =
2472 le64_to_cpu(response_data->Capability);
2473 memcpy(&tcon->fsUnixInfo, response_data,
2474 sizeof (FILE_SYSTEM_UNIX_INFO));
2478 cifs_buf_release(pSMB);
2487 /* We can not use write of zero bytes trick to
2488 set file size due to need for large file support. Also note that
2489 this SetPathInfo is preferred to SetFileInfo based method in next
2490 routine which is only needed to work around a sharing violation bug
2491 in Samba which this routine can run into */
2494 CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
2495 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2497 struct smb_com_transaction2_spi_req *pSMB = NULL;
2498 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2499 struct file_end_of_file_info *parm_data;
2502 int bytes_returned = 0;
2504 cFYI(1, ("In SetEOF"));
2506 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2511 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2513 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2514 /* find define for this maxpathcomponent */
2516 name_len++; /* trailing null */
2518 } else { /* BB improve the check for buffer overruns BB */
2519 name_len = strnlen(fileName, 530);
2520 name_len++; /* trailing null */
2521 strncpy(pSMB->FileName, fileName, name_len);
2523 pSMB->ParameterCount = 6 + name_len;
2524 pSMB->DataCount = sizeof (struct file_end_of_file_info);
2525 pSMB->MaxParameterCount = cpu_to_le16(2);
2526 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2527 pSMB->MaxSetupCount = 0;
2531 pSMB->Reserved2 = 0;
2532 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2533 InformationLevel) - 4;
2534 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2536 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2537 pSMB->InformationLevel =
2538 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2540 pSMB->InformationLevel =
2541 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2542 } else /* Set File Size */ {
2543 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2544 pSMB->InformationLevel =
2545 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2547 pSMB->InformationLevel =
2548 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2552 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2554 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2555 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2556 pSMB->SetupCount = 1;
2557 pSMB->Reserved3 = 0;
2558 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2559 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2560 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2561 pSMB->TotalDataCount = pSMB->DataCount;
2562 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2563 pSMB->TotalParameterCount = pSMB->ParameterCount;
2564 pSMB->Reserved4 = 0;
2565 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2566 parm_data->FileSize = cpu_to_le64(size);
2567 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2568 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2569 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2571 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2575 cifs_buf_release(pSMB);
2584 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
2585 __u16 fid, __u32 pid_of_opener, int SetAllocation)
2587 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2588 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2590 struct file_end_of_file_info *parm_data;
2592 int bytes_returned = 0;
2595 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
2597 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2602 tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
2603 so network fid will be valid */
2604 pSMB->hdr.Pid = tmp & 0xFFFF;
2606 pSMB->hdr.PidHigh = tmp & 0xFFFF;
2608 pSMB->ParameterCount = 6;
2609 pSMB->MaxSetupCount = 0;
2613 pSMB->Reserved2 = 0;
2614 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
2616 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2618 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2620 pSMB->DataCount = sizeof(struct file_end_of_file_info);
2621 pSMB->MaxParameterCount = cpu_to_le16(2);
2622 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2623 pSMB->SetupCount = 1;
2624 pSMB->Reserved3 = 0;
2625 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2626 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2627 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2628 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2629 pSMB->TotalDataCount = pSMB->DataCount;
2630 pSMB->TotalParameterCount = pSMB->ParameterCount;
2631 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2633 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2635 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
2636 parm_data->FileSize = cpu_to_le64(size);
2639 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2640 pSMB->InformationLevel =
2641 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2643 pSMB->InformationLevel =
2644 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2645 } else /* Set File Size */ {
2646 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2647 pSMB->InformationLevel =
2648 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2650 pSMB->InformationLevel =
2651 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2653 pSMB->Reserved4 = 0;
2654 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2655 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2656 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2657 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2660 ("Send error in SetFileInfo (SetFileSize) = %d",
2665 cifs_buf_release(pSMB);
2667 /* Note: On -EAGAIN error only caller can retry on handle based calls
2668 since file handle passed in no longer valid */
2674 CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
2675 FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
2677 TRANSACTION2_SPI_REQ *pSMB = NULL;
2678 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2681 int bytes_returned = 0;
2684 cFYI(1, ("In SetTimes"));
2687 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2692 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2694 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2695 /* find define for this maxpathcomponent */
2697 name_len++; /* trailing null */
2699 } else { /* BB improve the check for buffer overruns BB */
2700 name_len = strnlen(fileName, 530);
2701 name_len++; /* trailing null */
2702 strncpy(pSMB->FileName, fileName, name_len);
2705 pSMB->ParameterCount = 6 + name_len;
2706 pSMB->DataCount = sizeof (FILE_BASIC_INFO);
2707 pSMB->MaxParameterCount = cpu_to_le16(2);
2708 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2709 pSMB->MaxSetupCount = 0;
2713 pSMB->Reserved2 = 0;
2714 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2715 InformationLevel) - 4;
2716 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2717 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2718 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2719 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2720 pSMB->SetupCount = 1;
2721 pSMB->Reserved3 = 0;
2722 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2723 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2725 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2726 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2727 pSMB->TotalDataCount = pSMB->DataCount;
2728 pSMB->TotalParameterCount = pSMB->ParameterCount;
2729 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2730 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2732 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2733 pSMB->Reserved4 = 0;
2734 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2735 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2736 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2737 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2738 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2740 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2744 cifs_buf_release(pSMB);
2753 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2754 char *fileName, __u64 mode, __u64 uid, __u64 gid,
2755 dev_t device, const struct nls_table *nls_codepage)
2757 TRANSACTION2_SPI_REQ *pSMB = NULL;
2758 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2761 int bytes_returned = 0;
2762 FILE_UNIX_BASIC_INFO *data_offset;
2764 cFYI(1, ("In SetUID/GID/Mode"));
2766 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2771 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2773 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2774 /* find define for this maxpathcomponent */
2776 name_len++; /* trailing null */
2778 } else { /* BB improve the check for buffer overruns BB */
2779 name_len = strnlen(fileName, 530);
2780 name_len++; /* trailing null */
2781 strncpy(pSMB->FileName, fileName, name_len);
2784 pSMB->ParameterCount = 6 + name_len;
2785 pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
2786 pSMB->MaxParameterCount = cpu_to_le16(2);
2787 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2788 pSMB->MaxSetupCount = 0;
2792 pSMB->Reserved2 = 0;
2793 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2794 InformationLevel) - 4;
2795 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2797 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2799 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2800 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2801 pSMB->SetupCount = 1;
2802 pSMB->Reserved3 = 0;
2803 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2804 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2805 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2806 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2807 pSMB->TotalParameterCount = pSMB->ParameterCount;
2808 pSMB->TotalDataCount = pSMB->DataCount;
2809 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2810 pSMB->Reserved4 = 0;
2811 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2812 data_offset->Uid = cpu_to_le64(uid);
2813 data_offset->Gid = cpu_to_le64(gid);
2814 /* better to leave device as zero when it is */
2815 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2816 data_offset->DevMinor = cpu_to_le64(MINOR(device));
2817 data_offset->Permissions = cpu_to_le64(mode);
2818 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2819 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2820 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2822 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2826 cifs_buf_release(pSMB);