4 * Copyright (c) International Business Machines Corp., 2002
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 */
27 #include <linux/kernel.h>
28 #include <linux/vfs.h>
29 #include <asm/uaccess.h>
32 #include "cifsproto.h"
33 #include "cifs_unicode.h"
34 #include "cifs_debug.h"
41 CIFS_PROT, "\2NT LM 0.12"}, {
46 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
47 void **request_buf /* returned */ ,
48 void **response_buf /* returned */ )
52 if(tcon && (tcon->tidStatus == CifsNeedReconnect)) {
55 struct nls_table *nls_codepage = load_nls_default();
56 if(tcon->ses->status == CifsNeedReconnect)
57 rc = setup_session(0, tcon->ses, nls_codepage);
59 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
61 cFYI(1, ("reconnect tcon rc = %d", rc));
63 reopen_files(tcon,nls_codepage);
70 *request_buf = buf_get();
71 if (request_buf == 0) {
74 /* Although the original thought was we needed the response buf for */
75 /* potential retries of smb operations it turns out we can determine */
76 /* from the mid flags when the request buffer can be resent without */
77 /* having to use a second distinct buffer for the response */
78 *response_buf = *request_buf;
80 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
86 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
92 struct TCP_Server_Info * server;
101 rc = smb_init(SMB_COM_NEGOTIATE, 0, 0 /* no tcon yet */ ,
102 (void **) &pSMB, (void **) &pSMBr);
106 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
107 if (extended_security)
108 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
110 pSMB->ByteCount = strlen(protocols[0].name) + 1;
111 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
112 /* null guaranteed to be at end of source and target buffers anyway */
114 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
115 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
117 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
118 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
120 server->secMode = pSMBr->SecurityMode;
121 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
122 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
123 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
124 /* probably no need to store and check maxvcs */
126 min(le32_to_cpu(pSMBr->MaxBufferSize),
127 (__u32) CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE);
128 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
129 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
130 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
131 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
132 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
133 /* BB with UTC do we ever need to be using srvr timezone? */
134 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
135 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
136 CIFS_CRYPTO_KEY_SIZE);
137 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
138 && (pSMBr->EncryptionKeyLength == 0)) {
139 /* decode security blob */
143 /* BB might be helpful to save off the domain of server here */
145 if (pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) {
146 if (pSMBr->ByteCount < 16)
148 else if (pSMBr->ByteCount == 16) {
149 server->secType = RawNTLMSSP;
150 if (server->socketUseCount.counter > 1) {
152 (server->server_GUID,
153 pSMBr->u.extended_response.
156 ("UID of server does not match previous connection to same ip address"));
164 memcpy(server->server_GUID,
165 pSMBr->u.extended_response.
168 rc = decode_negTokenInit(pSMBr->u.
172 16, &server->secType);
176 server->capabilities &= ~CAP_EXTENDED_SECURITY;
177 if(sign_CIFS_PDUs == FALSE) {
178 if(server->secMode & SECMODE_SIGN_REQUIRED)
180 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
181 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
182 } else if(sign_CIFS_PDUs == 1) {
183 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
184 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
194 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
196 struct smb_hdr *smb_buffer;
197 struct smb_hdr *smb_buffer_response;
201 cFYI(1, ("In tree disconnect"));
203 * If last user of the connection and
204 * connection alive - disconnect it
205 * If this is the last connection on the server session disconnect it
206 * (and inside session disconnect we should check if tcp socket needs
207 * to be freed and kernel thread woken up).
210 down(&tcon->tconSem);
214 atomic_dec(&tcon->useCount);
215 if (atomic_read(&tcon->useCount) > 0) {
220 /* BB remove (from server) list of shares - but with smp safety BB */
221 /* BB is ses active - do we need to check here - but how? BB */
222 if((tcon->ses == 0) || (tcon->ses->server == 0)) {
227 rc = smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
228 (void **) &smb_buffer, (void **) &smb_buffer_response);
233 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
236 cFYI(1, (" Tree disconnect failed %d", rc));
239 buf_release(smb_buffer);
245 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
247 struct smb_hdr *smb_buffer_response;
248 LOGOFF_ANDX_REQ *pSMB;
252 cFYI(1, ("In SMBLogoff for session disconnect"));
255 down(&ses->sesSem); /* check this sem more places */
259 atomic_dec(&ses->inUse);
260 if (atomic_read(&ses->inUse) > 0) {
265 rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
266 (void **) &pSMB, (void **) &smb_buffer_response);
268 if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
269 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
276 pSMB->hdr.Uid = ses->Suid;
278 pSMB->AndXCommand = 0xFF;
279 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
280 smb_buffer_response, &length, 0);
282 atomic_dec(&ses->server->socketUseCount);
283 if (atomic_read(&ses->server->socketUseCount) == 0)
284 ses->server->tcpStatus = CifsExiting;
293 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
294 const char *fileName, const struct nls_table *nls_codepage)
296 DELETE_FILE_REQ *pSMB = NULL;
297 DELETE_FILE_RSP *pSMBr = NULL;
302 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
307 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
309 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, 530
310 /* find define for this maxpathcomponent */
312 name_len++; /* trailing null */
314 } else { /* BB improve the check for buffer overruns BB */
315 name_len = strnlen(fileName, 530);
316 name_len++; /* trailing null */
317 strncpy(pSMB->fileName, fileName, name_len);
319 pSMB->SearchAttributes =
320 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
321 pSMB->ByteCount = name_len + 1;
322 pSMB->BufferFormat = 0x04;
323 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
324 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
325 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
326 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
328 cFYI(1, ("Error in RMFile = %d", rc));
336 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
337 const char *dirName, const struct nls_table *nls_codepage)
339 DELETE_DIRECTORY_REQ *pSMB = NULL;
340 DELETE_DIRECTORY_RSP *pSMBr = NULL;
345 cFYI(1, ("In CIFSSMBRmDir"));
347 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
352 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
353 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, 530
354 /* find define for this maxpathcomponent */
356 name_len++; /* trailing null */
358 } else { /* BB improve the check for buffer overruns BB */
359 name_len = strnlen(dirName, 530);
360 name_len++; /* trailing null */
361 strncpy(pSMB->DirName, dirName, name_len);
364 pSMB->ByteCount = name_len + 1;
365 pSMB->BufferFormat = 0x04;
366 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
367 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
368 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
369 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
371 cFYI(1, ("Error in RMDir = %d", rc));
379 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
380 const char *name, const struct nls_table *nls_codepage)
383 CREATE_DIRECTORY_REQ *pSMB = NULL;
384 CREATE_DIRECTORY_RSP *pSMBr = NULL;
388 cFYI(1, ("In CIFSSMBMkDir"));
390 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
395 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
396 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, 530
397 /* find define for this maxpathcomponent */
399 name_len++; /* trailing null */
401 } else { /* BB improve the check for buffer overruns BB */
402 name_len = strnlen(name, 530);
403 name_len++; /* trailing null */
404 strncpy(pSMB->DirName, name, name_len);
407 pSMB->ByteCount = name_len + 1 /* for buf format */ ;
408 pSMB->BufferFormat = 0x04;
409 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
410 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
411 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
412 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
414 cFYI(1, ("Error in Mkdir = %d", rc));
423 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
424 const char *fileName, const int openDisposition,
425 const int access_flags, const int create_options, __u16 * netfid,
426 int *pOplock, FILE_ALL_INFO * pfile_info,
427 const struct nls_table *nls_codepage)
430 OPEN_REQ *pSMB = NULL;
431 OPEN_RSP *pSMBr = NULL;
435 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
440 pSMB->AndXCommand = 0xFF; /* none */
442 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
443 pSMB->ByteCount = 1; /* account for one byte pad to word boundary */
445 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
447 /* find define for this maxpathcomponent */
449 name_len++; /* trailing null */
451 pSMB->NameLength = cpu_to_le16(name_len);
452 } else { /* BB improve the check for buffer overruns BB */
453 pSMB->ByteCount = 0; /* no pad */
454 name_len = strnlen(fileName, 530);
455 name_len++; /* trailing null */
456 pSMB->NameLength = cpu_to_le16(name_len);
457 strncpy(pSMB->fileName, fileName, name_len);
459 if (*pOplock & REQ_OPLOCK)
460 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
461 else if (*pOplock & REQ_BATCHOPLOCK) {
462 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
464 pSMB->DesiredAccess = cpu_to_le32(access_flags);
465 pSMB->AllocationSize = 0;
466 pSMB->FileAttributes = ATTR_NORMAL; /* XP does not handle ATTR_POSIX_SEMANTICS */
467 /*if ((omode & S_IWUGO) == 0)
468 pSMB->FileAttributes |= ATTR_READONLY;*/
469 /* Above line causes problems due to vfs splitting create into two
470 pieces - need to set mode after file created not while it is
472 pSMB->FileAttributes = cpu_to_le32(pSMB->FileAttributes);
473 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
474 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
475 pSMB->CreateOptions = cpu_to_le32(create_options);
476 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
477 pSMB->SecurityFlags =
478 cpu_to_le32(SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY);
480 pSMB->ByteCount += name_len;
481 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
483 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
484 /* long_op set to 1 to allow for oplock break timeouts */
485 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
486 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
488 cFYI(1, ("Error in Open = %d", rc));
490 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
491 *netfid = pSMBr->Fid; /* cifs fid stays in le */
492 /* Do we care about the CreateAction in any cases? */
494 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
495 36 /* CreationTime to Attributes */);
496 /* the file_info buf is endian converted by caller */
497 pfile_info->AllocationSize = pSMBr->AllocationSize;
498 pfile_info->EndOfFile = pSMBr->EndOfFile;
499 pfile_info->NumberOfLinks = cpu_to_le32(1);
508 /* If no buffer passed in, then caller wants to do the copy
509 as in the case of readpages so the SMB buffer must be
510 freed by the caller */
513 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
514 const int netfid, const unsigned int count,
515 const __u64 lseek, unsigned int *nbytes, char **buf)
518 READ_REQ *pSMB = NULL;
519 READ_RSP *pSMBr = NULL;
520 char *pReadData = NULL;
524 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
529 pSMB->AndXCommand = 0xFF; /* none */
531 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
532 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
534 pSMB->MaxCount = cpu_to_le16(count);
535 pSMB->MaxCountHigh = 0;
536 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
538 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
539 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
541 cERROR(1, ("Send error in read = %d", rc));
543 pSMBr->DataLength = le16_to_cpu(pSMBr->DataLength);
544 *nbytes = pSMBr->DataLength;
545 /*check that DataLength would not go beyond end of SMB */
546 if ((pSMBr->DataLength > CIFS_MAX_MSGSIZE)
547 || (pSMBr->DataLength > count)) {
548 cFYI(1,("bad length %d for count %d",pSMBr->DataLength,count));
553 (char *) (&pSMBr->hdr.Protocol) +
554 le16_to_cpu(pSMBr->DataOffset);
555 /* if(rc = copy_to_user(buf, pReadData, pSMBr->DataLength)) {
556 cERROR(1,("Faulting on read rc = %d",rc));
558 }*/ /* can not use copy_to_user when using page cache*/
560 memcpy(*buf,pReadData,pSMBr->DataLength);
573 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
574 const int netfid, const unsigned int count,
575 const __u64 offset, unsigned int *nbytes, const char *buf,
579 WRITE_REQ *pSMB = NULL;
580 WRITE_RSP *pSMBr = NULL;
583 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
588 pSMB->AndXCommand = 0xFF; /* none */
590 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
591 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
593 if (count > ((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00))
594 pSMB->DataLengthLow =
595 (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00;
597 pSMB->DataLengthLow = count;
598 pSMB->DataLengthHigh = 0;
600 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
602 memcpy(pSMB->Data,buf,pSMB->DataLengthLow);
604 pSMB->ByteCount += pSMB->DataLengthLow + 1 /* pad */ ;
605 pSMB->DataLengthLow = cpu_to_le16(pSMB->DataLengthLow);
606 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
607 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
610 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
612 cERROR(1, ("Send error in write = %d", rc));
615 *nbytes = le16_to_cpu(pSMBr->Count);
624 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
625 const __u16 smb_file_id, const __u64 len,
626 const __u64 offset, const __u32 numUnlock,
627 const __u32 numLock, const __u8 lockType, const int waitFlag)
630 LOCK_REQ *pSMB = NULL;
631 LOCK_RSP *pSMBr = NULL;
635 cFYI(1, ("In CIFSSMBLock"));
637 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
642 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE)
643 timeout = -1; /* no response expected */
645 pSMB->NumberOfLocks = cpu_to_le32(numLock);
646 pSMB->NumberOfUnlocks = cpu_to_le32(numUnlock);
647 pSMB->LockType = lockType;
648 pSMB->AndXCommand = 0xFF; /* none */
649 pSMB->Fid = smb_file_id; /* netfid stays le */
651 pSMB->Locks[0].Pid = cpu_to_le16(current->pid);
652 pSMB->Locks[0].Length = cpu_to_le64(len);
653 pSMB->Locks[0].Offset = cpu_to_le64(offset);
654 pSMB->ByteCount = sizeof (LOCKING_ANDX_RANGE);
655 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
656 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
658 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
659 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
662 cERROR(1, ("Send error in Lock = %d", rc));
671 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
674 CLOSE_REQ *pSMB = NULL;
675 CLOSE_RSP *pSMBr = NULL;
677 cFYI(1, ("In CIFSSMBClose"));
679 rc = smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB,
684 pSMB->FileID = (__u16) smb_file_id;
685 pSMB->LastWriteTime = 0;
687 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
688 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
690 cERROR(1, ("Send error in Close = %d", rc));
699 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
700 const char *fromName, const char *toName,
701 const struct nls_table *nls_codepage)
704 RENAME_REQ *pSMB = NULL;
705 RENAME_RSP *pSMBr = NULL;
707 int name_len, name_len2;
709 cFYI(1, ("In CIFSSMBRename"));
711 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
716 pSMB->BufferFormat = 0x04;
717 pSMB->SearchAttributes =
718 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
721 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
723 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
724 /* find define for this maxpathcomponent */
726 name_len++; /* trailing null */
728 pSMB->OldFileName[name_len] = 0x04; /* pad */
729 /* protocol requires ASCII signature byte on Unicode string */
730 pSMB->OldFileName[name_len + 1] = 0x00;
732 cifs_strtoUCS((wchar_t *) & pSMB->
733 OldFileName[name_len + 2], toName, 530,
735 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
736 name_len2 *= 2; /* convert to bytes */
737 } else { /* BB improve the check for buffer overruns BB */
738 name_len = strnlen(fromName, 530);
739 name_len++; /* trailing null */
740 strncpy(pSMB->OldFileName, fromName, name_len);
741 name_len2 = strnlen(toName, 530);
742 name_len2++; /* trailing null */
743 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
744 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
745 name_len2++; /* trailing null */
746 name_len2++; /* signature byte */
749 pSMB->ByteCount = 1 /* 1st signature byte */ + name_len + name_len2;
750 /* we could also set search attributes but not needed */
751 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
752 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
754 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
755 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
757 cFYI(1, ("Send error in RMDir = %d", rc));
766 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
767 const char *fromName, const char *toName,
768 const struct nls_table *nls_codepage)
770 TRANSACTION2_SPI_REQ *pSMB = NULL;
771 TRANSACTION2_SPI_RSP *pSMBr = NULL;
776 int bytes_returned = 0;
778 cFYI(1, ("In Symlink Unix style"));
780 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
785 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
787 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, 530
788 /* find define for this maxpathcomponent */
790 name_len++; /* trailing null */
793 } else { /* BB improve the check for buffer overruns BB */
794 name_len = strnlen(fromName, 530);
795 name_len++; /* trailing null */
796 strncpy(pSMB->FileName, fromName, name_len);
798 pSMB->ParameterCount = 6 + name_len;
799 pSMB->MaxSetupCount = 0;
804 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
805 InformationLevel) - 4;
806 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
808 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
809 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
811 cifs_strtoUCS((wchar_t *) data_offset, toName, 530
812 /* find define for this maxpathcomponent */
814 name_len_target++; /* trailing null */
815 name_len_target *= 2;
816 } else { /* BB improve the check for buffer overruns BB */
817 name_len_target = strnlen(toName, 530);
818 name_len_target++; /* trailing null */
819 strncpy(data_offset, toName, name_len_target);
822 pSMB->DataCount = name_len_target;
823 pSMB->MaxParameterCount = cpu_to_le16(2);
824 /* BB find exact max on data count below from sess */
825 pSMB->MaxDataCount = cpu_to_le16(1000);
826 pSMB->SetupCount = 1;
828 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
829 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
830 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
831 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
832 pSMB->TotalDataCount = pSMB->DataCount;
833 pSMB->TotalParameterCount = pSMB->ParameterCount;
834 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
835 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
836 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
838 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
839 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
840 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
841 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
844 ("Send error in SetPathInfo (create symlink) = %d",
854 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
855 const char *fromName, const char *toName,
856 const struct nls_table *nls_codepage)
858 TRANSACTION2_SPI_REQ *pSMB = NULL;
859 TRANSACTION2_SPI_RSP *pSMBr = NULL;
864 int bytes_returned = 0;
866 cFYI(1, ("In Create Hard link Unix style"));
868 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
873 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
874 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, 530
875 /* find define for this maxpathcomponent */
877 name_len++; /* trailing null */
880 } else { /* BB improve the check for buffer overruns BB */
881 name_len = strnlen(toName, 530);
882 name_len++; /* trailing null */
883 strncpy(pSMB->FileName, toName, name_len);
885 pSMB->ParameterCount = 6 + name_len;
886 pSMB->MaxSetupCount = 0;
891 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
892 InformationLevel) - 4;
893 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
895 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
896 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
898 cifs_strtoUCS((wchar_t *) data_offset, fromName, 530
899 /* find define for this maxpathcomponent */
901 name_len_target++; /* trailing null */
902 name_len_target *= 2;
903 } else { /* BB improve the check for buffer overruns BB */
904 name_len_target = strnlen(fromName, 530);
905 name_len_target++; /* trailing null */
906 strncpy(data_offset, fromName, name_len_target);
909 pSMB->DataCount = name_len_target;
910 pSMB->MaxParameterCount = cpu_to_le16(2);
911 /* BB find exact max on data count below from sess*/
912 pSMB->MaxDataCount = cpu_to_le16(1000);
913 pSMB->SetupCount = 1;
915 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
916 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
917 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
918 pSMB->TotalParameterCount = pSMB->ParameterCount;
919 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
920 pSMB->TotalDataCount = pSMB->DataCount;
921 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
922 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
923 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
925 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
926 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
927 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
928 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
930 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
939 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
940 const char *fromName, const char *toName,
941 const struct nls_table *nls_codepage)
944 NT_RENAME_REQ *pSMB = NULL;
945 RENAME_RSP *pSMBr = NULL;
947 int name_len, name_len2;
949 cFYI(1, ("In CIFSCreateHardLink"));
951 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
956 pSMB->SearchAttributes =
957 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
959 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
960 pSMB->ClusterCount = 0;
962 pSMB->BufferFormat = 0x04;
964 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
966 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, 530
967 /* find define for this maxpathcomponent */
969 name_len++; /* trailing null */
971 pSMB->OldFileName[name_len] = 0; /* pad */
972 pSMB->OldFileName[name_len + 1] = 0x04;
974 cifs_strtoUCS((wchar_t *) & pSMB->
975 OldFileName[name_len + 2], toName, 530,
977 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
978 name_len2 *= 2; /* convert to bytes */
979 } else { /* BB improve the check for buffer overruns BB */
980 name_len = strnlen(fromName, 530);
981 name_len++; /* trailing null */
982 strncpy(pSMB->OldFileName, fromName, name_len);
983 name_len2 = strnlen(toName, 530);
984 name_len2++; /* trailing null */
985 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
986 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
987 name_len2++; /* trailing null */
988 name_len2++; /* signature byte */
991 pSMB->ByteCount = 1 /* string type byte */ + name_len + name_len2;
992 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
993 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
996 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
998 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1007 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1008 const unsigned char *searchName,
1009 char *symlinkinfo, const int buflen,
1010 const struct nls_table *nls_codepage)
1012 /* SMB_QUERY_FILE_UNIX_LINK */
1013 TRANSACTION2_QPI_REQ *pSMB = NULL;
1014 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1019 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1020 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1025 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1027 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1028 /* find define for this maxpathcomponent */
1030 name_len++; /* trailing null */
1032 } else { /* BB improve the check for buffer overruns BB */
1033 name_len = strnlen(searchName, 530);
1034 name_len++; /* trailing null */
1035 strncpy(pSMB->FileName, searchName, name_len);
1038 pSMB->TotalParameterCount =
1039 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1040 pSMB->TotalDataCount = 0;
1041 pSMB->MaxParameterCount = cpu_to_le16(2);
1042 /* BB find exact max data count below from sess structure BB */
1043 pSMB->MaxDataCount = cpu_to_le16(4000);
1044 pSMB->MaxSetupCount = 0;
1048 pSMB->Reserved2 = 0;
1049 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1050 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1051 pSMB->DataCount = 0;
1052 pSMB->DataOffset = 0;
1053 pSMB->SetupCount = 1;
1054 pSMB->Reserved3 = 0;
1055 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1056 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1057 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1058 pSMB->ParameterCount = pSMB->TotalParameterCount;
1059 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1060 pSMB->Reserved4 = 0;
1061 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1062 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1064 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1065 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1067 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1068 } else { /* decode response */
1069 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1070 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1071 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1072 /* BB also check enough total bytes returned */
1073 rc = -EIO; /* bad smb */
1075 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1076 name_len = UniStrnlen((wchar_t *) ((char *)
1077 &pSMBr->hdr.Protocol +pSMBr->DataOffset),
1078 min_t(const int, buflen,pSMBr->DataCount) / 2);
1079 cifs_strfromUCS_le(symlinkinfo,
1080 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1082 name_len, nls_codepage);
1084 strncpy(symlinkinfo,
1085 (char *) &pSMBr->hdr.Protocol +
1087 min_t(const int, buflen, pSMBr->DataCount));
1089 symlinkinfo[buflen] = 0;
1090 /* just in case so calling code does not go off the end of buffer */
1101 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1102 const unsigned char *searchName,
1103 char *symlinkinfo, const int buflen,__u16 fid,
1104 const struct nls_table *nls_codepage)
1109 struct smb_com_transaction_ioctl_req * pSMB;
1110 struct smb_com_transaction_ioctl_rsp * pSMBr;
1112 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1113 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1118 pSMB->TotalParameterCount = 0 ;
1119 pSMB->TotalDataCount = 0;
1120 pSMB->MaxParameterCount = cpu_to_le16(2);
1121 /* BB find exact data count max from sess structure BB */
1122 pSMB->MaxDataCount = cpu_to_le16(4000);
1123 pSMB->MaxSetupCount = 4;
1125 pSMB->ParameterOffset = 0;
1126 pSMB->DataCount = 0;
1127 pSMB->DataOffset = 0;
1128 pSMB->SetupCount = 4;
1129 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1130 pSMB->ParameterCount = pSMB->TotalParameterCount;
1131 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1132 pSMB->IsFsctl = 1; /* FSCTL */
1133 pSMB->IsRootFlag = 0;
1134 pSMB->Fid = fid; /* file handle always le */
1135 pSMB->ByteCount = 0;
1137 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1138 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1140 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1141 } else { /* decode response */
1142 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1143 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1144 if ((pSMBr->ByteCount < 2) || (pSMBr->DataOffset > 512))
1145 /* BB also check enough total bytes returned */
1146 rc = -EIO; /* bad smb */
1148 if(pSMBr->DataCount && (pSMBr->DataCount < 2048)) {
1149 /* could also validate reparse tag && better check name length */
1150 struct reparse_data * reparse_buf = (struct reparse_data *)
1151 ((char *)&pSMBr->hdr.Protocol + pSMBr->DataOffset);
1152 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1153 name_len = UniStrnlen((wchar_t *)
1154 (reparse_buf->LinkNamesBuf +
1155 reparse_buf->TargetNameOffset),
1156 min(buflen/2, reparse_buf->TargetNameLen / 2));
1157 cifs_strfromUCS_le(symlinkinfo,
1158 (wchar_t *) (reparse_buf->LinkNamesBuf +
1159 reparse_buf->TargetNameOffset),
1160 name_len, nls_codepage);
1161 } else { /* ASCII names */
1162 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1163 reparse_buf->TargetNameOffset,
1164 min_t(const int, buflen, reparse_buf->TargetNameLen));
1168 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1170 symlinkinfo[buflen] = 0; /* just in case so the caller
1171 does not go off the end of the buffer */
1172 cFYI(1,("readlink result - %s ",symlinkinfo));
1181 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
1182 const unsigned char *searchName,
1183 FILE_ALL_INFO * pFindData,
1184 const struct nls_table *nls_codepage)
1186 /* level 263 SMB_QUERY_FILE_ALL_INFO */
1187 TRANSACTION2_QPI_REQ *pSMB = NULL;
1188 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1193 cFYI(1, ("In QPathInfo path %s", searchName));
1194 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1199 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1201 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1202 /* find define for this maxpathcomponent */
1204 name_len++; /* trailing null */
1206 } else { /* BB improve the check for buffer overruns BB */
1207 name_len = strnlen(searchName, 530);
1208 name_len++; /* trailing null */
1209 strncpy(pSMB->FileName, searchName, name_len);
1212 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1213 name_len /* includes null */ ;
1214 pSMB->TotalDataCount = 0;
1215 pSMB->MaxParameterCount = cpu_to_le16(2);
1216 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1217 pSMB->MaxSetupCount = 0;
1221 pSMB->Reserved2 = 0;
1222 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1223 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1224 pSMB->DataCount = 0;
1225 pSMB->DataOffset = 0;
1226 pSMB->SetupCount = 1;
1227 pSMB->Reserved3 = 0;
1228 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1229 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1230 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1231 pSMB->ParameterCount = pSMB->TotalParameterCount;
1232 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
1233 pSMB->Reserved4 = 0;
1234 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1235 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1237 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1238 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1240 cFYI(1, ("Send error in QPathInfo = %d", rc));
1241 } else { /* decode response */
1242 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1243 /* BB also check enough total bytes returned */
1244 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1245 rc = -EIO; /* bad smb */
1246 else if (pFindData){
1247 memcpy((char *) pFindData,
1248 (char *) &pSMBr->hdr.Protocol +
1249 pSMBr->DataOffset, sizeof (FILE_ALL_INFO));
1259 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
1260 const unsigned char *searchName,
1261 FILE_UNIX_BASIC_INFO * pFindData,
1262 const struct nls_table *nls_codepage)
1264 /* SMB_QUERY_FILE_UNIX_BASIC */
1265 TRANSACTION2_QPI_REQ *pSMB = NULL;
1266 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1271 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
1272 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1277 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1279 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1280 /* find define for this maxpathcomponent */
1282 name_len++; /* trailing null */
1284 } else { /* BB improve the check for buffer overruns BB */
1285 name_len = strnlen(searchName, 530);
1286 name_len++; /* trailing null */
1287 strncpy(pSMB->FileName, searchName, name_len);
1290 pSMB->TotalParameterCount = 2 /* level */ + 4 /* reserved */ +
1291 name_len /* includes null */ ;
1292 pSMB->TotalDataCount = 0;
1293 pSMB->MaxParameterCount = cpu_to_le16(2);
1294 /* BB find exact max SMB PDU from sess structure BB */
1295 pSMB->MaxDataCount = cpu_to_le16(4000);
1296 pSMB->MaxSetupCount = 0;
1300 pSMB->Reserved2 = 0;
1301 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1302 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1303 pSMB->DataCount = 0;
1304 pSMB->DataOffset = 0;
1305 pSMB->SetupCount = 1;
1306 pSMB->Reserved3 = 0;
1307 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1308 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1309 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1310 pSMB->ParameterCount = pSMB->TotalParameterCount;
1311 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
1312 pSMB->Reserved4 = 0;
1313 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1314 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1316 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1317 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1319 cFYI(1, ("Send error in QPathInfo = %d", rc));
1320 } else { /* decode response */
1321 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1322 /* BB also check if enough total bytes returned */
1323 if ((pSMBr->ByteCount < 40) || (pSMBr->DataOffset > 512))
1324 rc = -EIO; /* bad smb */
1326 memcpy((char *) pFindData,
1327 (char *) &pSMBr->hdr.Protocol +
1329 sizeof (FILE_UNIX_BASIC_INFO));
1338 CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
1339 const char *searchName, FILE_ALL_INFO * findData,
1340 const struct nls_table *nls_codepage)
1342 /* level 257 SMB_ */
1343 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1344 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1349 cFYI(1, ("In FindUnique"));
1350 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1355 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1357 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1358 /* find define for this maxpathcomponent */
1360 name_len++; /* trailing null */
1362 } else { /* BB improve the check for buffer overruns BB */
1363 name_len = strnlen(searchName, 530);
1364 name_len++; /* trailing null */
1365 strncpy(pSMB->FileName, searchName, name_len);
1368 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1369 pSMB->TotalDataCount = 0; /* no EAs */
1370 pSMB->MaxParameterCount = cpu_to_le16(2);
1371 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1372 pSMB->MaxSetupCount = 0;
1376 pSMB->Reserved2 = 0;
1377 pSMB->ParameterOffset = cpu_to_le16(
1378 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
1379 pSMB->DataCount = 0;
1380 pSMB->DataOffset = 0;
1381 pSMB->SetupCount = 1; /* one byte, no need to le convert */
1382 pSMB->Reserved3 = 0;
1383 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1384 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1385 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalDataCount);
1386 pSMB->ParameterCount = pSMB->TotalParameterCount;
1387 pSMB->SearchAttributes =
1388 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1390 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
1391 pSMB->SearchFlags = cpu_to_le16(1);
1392 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1393 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
1394 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1395 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1397 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1398 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1401 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
1402 } else { /* decode response */
1412 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
1413 const char *searchName, FILE_DIRECTORY_INFO * findData,
1414 T2_FFIRST_RSP_PARMS * findParms,
1415 const struct nls_table *nls_codepage, int *pUnicodeFlag,
1418 /* level 257 SMB_ */
1419 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
1420 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
1421 char *response_data;
1426 cFYI(1, ("In FindFirst"));
1427 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1432 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1434 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 530
1435 /* find define for this maxpathcomponent */
1437 name_len++; /* trailing null */
1439 } else { /* BB improve the check for buffer overruns BB */
1440 name_len = strnlen(searchName, 530);
1441 name_len++; /* trailing null */
1442 strncpy(pSMB->FileName, searchName, name_len);
1445 pSMB->TotalParameterCount = 12 + name_len /* includes null */ ;
1446 pSMB->TotalDataCount = 0; /* no EAs */
1447 pSMB->MaxParameterCount = cpu_to_le16(10);
1448 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
1449 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1450 pSMB->MaxSetupCount = 0;
1454 pSMB->Reserved2 = 0;
1455 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1456 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1457 pSMB->ParameterCount = pSMB->TotalParameterCount;
1458 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
1459 smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
1460 pSMB->DataCount = 0;
1461 pSMB->DataOffset = 0;
1462 pSMB->SetupCount = 1; /* one byte no need to make endian neutral */
1463 pSMB->Reserved3 = 0;
1464 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
1465 pSMB->SearchAttributes =
1466 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1468 pSMB->SearchCount = cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO)); /* should this be shrunk even more ? */
1469 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1471 /* test for Unix extensions */
1472 if (tcon->ses->capabilities & CAP_UNIX) {
1473 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1476 pSMB->InformationLevel =
1477 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1480 pSMB->SearchStorageType = 0; /* BB what should we set this to? It is not clear if it matters BB */
1481 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1482 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1484 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1485 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1487 if (rc) { /* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
1488 cFYI(1, ("Error in FindFirst = %d", rc));
1489 } else { /* decode response */
1490 /* BB add safety checks for these memcpys */
1491 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1492 *pUnicodeFlag = TRUE;
1494 *pUnicodeFlag = FALSE;
1496 (char *) &pSMBr->hdr.Protocol +
1497 le16_to_cpu(pSMBr->ParameterOffset),
1498 sizeof (T2_FFIRST_RSP_PARMS));
1499 /* search handle can stay LE and EAoffset not needed so not converted */
1500 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1501 findParms->LastNameOffset =
1502 le16_to_cpu(findParms->LastNameOffset);
1503 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1505 (char *) &pSMBr->hdr.Protocol +
1506 le16_to_cpu(pSMBr->DataOffset);
1507 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1515 CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
1516 FILE_DIRECTORY_INFO * findData, T2_FNEXT_RSP_PARMS * findParms,
1517 const __u16 searchHandle, char * resume_file_name, int name_len,
1518 __u32 resume_key, int *pUnicodeFlag, int *pUnixFlag)
1520 /* level 257 SMB_ */
1521 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
1522 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
1523 char *response_data;
1527 cFYI(1, ("In FindNext"));
1528 if(resume_file_name == NULL) {
1531 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1536 pSMB->TotalParameterCount = 14; /* includes 2 bytes of null string, converted to LE below */
1537 pSMB->TotalDataCount = 0; /* no EAs */
1538 pSMB->MaxParameterCount = cpu_to_le16(8);
1539 pSMB->MaxDataCount =
1540 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
1541 pSMB->MaxSetupCount = 0;
1545 pSMB->Reserved2 = 0;
1546 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1547 struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
1548 pSMB->DataCount = 0;
1549 pSMB->DataOffset = 0;
1550 pSMB->SetupCount = 1;
1551 pSMB->Reserved3 = 0;
1552 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
1553 pSMB->SearchHandle = searchHandle; /* always kept as le */
1554 findParms->SearchCount = 0; /* set to zero in case of error */
1556 cpu_to_le16(CIFS_MAX_MSGSIZE / sizeof (FILE_DIRECTORY_INFO));
1557 /* test for Unix extensions */
1558 if (tcon->ses->capabilities & CAP_UNIX) {
1559 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
1562 pSMB->InformationLevel =
1563 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
1566 pSMB->ResumeKey = resume_key;
1568 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
1569 /* BB add check to make sure we do not cross end of smb */
1570 if(name_len < CIFS_MAX_MSGSIZE) {
1571 memcpy(pSMB->ResumeFileName, resume_file_name, name_len);
1572 pSMB->ByteCount += name_len;
1574 pSMB->TotalParameterCount += name_len;
1575 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1576 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1577 pSMB->ParameterCount = pSMB->TotalParameterCount;
1578 /* BB improve error handling here */
1579 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1580 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1582 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1583 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1587 rc = 0; /* search probably was closed at end of search above */
1589 cFYI(1, ("FindNext returned = %d", rc));
1590 } else { /* decode response */
1591 /* BB add safety checks for these memcpys */
1592 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
1593 *pUnicodeFlag = TRUE;
1595 *pUnicodeFlag = FALSE;
1597 (char *) &pSMBr->hdr.Protocol +
1598 le16_to_cpu(pSMBr->ParameterOffset),
1599 sizeof (T2_FNEXT_RSP_PARMS));
1600 findParms->EndofSearch = le16_to_cpu(findParms->EndofSearch);
1601 findParms->LastNameOffset =
1602 le16_to_cpu(findParms->LastNameOffset);
1603 findParms->SearchCount = le16_to_cpu(findParms->SearchCount);
1605 (char *) &pSMBr->hdr.Protocol +
1606 le16_to_cpu(pSMBr->DataOffset);
1607 memcpy(findData, response_data, le16_to_cpu(pSMBr->DataCount));
1615 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
1618 FINDCLOSE_REQ *pSMB = NULL;
1619 CLOSE_RSP *pSMBr = NULL;
1621 cFYI(1, ("In CIFSSMBFindClose"));
1623 rc = smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **) &pSMB,
1628 pSMB->FileID = searchHandle;
1629 pSMB->ByteCount = 0;
1630 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1631 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1633 cERROR(1, ("Send error in FindClose = %d", rc));
1642 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
1643 const unsigned char *searchName,
1644 unsigned char **targetUNCs,
1645 unsigned int *number_of_UNC_in_array,
1646 const struct nls_table *nls_codepage)
1648 /* TRANS2_GET_DFS_REFERRAL */
1649 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
1650 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
1651 struct dfs_referral_level_3 * referrals = NULL;
1657 *number_of_UNC_in_array = 0;
1660 cFYI(1, ("In GetDFSRefer the path %s", searchName));
1664 rc = smb_init(SMB_COM_TRANSACTION2, 15, 0, (void **) &pSMB,
1669 pSMB->hdr.Tid = ses->ipc_tid;
1670 pSMB->hdr.Uid = ses->Suid;
1671 if (ses->capabilities & CAP_STATUS32) {
1672 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
1674 if (ses->capabilities & CAP_DFS) {
1675 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
1678 if (ses->capabilities & CAP_UNICODE) {
1679 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
1681 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
1683 /* find define for this maxpathcomponent */
1685 name_len++; /* trailing null */
1687 } else { /* BB improve the check for buffer overruns BB */
1688 name_len = strnlen(searchName, 530);
1689 name_len++; /* trailing null */
1690 strncpy(pSMB->RequestFileName, searchName, name_len);
1693 pSMB->ParameterCount = 2 /* level */ + name_len /*includes null */ ;
1694 pSMB->TotalDataCount = 0;
1695 pSMB->DataCount = 0;
1696 pSMB->DataOffset = 0;
1697 pSMB->MaxParameterCount = 0;
1698 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
1699 pSMB->MaxSetupCount = 0;
1703 pSMB->Reserved2 = 0;
1704 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1705 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
1706 pSMB->SetupCount = 1;
1707 pSMB->Reserved3 = 0;
1708 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
1709 pSMB->ByteCount = pSMB->ParameterCount + 3 /* pad */ ;
1710 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
1711 pSMB->TotalParameterCount = pSMB->ParameterCount;
1712 pSMB->MaxReferralLevel = cpu_to_le16(3);
1713 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1714 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1716 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
1717 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1719 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
1720 } else { /* decode response */
1721 /* BB Add logic to parse referrals here */
1722 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1723 pSMBr->DataCount = le16_to_cpu(pSMBr->DataCount);
1725 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
1726 pSMBr->ByteCount, pSMBr->DataOffset));
1727 if ((pSMBr->ByteCount < 17) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
1728 rc = -EIO; /* bad smb */
1731 (struct dfs_referral_level_3 *)
1732 (8 /* sizeof start of data block */ +
1734 (char *) &pSMBr->hdr.Protocol);
1735 cFYI(1,("num_referrals: %d dfs flags: 0x%x ... \nfor referral one refer size: 0x%x srv type: 0x%x refer flags: 0x%x ttl: 0x%x",pSMBr->NumberOfReferrals,pSMBr->DFSFlags, referrals->ReferralSize,referrals->ServerType,referrals->ReferralFlags,referrals->TimeToLive));
1736 /* BB This field is actually two bytes in from start of
1737 data block so we could do safety check that DataBlock
1738 begins at address of pSMBr->NumberOfReferrals */
1739 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
1741 /* BB Fix below so can return more than one referral */
1742 if(*number_of_UNC_in_array > 1)
1743 *number_of_UNC_in_array = 1;
1745 /* get the length of the strings describing refs */
1747 for(i=0;i<*number_of_UNC_in_array;i++) {
1748 /* make sure that DfsPathOffset not past end */
1749 referrals->DfsPathOffset = le16_to_cpu(referrals->DfsPathOffset);
1750 if(referrals->DfsPathOffset > pSMBr->DataCount) {
1751 /* if invalid referral, stop here and do
1752 not try to copy any more */
1753 *number_of_UNC_in_array = i;
1756 temp = ((char *)referrals) + referrals->DfsPathOffset;
1758 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1759 name_len += UniStrnlen((wchar_t *)temp,pSMBr->DataCount);
1761 name_len += strnlen(temp,pSMBr->DataCount);
1764 /* BB add check that referral pointer does not fall off end PDU */
1767 /* BB add check for name_len bigger than bcc */
1769 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
1770 /* copy the ref strings */
1772 (struct dfs_referral_level_3 *)
1773 (8 /* sizeof data hdr */ +
1775 (char *) &pSMBr->hdr.Protocol);
1777 for(i=0;i<*number_of_UNC_in_array;i++) {
1778 temp = ((char *)referrals) + referrals->DfsPathOffset;
1779 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1780 cifs_strfromUCS_le(*targetUNCs,
1781 (wchar_t *) temp, name_len, nls_codepage);
1783 strncpy(*targetUNCs,temp,name_len);
1785 /* BB update target_uncs pointers */
1799 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
1800 struct kstatfs *FSData, const struct nls_table *nls_codepage)
1802 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
1803 TRANSACTION2_QFSI_REQ *pSMB = NULL;
1804 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1805 FILE_SYSTEM_INFO *response_data;
1807 int bytes_returned = 0;
1809 cFYI(1, ("In QFSInfo"));
1811 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1816 pSMB->TotalParameterCount = 2; /* level */
1817 pSMB->TotalDataCount = 0;
1818 pSMB->MaxParameterCount = cpu_to_le16(2);
1819 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1820 pSMB->MaxSetupCount = 0;
1824 pSMB->Reserved2 = 0;
1825 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1826 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1827 pSMB->ParameterCount = pSMB->TotalParameterCount;
1828 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1829 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1830 pSMB->DataCount = 0;
1831 pSMB->DataOffset = 0;
1832 pSMB->SetupCount = 1;
1833 pSMB->Reserved3 = 0;
1834 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1835 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
1836 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1837 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1839 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1840 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1842 cERROR(1, ("Send error in QFSInfo = %d", rc));
1843 } else { /* decode response */
1844 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1846 ("Decoding qfsinfo response. BCC: %d Offset %d",
1847 pSMBr->ByteCount, pSMBr->DataOffset));
1848 if ((pSMBr->ByteCount < 24) || (pSMBr->DataOffset > 512)) /* BB also check enough total bytes returned */
1849 rc = -EIO; /* bad smb */
1853 *) (((char *) &pSMBr->hdr.Protocol) +
1856 le32_to_cpu(response_data->BytesPerSector) *
1857 le32_to_cpu(response_data->
1858 SectorsPerAllocationUnit);
1860 le64_to_cpu(response_data->TotalAllocationUnits);
1861 FSData->f_bfree = FSData->f_bavail =
1862 le64_to_cpu(response_data->FreeAllocationUnits);
1864 ("Blocks: %lld Free: %lld Block size %ld",
1865 (unsigned long long)FSData->f_blocks,
1866 (unsigned long long)FSData->f_bfree,
1876 CIFSSMBQFSAttributeInfo(int xid, struct cifsTconInfo *tcon,
1877 const struct nls_table *nls_codepage)
1879 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
1880 TRANSACTION2_QFSI_REQ *pSMB = NULL;
1881 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1882 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
1884 int bytes_returned = 0;
1886 cFYI(1, ("In QFSAttributeInfo"));
1887 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1892 pSMB->TotalParameterCount = 2; /* level */
1893 pSMB->TotalDataCount = 0;
1894 pSMB->MaxParameterCount = cpu_to_le16(2);
1895 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1896 pSMB->MaxSetupCount = 0;
1900 pSMB->Reserved2 = 0;
1901 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1902 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1903 pSMB->ParameterCount = pSMB->TotalParameterCount;
1904 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1905 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1906 pSMB->DataCount = 0;
1907 pSMB->DataOffset = 0;
1908 pSMB->SetupCount = 1;
1909 pSMB->Reserved3 = 0;
1910 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1911 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
1912 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1913 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1915 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1916 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1918 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
1919 } else { /* decode response */
1920 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1921 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) { /* BB also check enough bytes returned */
1922 rc = -EIO; /* bad smb */
1925 (FILE_SYSTEM_ATTRIBUTE_INFO
1926 *) (((char *) &pSMBr->hdr.Protocol) +
1928 memcpy(&tcon->fsAttrInfo, response_data,
1929 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
1938 CIFSSMBQFSDeviceInfo(int xid, struct cifsTconInfo *tcon,
1939 const struct nls_table *nls_codepage)
1941 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
1942 TRANSACTION2_QFSI_REQ *pSMB = NULL;
1943 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
1944 FILE_SYSTEM_DEVICE_INFO *response_data;
1946 int bytes_returned = 0;
1948 cFYI(1, ("In QFSDeviceInfo"));
1950 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1955 pSMB->TotalParameterCount = 2; /* level */
1956 pSMB->TotalDataCount = 0;
1957 pSMB->MaxParameterCount = cpu_to_le16(2);
1958 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
1959 pSMB->MaxSetupCount = 0;
1963 pSMB->Reserved2 = 0;
1964 pSMB->ByteCount = pSMB->TotalParameterCount + 1 /* pad */ ;
1965 pSMB->TotalParameterCount = cpu_to_le16(pSMB->TotalParameterCount);
1966 pSMB->ParameterCount = pSMB->TotalParameterCount;
1967 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1968 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
1970 pSMB->DataCount = 0;
1971 pSMB->DataOffset = 0;
1972 pSMB->SetupCount = 1;
1973 pSMB->Reserved3 = 0;
1974 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
1975 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
1976 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
1977 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
1979 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1980 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1982 cERROR(1, ("Send error in QFSDeviceInfo = %d", rc));
1983 } else { /* decode response */
1984 pSMBr->DataOffset = le16_to_cpu(pSMBr->DataOffset);
1985 if ((pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO))
1986 || (pSMBr->DataOffset > 512))
1987 rc = -EIO; /* bad smb */
1990 (FILE_SYSTEM_DEVICE_INFO
1991 *) (((char *) &pSMBr->hdr.Protocol) +
1993 memcpy(&tcon->fsDevInfo, response_data,
1994 sizeof (FILE_SYSTEM_DEVICE_INFO));
2003 CIFSSMBQFSUnixInfo(int xid, struct cifsTconInfo *tcon,
2004 const struct nls_table *nls_codepage)
2006 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
2007 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2008 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2009 FILE_SYSTEM_UNIX_INFO *response_data;
2011 int bytes_returned = 0;
2013 cFYI(1, ("In QFSUnixInfo"));
2014 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2019 pSMB->ParameterCount = 2; /* level */
2020 pSMB->TotalDataCount = 0;
2021 pSMB->DataCount = 0;
2022 pSMB->DataOffset = 0;
2023 pSMB->MaxParameterCount = cpu_to_le16(2);
2024 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
2025 pSMB->MaxSetupCount = 0;
2029 pSMB->Reserved2 = 0;
2030 pSMB->ByteCount = pSMB->ParameterCount + 1 /* pad */ ;
2031 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2032 pSMB->TotalParameterCount = pSMB->ParameterCount;
2033 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
2034 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2035 pSMB->SetupCount = 1;
2036 pSMB->Reserved3 = 0;
2037 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2038 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
2039 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2040 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2042 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2043 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2045 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
2046 } else { /* decode response */
2047 pSMBr->DataOffset = cpu_to_le16(pSMBr->DataOffset);
2048 if ((pSMBr->ByteCount < 13) || (pSMBr->DataOffset > 512)) {
2049 rc = -EIO; /* bad smb */
2052 (FILE_SYSTEM_UNIX_INFO
2053 *) (((char *) &pSMBr->hdr.Protocol) +
2055 memcpy(&tcon->fsUnixInfo, response_data,
2056 sizeof (FILE_SYSTEM_UNIX_INFO));
2064 /* We can not use write of zero bytes trick to
2065 set file size due to need for large file support. Also note that
2066 this SetPathInfo is preferred to SetFileInfo based method in next
2067 routine which is only needed to work around a sharing violation bug
2068 in Samba which this routine can run into */
2071 CIFSSMBSetEOF(int xid, struct cifsTconInfo *tcon, char *fileName,
2072 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
2074 struct smb_com_transaction2_spi_req *pSMB = NULL;
2075 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2076 struct file_end_of_file_info *parm_data;
2079 int bytes_returned = 0;
2081 cFYI(1, ("In SetEOF"));
2083 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2088 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2090 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2091 /* find define for this maxpathcomponent */
2093 name_len++; /* trailing null */
2095 } else { /* BB improve the check for buffer overruns BB */
2096 name_len = strnlen(fileName, 530);
2097 name_len++; /* trailing null */
2098 strncpy(pSMB->FileName, fileName, name_len);
2100 pSMB->ParameterCount = 6 + name_len;
2101 pSMB->DataCount = sizeof (struct file_end_of_file_info);
2102 pSMB->MaxParameterCount = cpu_to_le16(2);
2103 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2104 pSMB->MaxSetupCount = 0;
2108 pSMB->Reserved2 = 0;
2109 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2110 InformationLevel) - 4;
2111 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2113 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2114 pSMB->InformationLevel =
2115 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2117 pSMB->InformationLevel =
2118 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2119 } else /* Set File Size */ {
2120 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2121 pSMB->InformationLevel =
2122 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2124 pSMB->InformationLevel =
2125 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2129 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2131 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2132 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2133 pSMB->SetupCount = 1;
2134 pSMB->Reserved3 = 0;
2135 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2136 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2137 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2138 pSMB->TotalDataCount = pSMB->DataCount;
2139 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2140 pSMB->TotalParameterCount = pSMB->ParameterCount;
2141 pSMB->Reserved4 = 0;
2142 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2143 parm_data->FileSize = cpu_to_le64(size);
2144 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2145 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2146 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2148 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
2157 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
2158 __u16 fid, __u32 pid_of_opener, int SetAllocation)
2160 struct smb_com_transaction2_sfi_req *pSMB = NULL;
2161 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
2163 struct file_end_of_file_info *parm_data;
2165 int bytes_returned = 0;
2168 cFYI(1, ("SetFileSize (via SetFileInfo)"));
2170 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2175 tmp = cpu_to_le32(pid_of_opener); /* override pid of current process
2176 so network fid will be valid */
2177 pSMB->hdr.Pid = tmp & 0xFFFF;
2179 pSMB->hdr.PidHigh = tmp & 0xFFFF;
2181 pSMB->ParameterCount = 6;
2182 pSMB->MaxSetupCount = 0;
2186 pSMB->Reserved2 = 0;
2187 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_sfi_req,
2189 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2191 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2193 pSMB->DataCount = sizeof(struct file_end_of_file_info);
2194 pSMB->MaxParameterCount = cpu_to_le16(2);
2195 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
2196 pSMB->SetupCount = 1;
2197 pSMB->Reserved3 = 0;
2198 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
2199 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2200 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2201 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2202 pSMB->TotalDataCount = pSMB->DataCount;
2203 pSMB->TotalParameterCount = pSMB->ParameterCount;
2204 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2205 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2207 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
2209 parm_data->FileSize = size;
2212 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2213 pSMB->InformationLevel =
2214 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
2216 pSMB->InformationLevel =
2217 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
2218 } else /* Set File Size */ {
2219 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2220 pSMB->InformationLevel =
2221 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
2223 pSMB->InformationLevel =
2224 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
2226 pSMB->Reserved4 = 0;
2227 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2228 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2229 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2230 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2233 ("Send error in SetFileInfo (SetFileSize) = %d",
2243 CIFSSMBSetTimes(int xid, struct cifsTconInfo *tcon, char *fileName,
2244 FILE_BASIC_INFO * data, const struct nls_table *nls_codepage)
2246 TRANSACTION2_SPI_REQ *pSMB = NULL;
2247 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2250 int bytes_returned = 0;
2253 cFYI(1, ("In SetTimes"));
2255 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2260 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2262 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2263 /* find define for this maxpathcomponent */
2265 name_len++; /* trailing null */
2267 } else { /* BB improve the check for buffer overruns BB */
2268 name_len = strnlen(fileName, 530);
2269 name_len++; /* trailing null */
2270 strncpy(pSMB->FileName, fileName, name_len);
2273 pSMB->ParameterCount = 6 + name_len;
2274 pSMB->DataCount = sizeof (FILE_BASIC_INFO);
2275 pSMB->MaxParameterCount = cpu_to_le16(2);
2276 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2277 pSMB->MaxSetupCount = 0;
2281 pSMB->Reserved2 = 0;
2282 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2283 InformationLevel) - 4;
2284 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2285 data_offset = (char *) (&pSMB->hdr.Protocol) + pSMB->DataOffset;
2286 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2287 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2288 pSMB->SetupCount = 1;
2289 pSMB->Reserved3 = 0;
2290 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2291 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2293 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2294 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2295 pSMB->TotalDataCount = pSMB->DataCount;
2296 pSMB->TotalParameterCount = pSMB->ParameterCount;
2297 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
2298 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
2300 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
2301 pSMB->Reserved4 = 0;
2302 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2303 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
2304 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2305 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2306 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2308 cFYI(1, ("SetPathInfo (times) returned %d", rc));
2317 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
2318 char *fileName, __u64 mode, __u64 uid, __u64 gid,
2319 dev_t device, const struct nls_table *nls_codepage)
2321 TRANSACTION2_SPI_REQ *pSMB = NULL;
2322 TRANSACTION2_SPI_RSP *pSMBr = NULL;
2325 int bytes_returned = 0;
2326 FILE_UNIX_BASIC_INFO *data_offset;
2328 cFYI(1, ("In SetUID/GID/Mode"));
2330 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2335 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2337 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, 530
2338 /* find define for this maxpathcomponent */
2340 name_len++; /* trailing null */
2342 } else { /* BB improve the check for buffer overruns BB */
2343 name_len = strnlen(fileName, 530);
2344 name_len++; /* trailing null */
2345 strncpy(pSMB->FileName, fileName, name_len);
2348 pSMB->ParameterCount = 6 + name_len;
2349 pSMB->DataCount = sizeof (FILE_UNIX_BASIC_INFO);
2350 pSMB->MaxParameterCount = cpu_to_le16(2);
2351 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2352 pSMB->MaxSetupCount = 0;
2356 pSMB->Reserved2 = 0;
2357 pSMB->ParameterOffset = offsetof(struct smb_com_transaction2_spi_req,
2358 InformationLevel) - 4;
2359 pSMB->DataOffset = pSMB->ParameterOffset + pSMB->ParameterCount;
2361 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
2363 pSMB->DataOffset = cpu_to_le16(pSMB->DataOffset);
2364 pSMB->ParameterOffset = cpu_to_le16(pSMB->ParameterOffset);
2365 pSMB->SetupCount = 1;
2366 pSMB->Reserved3 = 0;
2367 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2368 pSMB->ByteCount = 3 /* pad */ + pSMB->ParameterCount + pSMB->DataCount;
2369 pSMB->ParameterCount = cpu_to_le16(pSMB->ParameterCount);
2370 pSMB->DataCount = cpu_to_le16(pSMB->DataCount);
2371 pSMB->TotalParameterCount = pSMB->ParameterCount;
2372 pSMB->TotalDataCount = pSMB->DataCount;
2373 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
2374 pSMB->Reserved4 = 0;
2375 pSMB->hdr.smb_buf_length += pSMB->ByteCount;
2376 data_offset->Uid = cpu_to_le64(uid);
2377 data_offset->Gid = cpu_to_le64(gid);
2378 /* better to leave device as zero when it is */
2379 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
2380 data_offset->DevMinor = cpu_to_le64(MINOR(device));
2381 data_offset->Permissions = cpu_to_le64(mode);
2382 pSMB->ByteCount = cpu_to_le16(pSMB->ByteCount);
2383 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2384 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2386 cFYI(1, ("SetPathInfo (perms) returned %d", rc));