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"
44 {CIFS_PROT, "\2NT LM 0.12"},
49 /* Mark as invalid, all open files on tree connections since they
50 were closed when session to server was lost */
51 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
53 struct cifsFileInfo *open_file = NULL;
54 struct list_head * tmp;
55 struct list_head * tmp1;
57 /* list all files open on tree connection and mark them invalid */
58 write_lock(&GlobalSMBSeslock);
59 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
60 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
62 open_file->invalidHandle = TRUE;
65 write_unlock(&GlobalSMBSeslock);
66 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */
70 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
71 void **request_buf /* returned */ ,
72 void **response_buf /* returned */ )
76 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
77 check for tcp and smb session status done differently
78 for those three - in the calling routine */
80 if((tcon->ses) && (tcon->ses->server)){
81 struct nls_table *nls_codepage;
82 /* Give Demultiplex thread up to 10 seconds to
83 reconnect, should be greater than cifs socket
84 timeout which is 7 seconds */
85 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
86 wait_event_interruptible_timeout(tcon->ses->server->response_q,
87 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
88 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
89 /* on "soft" mounts we wait once */
90 if((tcon->retry == FALSE) ||
91 (tcon->ses->status == CifsExiting)) {
92 cFYI(1,("gave up waiting on reconnect in smb_init"));
94 } /* else "hard" mount - keep retrying until
95 process is killed or server comes back up */
96 } else /* TCP session is reestablished now */
101 nls_codepage = load_nls_default();
102 /* need to prevent multiple threads trying to
103 simultaneously reconnect the same SMB session */
104 down(&tcon->ses->sesSem);
105 if(tcon->ses->status == CifsNeedReconnect)
106 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
107 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
108 mark_open_files_invalid(tcon);
109 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
111 up(&tcon->ses->sesSem);
113 atomic_inc(&tconInfoReconnectCount);
115 cFYI(1, ("reconnect tcon rc = %d", rc));
116 /* Removed call to reopen open files here -
117 it is safer (and faster) to reopen files
118 one at a time as needed in read and write */
120 /* Check if handle based operation so we
121 know whether we can continue or not without
122 returning to caller to reset file handle */
123 switch(smb_command) {
124 case SMB_COM_READ_ANDX:
125 case SMB_COM_WRITE_ANDX:
127 case SMB_COM_FIND_CLOSE2:
128 case SMB_COM_LOCKING_ANDX: {
129 unload_nls(nls_codepage);
134 up(&tcon->ses->sesSem);
136 unload_nls(nls_codepage);
145 *request_buf = cifs_buf_get();
146 if (request_buf == 0) {
149 /* Although the original thought was we needed the response buf for */
150 /* potential retries of smb operations it turns out we can determine */
151 /* from the mid flags when the request buffer can be resent without */
152 /* having to use a second distinct buffer for the response */
153 *response_buf = *request_buf;
155 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
161 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
164 NEGOTIATE_RSP *pSMBr;
167 struct TCP_Server_Info * server;
170 server = ses->server;
175 rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
176 (void **) &pSMB, (void **) &pSMBr);
180 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
181 if (extended_security)
182 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
184 pSMB->ByteCount = strlen(protocols[0].name) + 1;
185 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
186 /* null guaranteed to be at end of source and target buffers anyway */
188 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
189 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
191 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
192 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
194 server->secMode = pSMBr->SecurityMode;
195 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
196 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
197 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
198 /* probably no need to store and check maxvcs */
200 min(le32_to_cpu(pSMBr->MaxBufferSize),
201 (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
202 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
203 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
204 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
205 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
206 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
207 /* BB with UTC do we ever need to be using srvr timezone? */
208 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
209 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
210 CIFS_CRYPTO_KEY_SIZE);
211 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
212 && (pSMBr->EncryptionKeyLength == 0)) {
213 /* decode security blob */
217 /* BB might be helpful to save off the domain of server here */
219 if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
220 if (pSMBr->ByteCount < 16)
222 else if (pSMBr->ByteCount == 16) {
223 server->secType = RawNTLMSSP;
224 if (server->socketUseCount.counter > 1) {
226 (server->server_GUID,
227 pSMBr->u.extended_response.
230 ("UID of server does not match previous connection to same ip address"));
238 memcpy(server->server_GUID,
239 pSMBr->u.extended_response.
242 rc = decode_negTokenInit(pSMBr->u.
246 16, &server->secType);
249 server->capabilities &= ~CAP_EXTENDED_SECURITY;
250 if(sign_CIFS_PDUs == FALSE) {
251 if(server->secMode & SECMODE_SIGN_REQUIRED)
253 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
254 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
255 } else if(sign_CIFS_PDUs == 1) {
256 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
257 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
262 cifs_buf_release(pSMB);
267 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
269 struct smb_hdr *smb_buffer;
270 struct smb_hdr *smb_buffer_response;
274 cFYI(1, ("In tree disconnect"));
276 * If last user of the connection and
277 * connection alive - disconnect it
278 * If this is the last connection on the server session disconnect it
279 * (and inside session disconnect we should check if tcp socket needs
280 * to be freed and kernel thread woken up).
283 down(&tcon->tconSem);
287 atomic_dec(&tcon->useCount);
288 if (atomic_read(&tcon->useCount) > 0) {
293 /* No need to return error on this operation if tid invalidated and
294 closed on server already e.g. due to tcp session crashing */
295 if(tcon->tidStatus == CifsNeedReconnect) {
300 /* BB remove (from server) list of shares - but with smp safety BB */
301 /* BB is ses active - do we need to check here - but how? BB */
302 if((tcon->ses == 0) || (tcon->ses->server == 0)) {
307 rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
308 (void **) &smb_buffer, (void **) &smb_buffer_response);
313 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
316 cFYI(1, (" Tree disconnect failed %d", rc));
319 cifs_buf_release(smb_buffer);
322 /* No need to return error on this operation if tid invalidated and
323 closed on server already e.g. due to tcp session crashing */
331 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
333 struct smb_hdr *smb_buffer_response;
334 LOGOFF_ANDX_REQ *pSMB;
338 cFYI(1, ("In SMBLogoff for session disconnect"));
344 atomic_dec(&ses->inUse);
345 if (atomic_read(&ses->inUse) > 0) {
350 rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
351 (void **) &pSMB, (void **) &smb_buffer_response);
353 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
354 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
361 pSMB->hdr.Uid = ses->Suid;
363 pSMB->AndXCommand = 0xFF;
364 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
365 smb_buffer_response, &length, 0);
367 atomic_dec(&ses->server->socketUseCount);
368 if (atomic_read(&ses->server->socketUseCount) == 0)
369 ses->server->tcpStatus = CifsExiting;
372 cifs_buf_release(pSMB);
375 /* if session dead then we do not need to do ulogoff,
376 since server closed smb session, no sense reporting
384 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
385 const char *fileName, const struct nls_table *nls_codepage)
387 DELETE_FILE_REQ *pSMB = NULL;
388 DELETE_FILE_RSP *pSMBr = NULL;
394 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
399 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
401 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
402 /* find define for this maxpathcomponent */
404 name_len++; /* trailing null */
406 } else { /* BB improve the check for buffer overruns BB */
407 name_len = strnlen(fileName, 530);
408 name_len++; /* trailing null */
409 strncpy(pSMB->fileName, fileName, name_len);
411 pSMB->SearchAttributes =
412 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
413 pSMB->ByteCount = name_len + 1;
414 pSMB->BufferFormat = 0x04;
415 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
416 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
417 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
418 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
420 cFYI(1, ("Error in RMFile = %d", rc));
423 cifs_buf_release(pSMB);
431 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
432 const char *dirName, const struct nls_table *nls_codepage)
434 DELETE_DIRECTORY_REQ *pSMB = NULL;
435 DELETE_DIRECTORY_RSP *pSMBr = NULL;
440 cFYI(1, ("In CIFSSMBRmDir"));
442 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
447 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
448 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
449 /* find define for this maxpathcomponent */
451 name_len++; /* trailing null */
453 } else { /* BB improve the check for buffer overruns BB */
454 name_len = strnlen(dirName, 530);
455 name_len++; /* trailing null */
456 strncpy(pSMB->DirName, dirName, name_len);
459 pSMB->ByteCount = name_len + 1;
460 pSMB->BufferFormat = 0x04;
461 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
462 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
463 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
464 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
466 cFYI(1, ("Error in RMDir = %d", rc));
469 cifs_buf_release(pSMB);
476 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
477 const char *name, const struct nls_table *nls_codepage)
480 CREATE_DIRECTORY_REQ *pSMB = NULL;
481 CREATE_DIRECTORY_RSP *pSMBr = NULL;
485 cFYI(1, ("In CIFSSMBMkDir"));
487 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
492 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
493 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
494 /* find define for this maxpathcomponent */
496 name_len++; /* trailing null */
498 } else { /* BB improve the check for buffer overruns BB */
499 name_len = strnlen(name, 530);
500 name_len++; /* trailing null */
501 strncpy(pSMB->DirName, name, name_len);
504 pSMB->ByteCount = name_len + 1 /* for buf format */ ;
505 pSMB->BufferFormat = 0x04;
506 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
507 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
508 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
509 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
511 cFYI(1, ("Error in Mkdir = %d", rc));
514 cifs_buf_release(pSMB);
521 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
522 const char *fileName, const int openDisposition,
523 const int access_flags, const int create_options, __u16 * netfid,
524 int *pOplock, FILE_ALL_INFO * pfile_info,
525 const struct nls_table *nls_codepage)
528 OPEN_REQ *pSMB = NULL;
529 OPEN_RSP *pSMBr = NULL;
534 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
539 pSMB->AndXCommand = 0xFF; /* none */
541 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
542 pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
544 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
546 /* find define for this maxpathcomponent */
548 name_len++; /* trailing null */
550 pSMB->NameLength = cpu_to_le16(name_len);
551 } else { /* BB improve the check for buffer overruns BB */
552 pSMB->ByteCount = 0; /* no pad */
553 name_len = strnlen(fileName, 530);
554 name_len++; /* trailing null */
555 pSMB->NameLength = cpu_to_le16(name_len);
556 strncpy(pSMB->fileName, fileName, name_len);
558 if (*pOplock & REQ_OPLOCK)
559 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
560 else if (*pOplock & REQ_BATCHOPLOCK) {
561 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
563 pSMB->DesiredAccess = cpu_to_le32(access_flags);
564 pSMB->AllocationSize = 0;
565 pSMB->FileAttributes = ATTR_NORMAL;
566 /* XP does not handle ATTR_POSIX_SEMANTICS */
567 /* but it helps speed up case sensitive checks for other
568 servers such as Samba */
569 if (tcon->ses->capabilities & CAP_UNIX)
570 pSMB->FileAttributes |= ATTR_POSIX_SEMANTICS;
572 /* if ((omode & S_IWUGO) == 0)
573 pSMB->FileAttributes |= ATTR_READONLY;*/
574 /* Above line causes problems due to vfs splitting create into two
575 pieces - need to set mode after file created not while it is
577 pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
578 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
579 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
580 pSMB->CreateOptions = cpu_to_le32(create_options);
581 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
582 pSMB->SecurityFlags =
583 cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
585 pSMB->ByteCount += name_len;
586 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
588 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
589 /* long_op set to 1 to allow for oplock break timeouts */
590 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
591 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
593 cFYI(1, ("Error in Open = %d", rc));
595 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
596 *netfid = pSMBr->Fid; /* cifs fid stays in le */
597 /* Let caller know file was created so we can set the mode. */
598 /* Do we care about the CreateAction in any other cases? */
599 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
600 *pOplock |= CIFS_CREATE_ACTION;
602 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
603 36 /* CreationTime to Attributes */);
604 /* the file_info buf is endian converted by caller */
605 pfile_info->AllocationSize = pSMBr->AllocationSize;
606 pfile_info->EndOfFile = pSMBr->EndOfFile;
607 pfile_info->NumberOfLinks = cpu_to_le32(1);
611 cifs_buf_release(pSMB);
617 /* If no buffer passed in, then caller wants to do the copy
618 as in the case of readpages so the SMB buffer must be
619 freed by the caller */
622 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
623 const int netfid, const unsigned int count,
624 const __u64 lseek, unsigned int *nbytes, char **buf)
627 READ_REQ *pSMB = NULL;
628 READ_RSP *pSMBr = NULL;
629 char *pReadData = NULL;
633 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
638 /* tcon and ses pointer are checked in smb_init */
639 if (tcon->ses->server == NULL)
640 return -ECONNABORTED;
642 pSMB->AndXCommand = 0xFF; /* none */
644 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
645 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
647 pSMB->MaxCount = cpu_to_le16(count);
648 pSMB->MaxCountHigh = 0;
649 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
651 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
652 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
654 cERROR(1, ("Send error in read = %d", rc));
656 pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
657 *nbytes = pSMBr->DataLength;
658 /*check that DataLength would not go beyond end of SMB */
659 if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
660 || (pSMBr->DataLength > count)) {
661 cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
666 (char *) (&pSMBr->hdr.Protocol) +
667 le16_to_cpu(pSMBr->DataOffset);
668 /* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
669 cERROR(1,("Faulting on read rc = %d",rc));
671 }*/ /* can not use copy_to_user when using page cache*/
673 memcpy(*buf,pReadData,pSMBr->DataLength);
678 cifs_buf_release(pSMB);
683 /* Note: On -EAGAIN error only caller can retry on handle based calls
684 since file handle passed in no longer valid */
689 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
690 const int netfid, const unsigned int count,
691 const __u64 offset, unsigned int *nbytes, const char *buf,
695 WRITE_REQ *pSMB = NULL;
696 WRITE_RSP *pSMBr = NULL;
699 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
703 /* tcon and ses pointer are checked in smb_init */
704 if (tcon->ses->server == NULL)
705 return -ECONNABORTED;
707 pSMB->AndXCommand = 0xFF; /* none */
709 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
710 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
712 if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
713 pSMB->DataLengthLow =
714 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
716 pSMB->DataLengthLow = count;
717 pSMB->DataLengthHigh = 0;
719 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
721 memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
723 pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
724 pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
725 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
726 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
728 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
729 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
731 cERROR(1, ("Send error in write = %d", rc));
734 *nbytes = le16_to_cpu(pSMBr->Count);
737 cifs_buf_release(pSMB);
739 /* Note: On -EAGAIN error only caller can retry on handle based calls
740 since file handle passed in no longer valid */
746 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
747 const __u16 smb_file_id, const __u64 len,
748 const __u64 offset, const __u32 numUnlock,
749 const __u32 numLock, const __u8 lockType, const int waitFlag)
752 LOCK_REQ *pSMB = NULL;
753 LOCK_RSP *pSMBr = NULL;
758 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
759 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
764 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
765 timeout = -1; /* no response expected */
767 } else if (waitFlag == TRUE) {
768 timeout = 3; /* blocking operation, no timeout */
769 pSMB->Timeout = -1; /* blocking - do not time out */
774 pSMB->NumberOfLocks = cpu_to_le32(numLock);
775 pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
776 pSMB->LockType = lockType;
777 pSMB->AndXCommand = 0xFF; /* none */
778 pSMB->Fid = smb_file_id; /* netfid stays le */
780 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
781 temp = cpu_to_le64(len);
782 pSMB->Locks[0].LengthLow = (__u32)(len & 0xFFFFFFFF);
783 pSMB->Locks[0].LengthHigh = (__u32)(len>>32);
784 temp = cpu_to_le64(offset);
785 pSMB->Locks[0].OffsetLow = (__u32)(offset & 0xFFFFFFFF);
786 pSMB->Locks[0].OffsetHigh = (__u32)(offset>>32);
787 pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
788 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
789 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
791 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
792 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
795 cERROR(1, ("Send error in Lock = %d", rc));
798 cifs_buf_release(pSMB);
800 /* Note: On -EAGAIN error only caller can retry on handle based calls
801 since file handle passed in no longer valid */
806 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
809 CLOSE_REQ *pSMB = NULL;
810 CLOSE_RSP *pSMBr = NULL;
812 cFYI(1, ("In CIFSSMBClose"));
814 /* do not retry on dead session on close */
815 rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
822 pSMB->FileID = (__u16) smb_file_id;
823 pSMB->LastWriteTime = 0;
825 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
826 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
829 /* EINTR is expected when user ctl-c to kill app */
830 cERROR(1, ("Send error in Close = %d", rc));
834 cifs_buf_release(pSMB);
836 /* Since session is dead, file will be closed on server already */
844 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
845 const char *fromName, const char *toName,
846 const struct nls_table *nls_codepage)
849 RENAME_REQ *pSMB = NULL;
850 RENAME_RSP *pSMBr = NULL;
852 int name_len, name_len2;
854 cFYI(1, ("In CIFSSMBRename"));
856 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
861 pSMB->BufferFormat = 0x04;
862 pSMB->SearchAttributes =
863 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
866 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
868 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
869 /* find define for this maxpathcomponent */
871 name_len++; /* trailing null */
873 pSMB->OldFileName[name_len] = 0x04; /* pad */
874 /* protocol requires ASCII signature byte on Unicode string */
875 pSMB->OldFileName[name_len + 1] = 0x00;
877 cifs_strtoUCS((wchar_t *) & pSMB->
878 OldFileName[name_len + 2], toName, 530,
880 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
881 name_len2 *= 2; /* convert to bytes */
882 } else { /* BB improve the check for buffer overruns BB */
883 name_len = strnlen(fromName, 530);
884 name_len++; /* trailing null */
885 strncpy(pSMB->OldFileName, fromName, name_len);
886 name_len2 = strnlen(toName, 530);
887 name_len2++; /* trailing null */
888 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
889 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
890 name_len2++; /* trailing null */
891 name_len2++; /* signature byte */
894 pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
895 /* we could also set search attributes but not needed */
896 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
897 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
899 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
900 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
902 cFYI(1, ("Send error in rename = %d", rc));
905 cifs_buf_release(pSMB);
913 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
914 int netfid, char * target_name, const struct nls_table * nls_codepage)
916 struct smb_com_transaction2_sfi_req *pSMB = NULL;
917 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
918 struct set_file_rename * rename_info;
920 char dummy_string[30];
922 int bytes_returned = 0;
925 cFYI(1, ("Rename to File by handle"));
926 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
931 pSMB->ParameterCount = 6;
932 pSMB->MaxSetupCount = 0;
937 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
939 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
941 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
942 rename_info = (struct set_file_rename *) data_offset;
943 pSMB->MaxParameterCount = cpu_to_le16(2);
944 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
945 pSMB->SetupCount = 1;
947 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
948 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount;
949 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
950 pSMB->TotalParameterCount = pSMB->ParameterCount;
951 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
952 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
953 /* construct random name ".cifs_tmp<inodenum><mid>" */
954 rename_info->overwrite = cpu_to_le32(1);
955 rename_info->root_fid = 0;
956 /* unicode only call */
957 if(target_name == NULL) {
958 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
959 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
961 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, 530, nls_codepage);
963 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
964 pSMB->DataCount = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
965 pSMB->ByteCount += pSMB->DataCount;
966 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
967 pSMB->TotalDataCount = pSMB->DataCount;
969 pSMB->InformationLevel =
970 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
972 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
973 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
974 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
975 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
977 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
981 cifs_buf_release(pSMB);
983 /* Note: On -EAGAIN error only caller can retry on handle based calls
984 since file handle passed in no longer valid */
991 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
992 const char *fromName, const char *toName,
993 const struct nls_table *nls_codepage)
995 TRANSACTION2_SPI_REQ *pSMB = NULL;
996 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1001 int bytes_returned = 0;
1003 cFYI(1, ("In Symlink Unix style"));
1005 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1010 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1012 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
1013 /* find define for this maxpathcomponent */
1015 name_len++; /* trailing null */
1018 } else { /* BB improve the check for buffer overruns BB */
1019 name_len = strnlen(fromName, 530);
1020 name_len++; /* trailing null */
1021 strncpy(pSMB->FileName, fromName, name_len);
1023 pSMB->ParameterCount = 6 + name_len;
1024 pSMB->MaxSetupCount = 0;
1028 pSMB->Reserved2 = 0;
1029 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1030 InformationLevel) - 4;
1031 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1033 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1034 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1036 cifs_strtoUCS((wchar_t *) data_offset, toName, 530
1037 /* find define for this maxpathcomponent */
1039 name_len_target++; /* trailing null */
1040 name_len_target *= 2;
1041 } else { /* BB improve the check for buffer overruns BB */
1042 name_len_target = strnlen(toName, 530);
1043 name_len_target++; /* trailing null */
1044 strncpy(data_offset, toName, name_len_target);
1047 pSMB->DataCount = name_len_target;
1048 pSMB->MaxParameterCount = cpu_to_le16(2);
1049 /* BB find exact max on data count below from sess */
1050 pSMB->MaxDataCount = cpu_to_le16(1000);
1051 pSMB->SetupCount = 1;
1052 pSMB->Reserved3 = 0;
1053 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1054 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
1055 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1056 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1057 pSMB->TotalDataCount = pSMB->DataCount;
1058 pSMB->TotalParameterCount = pSMB->ParameterCount;
1059 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1060 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1061 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1062 pSMB->Reserved4 = 0;
1063 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1064 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1065 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1066 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1069 ("Send error in SetPathInfo (create symlink) = %d",
1074 cifs_buf_release(pSMB);
1077 goto createSymLinkRetry;
1083 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1084 const char *fromName, const char *toName,
1085 const struct nls_table *nls_codepage)
1087 TRANSACTION2_SPI_REQ *pSMB = NULL;
1088 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1091 int name_len_target;
1093 int bytes_returned = 0;
1095 cFYI(1, ("In Create Hard link Unix style"));
1096 createHardLinkRetry:
1097 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1102 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1103 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
1104 /* find define for this maxpathcomponent */
1106 name_len++; /* trailing null */
1109 } else { /* BB improve the check for buffer overruns BB */
1110 name_len = strnlen(toName, 530);
1111 name_len++; /* trailing null */
1112 strncpy(pSMB->FileName, toName, name_len);
1114 pSMB->ParameterCount = 6 + name_len;
1115 pSMB->MaxSetupCount = 0;
1119 pSMB->Reserved2 = 0;
1120 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
1121 InformationLevel) - 4;
1122 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
1124 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
1125 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1127 cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
1128 /* find define for this maxpathcomponent */
1130 name_len_target++; /* trailing null */
1131 name_len_target *= 2;
1132 } else { /* BB improve the check for buffer overruns BB */
1133 name_len_target = strnlen(fromName, 530);
1134 name_len_target++; /* trailing null */
1135 strncpy(data_offset, fromName, name_len_target);
1138 pSMB->DataCount = name_len_target;
1139 pSMB->MaxParameterCount = cpu_to_le16(2);
1140 /* BB find exact max on data count below from sess*/
1141 pSMB->MaxDataCount = cpu_to_le16(1000);
1142 pSMB->SetupCount = 1;
1143 pSMB->Reserved3 = 0;
1144 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1145 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
1146 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1147 pSMB->TotalParameterCount = pSMB->ParameterCount;
1148 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
1149 pSMB->TotalDataCount = pSMB->DataCount;
1150 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
1151 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
1152 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1153 pSMB->Reserved4 = 0;
1154 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1155 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1156 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1157 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1159 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1163 cifs_buf_release(pSMB);
1165 goto createHardLinkRetry;
1171 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1172 const char *fromName, const char *toName,
1173 const struct nls_table *nls_codepage)
1176 NT_RENAME_REQ *pSMB = NULL;
1177 RENAME_RSP *pSMBr = NULL;
1179 int name_len, name_len2;
1181 cFYI(1, ("In CIFSCreateHardLink"));
1182 winCreateHardLinkRetry:
1184 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1189 pSMB->SearchAttributes =
1190 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1192 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1193 pSMB->ClusterCount = 0;
1195 pSMB->BufferFormat = 0x04;
1197 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1199 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
1200 /* find define for this maxpathcomponent */
1202 name_len++; /* trailing null */
1204 pSMB->OldFileName[name_len] = 0; /* pad */
1205 pSMB->OldFileName[name_len + 1] = 0x04;
1207 cifs_strtoUCS((wchar_t *) & pSMB->
1208 OldFileName[name_len + 2], toName, 530,
1210 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1211 name_len2 *= 2; /* convert to bytes */
1212 } else { /* BB improve the check for buffer overruns BB */
1213 name_len = strnlen(fromName, 530);
1214 name_len++; /* trailing null */
1215 strncpy(pSMB->OldFileName, fromName, name_len);
1216 name_len2 = strnlen(toName, 530);
1217 name_len2++; /* trailing null */
1218 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1219 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1220 name_len2++; /* trailing null */
1221 name_len2++; /* signature byte */
1224 pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
1225 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1226 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1228 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1229 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1231 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1234 cifs_buf_release(pSMB);
1236 goto winCreateHardLinkRetry;
1242 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1243 const unsigned char *searchName,
1244 char *symlinkinfo, const int buflen,
1245 const struct nls_table *nls_codepage)
1247 /* SMB_QUERY_FILE_UNIX_LINK */
1248 TRANSACTION2_QPI_REQ *pSMB = NULL;
1249 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1254 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1257 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1262 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1264 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1265 /* find define for this maxpathcomponent */
1267 name_len++; /* trailing null */
1269 } else { /* BB improve the check for buffer overruns BB */
1270 name_len = strnlen(searchName, 530);
1271 name_len++; /* trailing null */
1272 strncpy(pSMB->FileName, searchName, name_len);
1275 pSMB->TotalParameterCount =
1276 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1277 pSMB->TotalDataCount = 0;
1278 pSMB->MaxParameterCount = cpu_to_le16(2);
1279 /* BB find exact max data count below from sess structure BB */
1280 pSMB->MaxDataCount = cpu_to_le16(4000);
1281 pSMB->MaxSetupCount = 0;
1285 pSMB->Reserved2 = 0;
1286 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1287 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1288 pSMB->DataCount = 0;
1289 pSMB->DataOffset = 0;
1290 pSMB->SetupCount = 1;
1291 pSMB->Reserved3 = 0;
1292 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1293 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1294 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1295 pSMB->ParameterCount = pSMB->TotalParameterCount;
1296 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1297 pSMB->Reserved4 = 0;
1298 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1299 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1301 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1302 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1304 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1305 } else { /* decode response */
1306 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1307 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1308 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1309 /* BB also check enough total bytes returned */
1310 rc = -EIO; /* bad smb */
1312 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1313 name_len = UniStrnlen((wchar_t *) ((char *)
1314 &pSMBr->hdr.Protocol +pSMBr->DataOffset),
1315 min_t(const int, buflen,pSMBr->DataCount) / 2);
1316 cifs_strfromUCS_le(symlinkinfo,
1317 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1319 name_len, nls_codepage);
1321 strncpy(symlinkinfo,
1322 (char *) &pSMBr->hdr.Protocol +
1324 min_t(const int, buflen, pSMBr->DataCount));
1326 symlinkinfo[buflen] = 0;
1327 /* just in case so calling code does not go off the end of buffer */
1331 cifs_buf_release(pSMB);
1333 goto querySymLinkRetry;
1340 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1341 const unsigned char *searchName,
1342 char *symlinkinfo, const int buflen,__u16 fid,
1343 const struct nls_table *nls_codepage)
1348 struct smb_com_transaction_ioctl_req * pSMB;
1349 struct smb_com_transaction_ioctl_rsp * pSMBr;
1351 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1352 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1357 pSMB->TotalParameterCount = 0 ;
1358 pSMB->TotalDataCount = 0;
1359 pSMB->MaxParameterCount = cpu_to_le16(2);
1360 /* BB find exact data count max from sess structure BB */
1361 pSMB->MaxDataCount = cpu_to_le16(4000);
1362 pSMB->MaxSetupCount = 4;
1364 pSMB->ParameterOffset = 0;
1365 pSMB->DataCount = 0;
1366 pSMB->DataOffset = 0;
1367 pSMB->SetupCount = 4;
1368 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1369 pSMB->ParameterCount = pSMB->TotalParameterCount;
1370 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1371 pSMB->IsFsctl = 1; /* FSCTL */
1372 pSMB->IsRootFlag = 0;
1373 pSMB->Fid = fid; /* file handle always le */
1374 pSMB->ByteCount = 0;
1376 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1377 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1379 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1380 } else { /* decode response */
1381 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1382 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1383 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1384 /* BB also check enough total bytes returned */
1385 rc = -EIO; /* bad smb */
1387 if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
1388 /* could also validate reparse tag && better check name length */
1389 struct reparse_data * reparse_buf = (struct reparse_data *)
1390 ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
1391 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1392 name_len = UniStrnlen((wchar_t *)
1393 (reparse_buf->LinkNamesBuf +
1394 reparse_buf->TargetNameOffset),
1395 min(buflen/2, reparse_buf->TargetNameLen / 2));
1396 cifs_strfromUCS_le(symlinkinfo,
1397 (wchar_t *) (reparse_buf->LinkNamesBuf +
1398 reparse_buf->TargetNameOffset),
1399 name_len, nls_codepage);
1400 } else { /* ASCII names */
1401 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1402 reparse_buf->TargetNameOffset,
1403 min_t(const int, buflen, reparse_buf->TargetNameLen));
1407 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1409 symlinkinfo[buflen] = 0; /* just in case so the caller
1410 does not go off the end of the buffer */
1411 cFYI(1,("readlink result - %s ",symlinkinfo));
1415 cifs_buf_release(pSMB);
1417 /* Note: On -EAGAIN error only caller can retry on handle based calls
1418 since file handle passed in no longer valid */
1424 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1425 const unsigned char *searchName,
1426 FILE_ALL_INFO * pFindData,
1427 const struct nls_table *nls_codepage)
1429 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1430 TRANSACTION2_QPI_REQ *pSMB = NULL;
1431 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1436 cFYI(1, ("In QPathInfo path %s", searchName));
1438 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1443 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1445 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1446 /* find define for this maxpathcomponent */
1448 name_len++; /* trailing null */
1450 } else { /* BB improve the check for buffer overruns BB */
1451 name_len = strnlen(searchName, 530);
1452 name_len++; /* trailing null */
1453 strncpy(pSMB->FileName, searchName, name_len);
1456 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1457 name_len /* includes null */ ;
1458 pSMB->TotalDataCount = 0;
1459 pSMB->MaxParameterCount = cpu_to_le16(2);
1460 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1461 pSMB->MaxSetupCount = 0;
1465 pSMB->Reserved2 = 0;
1466 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1467 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1468 pSMB->DataCount = 0;
1469 pSMB->DataOffset = 0;
1470 pSMB->SetupCount = 1;
1471 pSMB->Reserved3 = 0;
1472 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1473 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1474 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1475 pSMB->ParameterCount = pSMB->TotalParameterCount;
1476 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1477 pSMB->Reserved4 = 0;
1478 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1479 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1481 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1482 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1484 cFYI(1, ("Send error in QPathInfo = %d", rc));
1485 } else { /* decode response */
1486 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1487 /* BB also check enough total bytes returned */
1488 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1489 rc = -EIO; /* bad smb */
1490 else if (pFindData){
1491 memcpy((char *) pFindData,
1492 (char *) &pSMBr->hdr.Protocol +
1493 pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
1498 cifs_buf_release(pSMB);
1500 goto QPathInfoRetry;
1506 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1507 const unsigned char *searchName,
1508 FILE_UNIX_BASIC_INFO * pFindData,
1509 const struct nls_table *nls_codepage)
1511 /* SMB_QUERY_FILE_UNIX_BASIC */
1512 TRANSACTION2_QPI_REQ *pSMB = NULL;
1513 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1515 int bytes_returned = 0;
1518 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1520 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1525 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1527 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1528 /* find define for this maxpathcomponent */
1530 name_len++; /* trailing null */
1532 } else { /* BB improve the check for buffer overruns BB */
1533 name_len = strnlen(searchName, 530);
1534 name_len++; /* trailing null */
1535 strncpy(pSMB->FileName, searchName, name_len);
1538 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1539 name_len /* includes null */ ;
1540 pSMB->TotalDataCount = 0;
1541 pSMB->MaxParameterCount = cpu_to_le16(2);
1542 /* BB find exact max SMB PDU from sess structure BB */
1543 pSMB->MaxDataCount = cpu_to_le16(4000);
1544 pSMB->MaxSetupCount = 0;
1548 pSMB->Reserved2 = 0;
1549 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1550 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1551 pSMB->DataCount = 0;
1552 pSMB->DataOffset = 0;
1553 pSMB->SetupCount = 1;
1554 pSMB->Reserved3 = 0;
1555 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1556 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1557 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1558 pSMB->ParameterCount = pSMB->TotalParameterCount;
1559 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1560 pSMB->Reserved4 = 0;
1561 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1562 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1564 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1565 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1567 cFYI(1, ("Send error in QPathInfo = %d", rc));
1568 } else { /* decode response */
1569 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1570 /* BB also check if enough total bytes returned */
1571 if ((pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO)) ||
1572 (pSMBr->DataOffset > 512) ||
1573 (pSMBr->DataOffset < sizeof(struct smb_hdr))) {
1574 cFYI(1,("UnixQPathinfo invalid data offset %d bytes returned %d",
1575 (int)pSMBr->DataOffset,bytes_returned));
1576 rc = -EIO; /* bad smb */
1578 memcpy((char *) pFindData,
1579 (char *) &pSMBr->hdr.Protocol +
1581 sizeof (FILE_UNIX_BASIC_INFO));
1585 cifs_buf_release(pSMB);
1587 goto UnixQPathInfoRetry;
1593 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1594 const char *searchName, FILE_ALL_INFO * findData,
1595 const struct nls_table *nls_codepage)
1597 /* level 257 SMB_ */
1598 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1599 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1604 cFYI(1, ("In FindUnique"));
1606 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1611 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1613 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1614 /* find define for this maxpathcomponent */
1616 name_len++; /* trailing null */
1618 } else { /* BB improve the check for buffer overruns BB */
1619 name_len = strnlen(searchName, 530);
1620 name_len++; /* trailing null */
1621 strncpy(pSMB->FileName, searchName, name_len);
1624 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1625 pSMB->TotalDataCount = 0; /* no EAs */
1626 pSMB->MaxParameterCount = cpu_to_le16(2);
1627 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1628 pSMB->MaxSetupCount = 0;
1632 pSMB->Reserved2 = 0;
1633 pSMB->ParameterOffset = cpu_to_le16(
1634 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1635 pSMB->DataCount = 0;
1636 pSMB->DataOffset = 0;
1637 pSMB->SetupCount = 1; /* one byte, no need to le convert */
1638 pSMB->Reserved3 = 0;
1639 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1640 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1641 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
1642 pSMB->ParameterCount = pSMB->TotalParameterCount;
1643 pSMB->SearchAttributes =
1644 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1646 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
1647 pSMB->SearchFlags = cpu_to_le16(1);
1648 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1649 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
1650 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1651 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1653 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1654 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1657 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1658 } else { /* decode response */
1663 cifs_buf_release(pSMB);
1665 goto findUniqueRetry;
1671 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1672 const char *searchName, FILE_DIRECTORY_INFO * findData,
1673 T2_FFIRST_RSP_PARMS * findParms,
1674 const struct nls_table *nls_codepage, int *pUnicodeFlag,
1677 /* level 257 SMB_ */
1678 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1679 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1680 char *response_data;
1685 cFYI(1, ("In FindFirst"));
1687 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1692 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1694 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1695 /* find define for this maxpathcomponent */
1697 name_len++; /* trailing null */
1699 } else { /* BB improve the check for buffer overruns BB */
1700 name_len = strnlen(searchName, 530);
1701 name_len++; /* trailing null */
1702 strncpy(pSMB->FileName, searchName, name_len);
1705 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1706 pSMB->TotalDataCount = 0; /* no EAs */
1707 pSMB->MaxParameterCount = cpu_to_le16(10);
1708 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1709 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1710 pSMB->MaxSetupCount = 0;
1714 pSMB->Reserved2 = 0;
1715 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1716 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1717 pSMB->ParameterCount = pSMB->TotalParameterCount;
1718 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
1719 smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1720 pSMB->DataCount = 0;
1721 pSMB->DataOffset = 0;
1722 pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
1723 pSMB->Reserved3 = 0;
1724 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1725 pSMB->SearchAttributes =
1726 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1728 pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
1729 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1731 /* test for Unix extensions */
1732 if (tcon->ses->capabilities & CAP_UNIX) {
1733 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1736 pSMB->InformationLevel =
1737 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1740 pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
1741 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1742 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1744 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1745 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1747 if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1748 cFYI(1, ("Error in FindFirst = %d", rc));
1749 } else { /* decode response */
1750 /* BB add safety checks for these memcpys */
1751 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1752 *pUnicodeFlag = TRUE;
1754 *pUnicodeFlag = FALSE;
1756 (char *) &pSMBr->hdr.Protocol +
1757 le16_to_cpu(pSMBr->ParameterOffset),
1758 sizeof (T2_FFIRST_RSP_PARMS));
1759 /* search handle can stay LE and EAoffset not needed so not converted */
1760 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1761 findParms->LastNameOffset =
1762 le16_to_cpu(findParms->LastNameOffset);
1763 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1765 (char *) &pSMBr->hdr.Protocol +
1766 le16_to_cpu(pSMBr->DataOffset);
1767 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1770 cifs_buf_release(pSMB);
1773 goto findFirstRetry;
1779 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1780 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1781 const __u16 searchHandle, char * resume_file_name, int name_len,
1782 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1784 /* level 257 SMB_ */
1785 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1786 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1787 char *response_data;
1791 cFYI(1, ("In FindNext"));
1793 if(resume_file_name == NULL) {
1796 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1801 pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
1802 pSMB->TotalDataCount = 0; /* no EAs */
1803 pSMB->MaxParameterCount = cpu_to_le16(8);
1804 pSMB->MaxDataCount =
1805 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1806 pSMB->MaxSetupCount = 0;
1810 pSMB->Reserved2 = 0;
1811 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1812 struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1813 pSMB->DataCount = 0;
1814 pSMB->DataOffset = 0;
1815 pSMB->SetupCount = 1;
1816 pSMB->Reserved3 = 0;
1817 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1818 pSMB->SearchHandle = searchHandle; /* always kept as le */
1819 findParms->SearchCount = 0; /* set to zero in case of error */
1821 cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1822 /* test for Unix extensions */
1823 if (tcon->ses->capabilities & CAP_UNIX) {
1824 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1827 pSMB->InformationLevel =
1828 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1831 pSMB->ResumeKey = resume_key;
1833 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1834 /* BB add check to make sure we do not cross end of smb */
1835 if(name_len < CIFS_MAX_MSGSIZE) {
1836 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1837 pSMB->ByteCount += name_len;
1839 pSMB->TotalParameterCount += name_len;
1840 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1841 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1842 pSMB->ParameterCount = pSMB->TotalParameterCount;
1843 /* BB improve error handling here */
1844 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1845 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1847 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1848 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1852 rc = 0; /* search probably was closed at end of search above */
1854 cFYI(1, ("FindNext returned = %d", rc));
1855 } else { /* decode response */
1856 /* BB add safety checks for these memcpys */
1857 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1858 *pUnicodeFlag = TRUE;
1860 *pUnicodeFlag = FALSE;
1862 (char *) &pSMBr->hdr.Protocol +
1863 le16_to_cpu(pSMBr->ParameterOffset),
1864 sizeof (T2_FNEXT_RSP_PARMS));
1865 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1866 findParms->LastNameOffset =
1867 le16_to_cpu(findParms->LastNameOffset);
1868 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1870 (char *) &pSMBr->hdr.Protocol +
1871 le16_to_cpu(pSMBr->DataOffset);
1872 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1875 cifs_buf_release(pSMB);
1877 /* Note: On -EAGAIN error only caller can retry on handle based calls
1878 since file handle passed in no longer valid */
1884 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
1887 FINDCLOSE_REQ *pSMB = NULL;
1888 CLOSE_RSP *pSMBr = NULL;
1891 cFYI(1, ("In CIFSSMBFindClose"));
1892 rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
1894 /* no sense returning error if session restarted
1895 file handle has been closed */
1901 pSMB->FileID = searchHandle;
1902 pSMB->ByteCount = 0;
1903 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1904 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1906 cERROR(1, ("Send error in FindClose = %d", rc));
1909 cifs_buf_release(pSMB);
1911 /* Since session is dead, search handle closed on server already */
1919 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
1920 const unsigned char *searchName,
1921 unsigned char **targetUNCs,
1922 unsigned int *number_of_UNC_in_array,
1923 const struct nls_table *nls_codepage)
1925 /* TRANS2_GET_DFS_REFERRAL */
1926 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
1927 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
1928 struct dfs_referral_level_3 * referrals = NULL;
1934 *number_of_UNC_in_array = 0;
1937 cFYI(1, ("In GetDFSRefer the path %s", searchName));
1941 rc = smb_init(SMB_COM_TRANSACTION2, 15, 0, (void **) &pSMB,
1946 pSMB->hdr.Tid = ses->ipc_tid;
1947 pSMB->hdr.Uid = ses->Suid;
1948 if (ses->capabilities & CAP_STATUS32) {
1949 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
1951 if (ses->capabilities & CAP_DFS) {
1952 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
1955 if (ses->capabilities & CAP_UNICODE) {
1956 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
1958 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
1960 /* find define for this maxpathcomponent */
1962 name_len++; /* trailing null */
1964 } else { /* BB improve the check for buffer overruns BB */
1965 name_len = strnlen(searchName, 530);
1966 name_len++; /* trailing null */
1967 strncpy(pSMB->RequestFileName, searchName, name_len);
1970 pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
1971 pSMB->TotalDataCount = 0;
1972 pSMB->DataCount = 0;
1973 pSMB->DataOffset = 0;
1974 pSMB->MaxParameterCount = 0;
1975 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1976 pSMB->MaxSetupCount = 0;
1980 pSMB->Reserved2 = 0;
1981 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1982 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1983 pSMB->SetupCount = 1;
1984 pSMB->Reserved3 = 0;
1985 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
1986 pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
1987 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1988 pSMB->TotalParameterCount = pSMB->ParameterCount;
1989 pSMB->MaxReferralLevel = cpu_to_le16(3);
1990 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1991 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1993 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
1994 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1996 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
1997 } else { /* decode response */
1998 /* BB Add logic to parse referrals here */
1999 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2000 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
2002 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2003 pSMBr->ByteCount, pSMBr->DataOffset));
2004 if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
2005 rc = -EIO; /* bad smb */
2008 (struct dfs_referral_level_3 *)
2009 (8 /* sizeof start of data block */ +
2011 (char *) &pSMBr->hdr.Protocol);
2012 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));
2013 /* BB This field is actually two bytes in from start of
2014 data block so we could do safety check that DataBlock
2015 begins at address of pSMBr->NumberOfReferrals */
2016 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2018 /* BB Fix below so can return more than one referral */
2019 if(*number_of_UNC_in_array > 1)
2020 *number_of_UNC_in_array = 1;
2022 /* get the length of the strings describing refs */
2024 for(i=0;i<*number_of_UNC_in_array;i++) {
2025 /* make sure that DfsPathOffset not past end */
2026 referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
2027 if(referrals->DfsPathOffset > pSMBr->DataCount) {
2028 /* if invalid referral, stop here and do
2029 not try to copy any more */
2030 *number_of_UNC_in_array = i;
2033 temp = ((char *)referrals) + referrals->DfsPathOffset;
2035 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2036 name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
2038 name_len += strnlen(temp,pSMBr->DataCount);
2041 /* BB add check that referral pointer does not fall off end PDU */
2044 /* BB add check for name_len bigger than bcc */
2046 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2047 /* copy the ref strings */
2049 (struct dfs_referral_level_3 *)
2050 (8 /* sizeof data hdr */ +
2052 (char *) &pSMBr->hdr.Protocol);
2054 for(i=0;i<*number_of_UNC_in_array;i++) {
2055 temp = ((char *)referrals) + referrals->DfsPathOffset;
2056 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2057 cifs_strfromUCS_le(*targetUNCs,
2058 (wchar_t *) temp, name_len, nls_codepage);
2060 strncpy(*targetUNCs,temp,name_len);
2062 /* BB update target_uncs pointers */
2071 cifs_buf_release(pSMB);
2080 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2081 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2083 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2084 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2085 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2086 FILE_SYSTEM_INFO *response_data;
2088 int bytes_returned = 0;
2090 cFYI(1, ("In QFSInfo"));
2092 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2097 pSMB->TotalParameterCount = 2; /* level */
2098 pSMB->TotalDataCount = 0;
2099 pSMB->MaxParameterCount = cpu_to_le16(2);
2100 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2101 pSMB->MaxSetupCount = 0;
2105 pSMB->Reserved2 = 0;
2106 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2107 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2108 pSMB->ParameterCount = pSMB->TotalParameterCount;
2109 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2110 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2111 pSMB->DataCount = 0;
2112 pSMB->DataOffset = 0;
2113 pSMB->SetupCount = 1;
2114 pSMB->Reserved3 = 0;
2115 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2116 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2117 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2118 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2120 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2121 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2123 cERROR(1, ("Send error in QFSInfo = %d", rc));
2124 } else { /* decode response */
2125 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2127 ("Decoding qfsinfo response. BCC: %d Offset %d",
2128 pSMBr->ByteCount, pSMBr->DataOffset));
2129 if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
2130 rc = -EIO; /* bad smb */
2134 *) (((char *) &pSMBr->hdr.Protocol) +
2137 le32_to_cpu(response_data->BytesPerSector) *
2138 le32_to_cpu(response_data->
2139 SectorsPerAllocationUnit);
2141 le64_to_cpu(response_data->TotalAllocationUnits);
2142 FSData->f_bfree = FSData->f_bavail =
2143 le64_to_cpu(response_data->FreeAllocationUnits);
2145 ("Blocks: %lld Free: %lld Block size %ld",
2146 (unsigned long long)FSData->f_blocks,
2147 (unsigned long long)FSData->f_bfree,
2152 cifs_buf_release(pSMB);
2161 CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
2162 const struct nls_table *nls_codepage)
2164 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
2165 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2166 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2167 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
2169 int bytes_returned = 0;
2171 cFYI(1, ("In QFSAttributeInfo"));
2173 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2178 pSMB->TotalParameterCount = 2; /* level */
2179 pSMB->TotalDataCount = 0;
2180 pSMB->MaxParameterCount = cpu_to_le16(2);
2181 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2182 pSMB->MaxSetupCount = 0;
2186 pSMB->Reserved2 = 0;
2187 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2188 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2189 pSMB->ParameterCount = pSMB->TotalParameterCount;
2190 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2191 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2192 pSMB->DataCount = 0;
2193 pSMB->DataOffset = 0;
2194 pSMB->SetupCount = 1;
2195 pSMB->Reserved3 = 0;
2196 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2197 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
2198 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2199 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2201 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2202 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2204 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
2205 } else { /* decode response */
2206 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2207 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
2208 rc = -EIO; /* bad smb */
2211 (FILE_SYSTEM_ATTRIBUTE_INFO
2212 *) (((char *) &pSMBr->hdr.Protocol) +
2214 memcpy(&tcon->fsAttrInfo, response_data,
2215 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
2219 cifs_buf_release(pSMB);
2222 goto QFSAttributeRetry;
2228 CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
2229 const struct nls_table *nls_codepage)
2231 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
2232 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2233 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2234 FILE_SYSTEM_DEVICE_INFO *response_data;
2236 int bytes_returned = 0;
2238 cFYI(1, ("In QFSDeviceInfo"));
2240 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2245 pSMB->TotalParameterCount = 2; /* level */
2246 pSMB->TotalDataCount = 0;
2247 pSMB->MaxParameterCount = cpu_to_le16(2);
2248 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2249 pSMB->MaxSetupCount = 0;
2253 pSMB->Reserved2 = 0;
2254 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
2255 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
2256 pSMB->ParameterCount = pSMB->TotalParameterCount;
2257 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2258 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2260 pSMB->DataCount = 0;
2261 pSMB->DataOffset = 0;
2262 pSMB->SetupCount = 1;
2263 pSMB->Reserved3 = 0;
2264 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2265 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
2266 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2267 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2269 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2270 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2272 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
2273 } else { /* decode response */
2274 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
2275 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
2276 || (pSMBr->DataOffset > 512))
2277 rc = -EIO; /* bad smb */
2280 (FILE_SYSTEM_DEVICE_INFO
2281 *) (((char *) &pSMBr->hdr.Protocol) +
2283 memcpy(&tcon->fsDevInfo, response_data,
2284 sizeof (FILE_SYSTEM_DEVICE_INFO));
2288 cifs_buf_release(pSMB);
2291 goto QFSDeviceRetry;
2298 CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
2299 const struct nls_table *nls_codepage)
2301 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
2302 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2303 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2304 FILE_SYSTEM_UNIX_INFO *response_data;
2306 int bytes_returned = 0;
2308 cFYI(1, ("In QFSUnixInfo"));
2310 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2315 pSMB->ParameterCount = 2; /* level */
2316 pSMB->TotalDataCount = 0;
2317 pSMB->DataCount = 0;
2318 pSMB->DataOffset = 0;
2319 pSMB->MaxParameterCount = cpu_to_le16(2);
2320 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
2321 pSMB->MaxSetupCount = 0;
2325 pSMB->Reserved2 = 0;
2326 pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
2327 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2328 pSMB->TotalParameterCount = pSMB->ParameterCount;
2329 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
2330 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2331 pSMB->SetupCount = 1;
2332 pSMB->Reserved3 = 0;
2333 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2334 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2335 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2336 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2338 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2339 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2341 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2342 } else { /* decode response */
2343 pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
2344 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
2345 rc = -EIO; /* bad smb */
2348 (FILE_SYSTEM_UNIX_INFO
2349 *) (((char *) &pSMBr->hdr.Protocol) +
2351 memcpy(&tcon->fsUnixInfo, response_data,
2352 sizeof (FILE_SYSTEM_UNIX_INFO));
2356 cifs_buf_release(pSMB);
2365 /* We can not use write of zero bytes trick to
2366 set file size due to need for large file support. Also note that
2367 this SetPathInfo is preferred to SetFileInfo based method in next
2368 routine which is only needed to work around a sharing violation bug
2369 in Samba which this routine can run into */
2372 CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
2373 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2375 struct smb_com_transaction2_spi_req *pSMB = NULL;
2376 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2377 struct file_end_of_file_info *parm_data;
2380 int bytes_returned = 0;
2382 cFYI(1, ("In SetEOF"));
2384 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2389 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2391 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2392 /* find define for this maxpathcomponent */
2394 name_len++; /* trailing null */
2396 } else { /* BB improve the check for buffer overruns BB */
2397 name_len = strnlen(fileName, 530);
2398 name_len++; /* trailing null */
2399 strncpy(pSMB->FileName, fileName, name_len);
2401 pSMB->ParameterCount = 6 + name_len;
2402 pSMB->DataCount = sizeof (struct file_end_of_file_info);
2403 pSMB->MaxParameterCount = cpu_to_le16(2);
2404 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2405 pSMB->MaxSetupCount = 0;
2409 pSMB->Reserved2 = 0;
2410 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2411 InformationLevel) - 4;
2412 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2414 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2415 pSMB->InformationLevel =
2416 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2418 pSMB->InformationLevel =
2419 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2420 } else /* Set File Size */ {
2421 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2422 pSMB->InformationLevel =
2423 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2425 pSMB->InformationLevel =
2426 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2430 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2432 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2433 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2434 pSMB->SetupCount = 1;
2435 pSMB->Reserved3 = 0;
2436 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2437 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2438 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2439 pSMB->TotalDataCount = pSMB->DataCount;
2440 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2441 pSMB->TotalParameterCount = pSMB->ParameterCount;
2442 pSMB->Reserved4 = 0;
2443 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2444 parm_data->FileSize = cpu_to_le64(size);
2445 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2446 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2447 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2449 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2453 cifs_buf_release(pSMB);
2462 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
2463 __u16 fid, __u32 pid_of_opener, int SetAllocation)
2465 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2466 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2468 struct file_end_of_file_info *parm_data;
2470 int bytes_returned = 0;
2473 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
2475 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2480 tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
2481 so network fid will be valid */
2482 pSMB->hdr.Pid = tmp & 0xFFFF;
2484 pSMB->hdr.PidHigh = tmp & 0xFFFF;
2486 pSMB->ParameterCount = 6;
2487 pSMB->MaxSetupCount = 0;
2491 pSMB->Reserved2 = 0;
2492 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
2494 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2496 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2498 pSMB->DataCount = sizeof(struct file_end_of_file_info);
2499 pSMB->MaxParameterCount = cpu_to_le16(2);
2500 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2501 pSMB->SetupCount = 1;
2502 pSMB->Reserved3 = 0;
2503 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2504 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2505 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2506 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2507 pSMB->TotalDataCount = pSMB->DataCount;
2508 pSMB->TotalParameterCount = pSMB->ParameterCount;
2509 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2511 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2513 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset); /* now safe to change to le */
2514 parm_data->FileSize = size;
2517 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2518 pSMB->InformationLevel =
2519 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2521 pSMB->InformationLevel =
2522 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2523 } else /* Set File Size */ {
2524 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2525 pSMB->InformationLevel =
2526 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2528 pSMB->InformationLevel =
2529 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2531 pSMB->Reserved4 = 0;
2532 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2533 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2534 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2535 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2538 ("Send error in SetFileInfo (SetFileSize) = %d",
2543 cifs_buf_release(pSMB);
2545 /* Note: On -EAGAIN error only caller can retry on handle based calls
2546 since file handle passed in no longer valid */
2552 CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
2553 FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
2555 TRANSACTION2_SPI_REQ *pSMB = NULL;
2556 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2559 int bytes_returned = 0;
2562 cFYI(1, ("In SetTimes"));
2565 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2570 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2572 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2573 /* find define for this maxpathcomponent */
2575 name_len++; /* trailing null */
2577 } else { /* BB improve the check for buffer overruns BB */
2578 name_len = strnlen(fileName, 530);
2579 name_len++; /* trailing null */
2580 strncpy(pSMB->FileName, fileName, name_len);
2583 pSMB->ParameterCount = 6 + name_len;
2584 pSMB->DataCount = sizeof (FILE_BASIC_INFO);
2585 pSMB->MaxParameterCount = cpu_to_le16(2);
2586 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2587 pSMB->MaxSetupCount = 0;
2591 pSMB->Reserved2 = 0;
2592 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2593 InformationLevel) - 4;
2594 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2595 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2596 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2597 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2598 pSMB->SetupCount = 1;
2599 pSMB->Reserved3 = 0;
2600 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2601 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2603 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2604 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2605 pSMB->TotalDataCount = pSMB->DataCount;
2606 pSMB->TotalParameterCount = pSMB->ParameterCount;
2607 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2608 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2610 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2611 pSMB->Reserved4 = 0;
2612 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2613 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2614 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2615 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2616 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2618 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2622 cifs_buf_release(pSMB);
2631 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2632 char *fileName, __u64 mode, __u64 uid, __u64 gid,
2633 dev_t device, const struct nls_table *nls_codepage)
2635 TRANSACTION2_SPI_REQ *pSMB = NULL;
2636 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2639 int bytes_returned = 0;
2640 FILE_UNIX_BASIC_INFO *data_offset;
2642 cFYI(1, ("In SetUID/GID/Mode"));
2644 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2649 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2651 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2652 /* find define for this maxpathcomponent */
2654 name_len++; /* trailing null */
2656 } else { /* BB improve the check for buffer overruns BB */
2657 name_len = strnlen(fileName, 530);
2658 name_len++; /* trailing null */
2659 strncpy(pSMB->FileName, fileName, name_len);
2662 pSMB->ParameterCount = 6 + name_len;
2663 pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
2664 pSMB->MaxParameterCount = cpu_to_le16(2);
2665 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2666 pSMB->MaxSetupCount = 0;
2670 pSMB->Reserved2 = 0;
2671 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2672 InformationLevel) - 4;
2673 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2675 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2677 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2678 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2679 pSMB->SetupCount = 1;
2680 pSMB->Reserved3 = 0;
2681 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2682 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2683 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2684 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2685 pSMB->TotalParameterCount = pSMB->ParameterCount;
2686 pSMB->TotalDataCount = pSMB->DataCount;
2687 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2688 pSMB->Reserved4 = 0;
2689 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2690 data_offset->Uid = cpu_to_le64(uid);
2691 data_offset->Gid = cpu_to_le64(gid);
2692 /* better to leave device as zero when it is */
2693 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2694 data_offset->DevMinor = cpu_to_le64(MINOR(device));
2695 data_offset->Permissions = cpu_to_le64(mode);
2696 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2697 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2698 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2700 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
2704 cifs_buf_release(pSMB);