4 * Copyright (C) International Business Machines Corp., 2002,2005
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 <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
41 #ifdef CONFIG_CIFS_POSIX
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
55 {CIFS_PROT, "\2NT LM 0.12"},
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
74 open_file->invalidHandle = TRUE;
77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
82 /* If the return code is zero, this function must fill in request_buf pointer */
84 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
85 void **request_buf /* returned */)
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
93 if((tcon->ses) && (tcon->ses->server)){
94 struct nls_table *nls_codepage;
95 /* Give Demultiplex thread up to 10 seconds to
96 reconnect, should be greater than cifs socket
97 timeout which is 7 seconds */
98 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
99 wait_event_interruptible_timeout(tcon->ses->server->response_q,
100 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
101 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
102 /* on "soft" mounts we wait once */
103 if((tcon->retry == FALSE) ||
104 (tcon->ses->status == CifsExiting)) {
105 cFYI(1,("gave up waiting on reconnect in smb_init"));
107 } /* else "hard" mount - keep retrying
108 until process is killed or server
109 comes back on-line */
110 } else /* TCP session is reestablished now */
115 nls_codepage = load_nls_default();
116 /* need to prevent multiple threads trying to
117 simultaneously reconnect the same SMB session */
118 down(&tcon->ses->sesSem);
119 if(tcon->ses->status == CifsNeedReconnect)
120 rc = cifs_setup_session(0, tcon->ses,
122 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
123 mark_open_files_invalid(tcon);
124 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
126 up(&tcon->ses->sesSem);
128 atomic_inc(&tconInfoReconnectCount);
130 cFYI(1, ("reconnect tcon rc = %d", rc));
131 /* Removed call to reopen open files here -
132 it is safer (and faster) to reopen files
133 one at a time as needed in read and write */
135 /* Check if handle based operation so we
136 know whether we can continue or not without
137 returning to caller to reset file handle */
138 switch(smb_command) {
139 case SMB_COM_READ_ANDX:
140 case SMB_COM_WRITE_ANDX:
142 case SMB_COM_FIND_CLOSE2:
143 case SMB_COM_LOCKING_ANDX: {
144 unload_nls(nls_codepage);
149 up(&tcon->ses->sesSem);
151 unload_nls(nls_codepage);
160 *request_buf = cifs_small_buf_get();
161 if (*request_buf == NULL) {
162 /* BB should we add a retry in here if not a writepage? */
166 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
168 #ifdef CONFIG_CIFS_STATS
170 atomic_inc(&tcon->num_smbs_sent);
172 #endif /* CONFIG_CIFS_STATS */
176 /* If the return code is zero, this function must fill in request_buf pointer */
178 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
179 void **request_buf /* returned */ ,
180 void **response_buf /* returned */ )
184 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
185 check for tcp and smb session status done differently
186 for those three - in the calling routine */
188 if((tcon->ses) && (tcon->ses->server)){
189 struct nls_table *nls_codepage;
190 /* Give Demultiplex thread up to 10 seconds to
191 reconnect, should be greater than cifs socket
192 timeout which is 7 seconds */
193 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
194 wait_event_interruptible_timeout(tcon->ses->server->response_q,
195 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
196 if(tcon->ses->server->tcpStatus ==
198 /* on "soft" mounts we wait once */
199 if((tcon->retry == FALSE) ||
200 (tcon->ses->status == CifsExiting)) {
201 cFYI(1,("gave up waiting on reconnect in smb_init"));
203 } /* else "hard" mount - keep retrying
204 until process is killed or server
206 } else /* TCP session is reestablished now */
211 nls_codepage = load_nls_default();
212 /* need to prevent multiple threads trying to
213 simultaneously reconnect the same SMB session */
214 down(&tcon->ses->sesSem);
215 if(tcon->ses->status == CifsNeedReconnect)
216 rc = cifs_setup_session(0, tcon->ses,
218 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
219 mark_open_files_invalid(tcon);
220 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
222 up(&tcon->ses->sesSem);
224 atomic_inc(&tconInfoReconnectCount);
226 cFYI(1, ("reconnect tcon rc = %d", rc));
227 /* Removed call to reopen open files here -
228 it is safer (and faster) to reopen files
229 one at a time as needed in read and write */
231 /* Check if handle based operation so we
232 know whether we can continue or not without
233 returning to caller to reset file handle */
234 switch(smb_command) {
235 case SMB_COM_READ_ANDX:
236 case SMB_COM_WRITE_ANDX:
238 case SMB_COM_FIND_CLOSE2:
239 case SMB_COM_LOCKING_ANDX: {
240 unload_nls(nls_codepage);
245 up(&tcon->ses->sesSem);
247 unload_nls(nls_codepage);
256 *request_buf = cifs_buf_get();
257 if (*request_buf == NULL) {
258 /* BB should we add a retry in here if not a writepage? */
261 /* Although the original thought was we needed the response buf for */
262 /* potential retries of smb operations it turns out we can determine */
263 /* from the mid flags when the request buffer can be resent without */
264 /* having to use a second distinct buffer for the response */
265 *response_buf = *request_buf;
267 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
270 #ifdef CONFIG_CIFS_STATS
272 atomic_inc(&tcon->num_smbs_sent);
274 #endif /* CONFIG_CIFS_STATS */
278 static int validate_t2(struct smb_t2_rsp * pSMB)
284 /* check for plausible wct, bcc and t2 data and parm sizes */
285 /* check for parm and data offset going beyond end of smb */
286 if(pSMB->hdr.WordCount >= 10) {
287 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
288 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
289 /* check that bcc is at least as big as parms + data */
290 /* check that bcc is less than negotiated smb buffer */
291 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
292 if(total_size < 512) {
293 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
294 /* BCC le converted in SendReceive */
295 pBCC = (pSMB->hdr.WordCount * 2) +
296 sizeof(struct smb_hdr) +
298 if((total_size <= (*(u16 *)pBCC)) &&
300 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
307 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
308 sizeof(struct smb_t2_rsp) + 16);
312 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
315 NEGOTIATE_RSP *pSMBr;
318 struct TCP_Server_Info * server;
322 server = ses->server;
327 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
328 (void **) &pSMB, (void **) &pSMBr);
332 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
333 if (extended_security)
334 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
336 count = strlen(protocols[0].name) + 1;
337 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
338 /* null guaranteed to be at end of source and target buffers anyway */
340 pSMB->hdr.smb_buf_length += count;
341 pSMB->ByteCount = cpu_to_le16(count);
343 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
344 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
346 server->secMode = pSMBr->SecurityMode;
347 server->secType = NTLM; /* BB override default for
348 NTLMv2 or kerberos v5 */
349 /* one byte - no need to convert this or EncryptionKeyLen
350 from little endian */
351 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
352 /* probably no need to store and check maxvcs */
354 min(le32_to_cpu(pSMBr->MaxBufferSize),
355 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
356 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
357 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
358 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
359 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
360 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
361 /* BB with UTC do we ever need to be using srvr timezone? */
362 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
363 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
364 CIFS_CRYPTO_KEY_SIZE);
365 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
366 && (pSMBr->EncryptionKeyLength == 0)) {
367 /* decode security blob */
371 /* BB might be helpful to save off the domain of server here */
373 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
374 (server->capabilities & CAP_EXTENDED_SECURITY)) {
375 count = pSMBr->ByteCount;
378 else if (count == 16) {
379 server->secType = RawNTLMSSP;
380 if (server->socketUseCount.counter > 1) {
382 (server->server_GUID,
383 pSMBr->u.extended_response.
386 ("UID of server does not match previous connection to same ip address"));
394 memcpy(server->server_GUID,
395 pSMBr->u.extended_response.
398 rc = decode_negTokenInit(pSMBr->u.
404 /* BB Need to fill struct for sessetup here */
411 server->capabilities &= ~CAP_EXTENDED_SECURITY;
412 if(sign_CIFS_PDUs == FALSE) {
413 if(server->secMode & SECMODE_SIGN_REQUIRED)
415 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
416 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
417 } else if(sign_CIFS_PDUs == 1) {
418 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
419 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
424 cifs_buf_release(pSMB);
429 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
431 struct smb_hdr *smb_buffer;
432 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
436 cFYI(1, ("In tree disconnect"));
438 * If last user of the connection and
439 * connection alive - disconnect it
440 * If this is the last connection on the server session disconnect it
441 * (and inside session disconnect we should check if tcp socket needs
442 * to be freed and kernel thread woken up).
445 down(&tcon->tconSem);
449 atomic_dec(&tcon->useCount);
450 if (atomic_read(&tcon->useCount) > 0) {
455 /* No need to return error on this operation if tid invalidated and
456 closed on server already e.g. due to tcp session crashing */
457 if(tcon->tidStatus == CifsNeedReconnect) {
462 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
466 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
467 (void **)&smb_buffer);
472 smb_buffer_response = smb_buffer; /* BB removeme BB */
474 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
477 cFYI(1, ("Tree disconnect failed %d", rc));
480 cifs_small_buf_release(smb_buffer);
483 /* No need to return error on this operation if tid invalidated and
484 closed on server already e.g. due to tcp session crashing */
492 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
494 struct smb_hdr *smb_buffer_response;
495 LOGOFF_ANDX_REQ *pSMB;
499 cFYI(1, ("In SMBLogoff for session disconnect"));
505 atomic_dec(&ses->inUse);
506 if (atomic_read(&ses->inUse) > 0) {
510 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
516 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
519 if(ses->server->secMode &
520 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
521 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
524 pSMB->hdr.Uid = ses->Suid;
526 pSMB->AndXCommand = 0xFF;
527 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
528 smb_buffer_response, &length, 0);
530 atomic_dec(&ses->server->socketUseCount);
531 if (atomic_read(&ses->server->socketUseCount) == 0) {
532 spin_lock(&GlobalMid_Lock);
533 ses->server->tcpStatus = CifsExiting;
534 spin_unlock(&GlobalMid_Lock);
539 cifs_small_buf_release(pSMB);
542 /* if session dead then we do not need to do ulogoff,
543 since server closed smb session, no sense reporting
551 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
552 const struct nls_table *nls_codepage, int remap)
554 DELETE_FILE_REQ *pSMB = NULL;
555 DELETE_FILE_RSP *pSMBr = NULL;
561 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
566 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
568 cifsConvertToUCS((__u16 *) pSMB->fileName, fileName,
569 PATH_MAX, nls_codepage, remap);
570 name_len++; /* trailing null */
572 } else { /* BB improve check for buffer overruns BB */
573 name_len = strnlen(fileName, PATH_MAX);
574 name_len++; /* trailing null */
575 strncpy(pSMB->fileName, fileName, name_len);
577 pSMB->SearchAttributes =
578 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
579 pSMB->BufferFormat = 0x04;
580 pSMB->hdr.smb_buf_length += name_len + 1;
581 pSMB->ByteCount = cpu_to_le16(name_len + 1);
582 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
583 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
585 cFYI(1, ("Error in RMFile = %d", rc));
587 #ifdef CONFIG_CIFS_STATS
589 atomic_inc(&tcon->num_deletes);
593 cifs_buf_release(pSMB);
601 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
602 const struct nls_table *nls_codepage, int remap)
604 DELETE_DIRECTORY_REQ *pSMB = NULL;
605 DELETE_DIRECTORY_RSP *pSMBr = NULL;
610 cFYI(1, ("In CIFSSMBRmDir"));
612 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
617 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
618 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
619 PATH_MAX, nls_codepage, remap);
620 name_len++; /* trailing null */
622 } else { /* BB improve check for buffer overruns BB */
623 name_len = strnlen(dirName, PATH_MAX);
624 name_len++; /* trailing null */
625 strncpy(pSMB->DirName, dirName, name_len);
628 pSMB->BufferFormat = 0x04;
629 pSMB->hdr.smb_buf_length += name_len + 1;
630 pSMB->ByteCount = cpu_to_le16(name_len + 1);
631 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
632 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
634 cFYI(1, ("Error in RMDir = %d", rc));
636 #ifdef CONFIG_CIFS_STATS
638 atomic_inc(&tcon->num_rmdirs);
642 cifs_buf_release(pSMB);
649 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
650 const char *name, const struct nls_table *nls_codepage, int remap)
653 CREATE_DIRECTORY_REQ *pSMB = NULL;
654 CREATE_DIRECTORY_RSP *pSMBr = NULL;
658 cFYI(1, ("In CIFSSMBMkDir"));
660 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
665 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
666 name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name,
667 PATH_MAX, nls_codepage, remap);
668 name_len++; /* trailing null */
670 } else { /* BB improve check for buffer overruns BB */
671 name_len = strnlen(name, PATH_MAX);
672 name_len++; /* trailing null */
673 strncpy(pSMB->DirName, name, name_len);
676 pSMB->BufferFormat = 0x04;
677 pSMB->hdr.smb_buf_length += name_len + 1;
678 pSMB->ByteCount = cpu_to_le16(name_len + 1);
679 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
680 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
682 cFYI(1, ("Error in Mkdir = %d", rc));
684 #ifdef CONFIG_CIFS_STATS
686 atomic_inc(&tcon->num_mkdirs);
689 cifs_buf_release(pSMB);
696 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
697 const char *fileName, const int openDisposition,
698 const int access_flags, const int create_options, __u16 * netfid,
699 int *pOplock, FILE_ALL_INFO * pfile_info,
700 const struct nls_table *nls_codepage, int remap)
703 OPEN_REQ *pSMB = NULL;
704 OPEN_RSP *pSMBr = NULL;
710 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
715 pSMB->AndXCommand = 0xFF; /* none */
717 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
718 count = 1; /* account for one byte pad to word boundary */
720 cifsConvertToUCS((__u16 *) (pSMB->fileName + 1),
721 fileName, PATH_MAX, nls_codepage, remap);
722 name_len++; /* trailing null */
724 pSMB->NameLength = cpu_to_le16(name_len);
725 } else { /* BB improve check for buffer overruns BB */
726 count = 0; /* no pad */
727 name_len = strnlen(fileName, PATH_MAX);
728 name_len++; /* trailing null */
729 pSMB->NameLength = cpu_to_le16(name_len);
730 strncpy(pSMB->fileName, fileName, name_len);
732 if (*pOplock & REQ_OPLOCK)
733 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
734 else if (*pOplock & REQ_BATCHOPLOCK) {
735 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
737 pSMB->DesiredAccess = cpu_to_le32(access_flags);
738 pSMB->AllocationSize = 0;
739 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
740 /* XP does not handle ATTR_POSIX_SEMANTICS */
741 /* but it helps speed up case sensitive checks for other
742 servers such as Samba */
743 if (tcon->ses->capabilities & CAP_UNIX)
744 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
746 /* if ((omode & S_IWUGO) == 0)
747 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
748 /* Above line causes problems due to vfs splitting create into two
749 pieces - need to set mode after file created not while it is
751 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
752 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
753 pSMB->CreateOptions = cpu_to_le32(create_options);
754 /* BB Expirement with various impersonation levels and verify */
755 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
756 pSMB->SecurityFlags =
757 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
760 pSMB->hdr.smb_buf_length += count;
762 pSMB->ByteCount = cpu_to_le16(count);
763 /* long_op set to 1 to allow for oplock break timeouts */
764 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
765 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
767 cFYI(1, ("Error in Open = %d", rc));
769 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
770 *netfid = pSMBr->Fid; /* cifs fid stays in le */
771 /* Let caller know file was created so we can set the mode. */
772 /* Do we care about the CreateAction in any other cases? */
773 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
774 *pOplock |= CIFS_CREATE_ACTION;
776 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
777 36 /* CreationTime to Attributes */);
778 /* the file_info buf is endian converted by caller */
779 pfile_info->AllocationSize = pSMBr->AllocationSize;
780 pfile_info->EndOfFile = pSMBr->EndOfFile;
781 pfile_info->NumberOfLinks = cpu_to_le32(1);
784 #ifdef CONFIG_CIFS_STATS
785 atomic_inc(&tcon->num_opens);
788 cifs_buf_release(pSMB);
794 /* If no buffer passed in, then caller wants to do the copy
795 as in the case of readpages so the SMB buffer must be
796 freed by the caller */
799 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
800 const int netfid, const unsigned int count,
801 const __u64 lseek, unsigned int *nbytes, char **buf)
804 READ_REQ *pSMB = NULL;
805 READ_RSP *pSMBr = NULL;
806 char *pReadData = NULL;
809 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
812 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
817 /* tcon and ses pointer are checked in smb_init */
818 if (tcon->ses->server == NULL)
819 return -ECONNABORTED;
821 pSMB->AndXCommand = 0xFF; /* none */
823 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
824 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
826 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
827 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
828 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
830 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
831 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
833 cERROR(1, ("Send error in read = %d", rc));
835 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
836 data_length = data_length << 16;
837 data_length += le16_to_cpu(pSMBr->DataLength);
838 *nbytes = data_length;
840 /*check that DataLength would not go beyond end of SMB */
841 if ((data_length > CIFSMaxBufSize)
842 || (data_length > count)) {
843 cFYI(1,("bad length %d for count %d",data_length,count));
848 (char *) (&pSMBr->hdr.Protocol) +
849 le16_to_cpu(pSMBr->DataOffset);
850 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
851 cERROR(1,("Faulting on read rc = %d",rc));
853 }*/ /* can not use copy_to_user when using page cache*/
855 memcpy(*buf,pReadData,data_length);
859 cifs_buf_release(pSMB);
863 /* Note: On -EAGAIN error only caller can retry on handle based calls
864 since file handle passed in no longer valid */
869 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
870 const int netfid, const unsigned int count,
871 const __u64 offset, unsigned int *nbytes, const char *buf,
872 const char __user * ubuf, const int long_op)
875 WRITE_REQ *pSMB = NULL;
876 WRITE_RSP *pSMBr = NULL;
881 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
882 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
886 /* tcon and ses pointer are checked in smb_init */
887 if (tcon->ses->server == NULL)
888 return -ECONNABORTED;
890 pSMB->AndXCommand = 0xFF; /* none */
892 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
893 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
894 pSMB->Reserved = 0xFFFFFFFF;
898 /* Can increase buffer size if buffer is big enough in some cases - ie we
899 can send more if LARGE_WRITE_X capability returned by the server and if
900 our buffer is big enough or if we convert to iovecs on socket writes
901 and eliminate the copy to the CIFS buffer */
902 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
903 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
905 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
909 if (bytes_sent > count)
912 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
914 memcpy(pSMB->Data,buf,bytes_sent);
916 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
917 cifs_buf_release(pSMB);
922 cifs_buf_release(pSMB);
926 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
927 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
928 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
929 pSMB->hdr.smb_buf_length += bytes_sent+1;
930 pSMB->ByteCount = cpu_to_le16(byte_count);
932 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
933 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
935 cFYI(1, ("Send error in write = %d", rc));
938 *nbytes = le16_to_cpu(pSMBr->CountHigh);
939 *nbytes = (*nbytes) << 16;
940 *nbytes += le16_to_cpu(pSMBr->Count);
943 cifs_buf_release(pSMB);
945 /* Note: On -EAGAIN error only caller can retry on handle based calls
946 since file handle passed in no longer valid */
951 #ifdef CONFIG_CIFS_EXPERIMENTAL
952 int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
953 const int netfid, const unsigned int count,
954 const __u64 offset, unsigned int *nbytes, const char __user *buf,
958 WRITE_REQ *pSMB = NULL;
959 WRITE_RSP *pSMBr = NULL;
960 /*int bytes_returned;*/
964 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
969 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
971 /* tcon and ses pointer are checked in smb_init */
972 if (tcon->ses->server == NULL)
973 return -ECONNABORTED;
975 pSMB->AndXCommand = 0xFF; /* none */
977 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
978 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
979 pSMB->Reserved = 0xFFFFFFFF;
982 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
983 if (bytes_sent > count)
985 pSMB->DataLengthHigh = 0;
987 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
989 byte_count = bytes_sent + 1 /* pad */ ;
990 pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
991 pSMB->DataLengthHigh = 0;
992 pSMB->hdr.smb_buf_length += byte_count;
993 pSMB->ByteCount = cpu_to_le16(byte_count);
995 /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
996 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
998 cFYI(1, ("Send error in write2 (large write) = %d", rc));
1001 *nbytes = le16_to_cpu(pSMBr->Count);
1003 cifs_small_buf_release(pSMB);
1005 /* Note: On -EAGAIN error only caller can retry on handle based calls
1006 since file handle passed in no longer valid */
1010 #endif /* CIFS_EXPERIMENTAL */
1013 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1014 const __u16 smb_file_id, const __u64 len,
1015 const __u64 offset, const __u32 numUnlock,
1016 const __u32 numLock, const __u8 lockType, const int waitFlag)
1019 LOCK_REQ *pSMB = NULL;
1020 LOCK_RSP *pSMBr = NULL;
1025 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1026 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1031 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1033 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1034 timeout = -1; /* no response expected */
1036 } else if (waitFlag == TRUE) {
1037 timeout = 3; /* blocking operation, no timeout */
1038 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1043 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1044 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1045 pSMB->LockType = lockType;
1046 pSMB->AndXCommand = 0xFF; /* none */
1047 pSMB->Fid = smb_file_id; /* netfid stays le */
1049 if((numLock != 0) || (numUnlock != 0)) {
1050 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1051 /* BB where to store pid high? */
1052 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1053 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1054 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1055 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1056 count = sizeof(LOCKING_ANDX_RANGE);
1061 pSMB->hdr.smb_buf_length += count;
1062 pSMB->ByteCount = cpu_to_le16(count);
1064 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1065 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1068 cFYI(1, ("Send error in Lock = %d", rc));
1070 cifs_small_buf_release(pSMB);
1072 /* Note: On -EAGAIN error only caller can retry on handle based calls
1073 since file handle passed in no longer valid */
1078 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1081 CLOSE_REQ *pSMB = NULL;
1082 CLOSE_RSP *pSMBr = NULL;
1084 cFYI(1, ("In CIFSSMBClose"));
1086 /* do not retry on dead session on close */
1087 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1093 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1095 pSMB->FileID = (__u16) smb_file_id;
1096 pSMB->LastWriteTime = 0;
1097 pSMB->ByteCount = 0;
1098 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1099 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1102 /* EINTR is expected when user ctl-c to kill app */
1103 cERROR(1, ("Send error in Close = %d", rc));
1107 cifs_small_buf_release(pSMB);
1109 /* Since session is dead, file will be closed on server already */
1117 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1118 const char *fromName, const char *toName,
1119 const struct nls_table *nls_codepage, int remap)
1122 RENAME_REQ *pSMB = NULL;
1123 RENAME_RSP *pSMBr = NULL;
1125 int name_len, name_len2;
1128 cFYI(1, ("In CIFSSMBRename"));
1130 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1135 pSMB->BufferFormat = 0x04;
1136 pSMB->SearchAttributes =
1137 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1140 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1142 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
1143 PATH_MAX, nls_codepage, remap);
1144 name_len++; /* trailing null */
1146 pSMB->OldFileName[name_len] = 0x04; /* pad */
1147 /* protocol requires ASCII signature byte on Unicode string */
1148 pSMB->OldFileName[name_len + 1] = 0x00;
1150 cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2],
1151 toName, PATH_MAX, nls_codepage, remap);
1152 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1153 name_len2 *= 2; /* convert to bytes */
1154 } else { /* BB improve the check for buffer overruns BB */
1155 name_len = strnlen(fromName, PATH_MAX);
1156 name_len++; /* trailing null */
1157 strncpy(pSMB->OldFileName, fromName, name_len);
1158 name_len2 = strnlen(toName, PATH_MAX);
1159 name_len2++; /* trailing null */
1160 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1161 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1162 name_len2++; /* trailing null */
1163 name_len2++; /* signature byte */
1166 count = 1 /* 1st signature byte */ + name_len + name_len2;
1167 pSMB->hdr.smb_buf_length += count;
1168 pSMB->ByteCount = cpu_to_le16(count);
1170 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1171 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1173 cFYI(1, ("Send error in rename = %d", rc));
1176 #ifdef CONFIG_CIFS_STATS
1178 atomic_inc(&tcon->num_renames);
1182 cifs_buf_release(pSMB);
1190 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1191 int netfid, char * target_name,
1192 const struct nls_table * nls_codepage, int remap)
1194 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1195 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1196 struct set_file_rename * rename_info;
1198 char dummy_string[30];
1200 int bytes_returned = 0;
1202 __u16 params, param_offset, offset, count, byte_count;
1204 cFYI(1, ("Rename to File by handle"));
1205 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1211 pSMB->MaxSetupCount = 0;
1215 pSMB->Reserved2 = 0;
1216 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1217 offset = param_offset + params;
1219 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1220 rename_info = (struct set_file_rename *) data_offset;
1221 pSMB->MaxParameterCount = cpu_to_le16(2);
1222 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1223 pSMB->SetupCount = 1;
1224 pSMB->Reserved3 = 0;
1225 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1226 byte_count = 3 /* pad */ + params;
1227 pSMB->ParameterCount = cpu_to_le16(params);
1228 pSMB->TotalParameterCount = pSMB->ParameterCount;
1229 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1230 pSMB->DataOffset = cpu_to_le16(offset);
1231 /* construct random name ".cifs_tmp<inodenum><mid>" */
1232 rename_info->overwrite = cpu_to_le32(1);
1233 rename_info->root_fid = 0;
1234 /* unicode only call */
1235 if(target_name == NULL) {
1236 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1237 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
1238 dummy_string, 24, nls_codepage, remap);
1240 len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
1241 target_name, PATH_MAX, nls_codepage, remap);
1243 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1244 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1245 byte_count += count;
1246 pSMB->DataCount = cpu_to_le16(count);
1247 pSMB->TotalDataCount = pSMB->DataCount;
1249 pSMB->InformationLevel =
1250 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1251 pSMB->Reserved4 = 0;
1252 pSMB->hdr.smb_buf_length += byte_count;
1253 pSMB->ByteCount = cpu_to_le16(byte_count);
1254 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1255 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1257 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1259 #ifdef CONFIG_CIFS_STATS
1261 atomic_inc(&pTcon->num_t2renames);
1264 cifs_buf_release(pSMB);
1266 /* Note: On -EAGAIN error only caller can retry on handle based calls
1267 since file handle passed in no longer valid */
1273 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1274 const __u16 target_tid, const char *toName, const int flags,
1275 const struct nls_table *nls_codepage, int remap)
1278 COPY_REQ *pSMB = NULL;
1279 COPY_RSP *pSMBr = NULL;
1281 int name_len, name_len2;
1284 cFYI(1, ("In CIFSSMBCopy"));
1286 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1291 pSMB->BufferFormat = 0x04;
1292 pSMB->Tid2 = target_tid;
1294 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1296 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1297 name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName,
1298 fromName, PATH_MAX, nls_codepage,
1300 name_len++; /* trailing null */
1302 pSMB->OldFileName[name_len] = 0x04; /* pad */
1303 /* protocol requires ASCII signature byte on Unicode string */
1304 pSMB->OldFileName[name_len + 1] = 0x00;
1305 name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
1306 toName, PATH_MAX, nls_codepage, remap);
1307 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1308 name_len2 *= 2; /* convert to bytes */
1309 } else { /* BB improve the check for buffer overruns BB */
1310 name_len = strnlen(fromName, PATH_MAX);
1311 name_len++; /* trailing null */
1312 strncpy(pSMB->OldFileName, fromName, name_len);
1313 name_len2 = strnlen(toName, PATH_MAX);
1314 name_len2++; /* trailing null */
1315 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1316 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1317 name_len2++; /* trailing null */
1318 name_len2++; /* signature byte */
1321 count = 1 /* 1st signature byte */ + name_len + name_len2;
1322 pSMB->hdr.smb_buf_length += count;
1323 pSMB->ByteCount = cpu_to_le16(count);
1325 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1326 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1328 cFYI(1, ("Send error in copy = %d with %d files copied",
1329 rc, le16_to_cpu(pSMBr->CopyCount)));
1332 cifs_buf_release(pSMB);
1341 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1342 const char *fromName, const char *toName,
1343 const struct nls_table *nls_codepage)
1345 TRANSACTION2_SPI_REQ *pSMB = NULL;
1346 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1349 int name_len_target;
1351 int bytes_returned = 0;
1352 __u16 params, param_offset, offset, byte_count;
1354 cFYI(1, ("In Symlink Unix style"));
1356 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1361 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1363 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1364 /* find define for this maxpathcomponent */
1366 name_len++; /* trailing null */
1369 } else { /* BB improve the check for buffer overruns BB */
1370 name_len = strnlen(fromName, PATH_MAX);
1371 name_len++; /* trailing null */
1372 strncpy(pSMB->FileName, fromName, name_len);
1374 params = 6 + name_len;
1375 pSMB->MaxSetupCount = 0;
1379 pSMB->Reserved2 = 0;
1380 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1381 InformationLevel) - 4;
1382 offset = param_offset + params;
1384 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1385 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1387 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1388 /* find define for this maxpathcomponent */
1390 name_len_target++; /* trailing null */
1391 name_len_target *= 2;
1392 } else { /* BB improve the check for buffer overruns BB */
1393 name_len_target = strnlen(toName, PATH_MAX);
1394 name_len_target++; /* trailing null */
1395 strncpy(data_offset, toName, name_len_target);
1398 pSMB->MaxParameterCount = cpu_to_le16(2);
1399 /* BB find exact max on data count below from sess */
1400 pSMB->MaxDataCount = cpu_to_le16(1000);
1401 pSMB->SetupCount = 1;
1402 pSMB->Reserved3 = 0;
1403 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1404 byte_count = 3 /* pad */ + params + name_len_target;
1405 pSMB->DataCount = cpu_to_le16(name_len_target);
1406 pSMB->ParameterCount = cpu_to_le16(params);
1407 pSMB->TotalDataCount = pSMB->DataCount;
1408 pSMB->TotalParameterCount = pSMB->ParameterCount;
1409 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1410 pSMB->DataOffset = cpu_to_le16(offset);
1411 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1412 pSMB->Reserved4 = 0;
1413 pSMB->hdr.smb_buf_length += byte_count;
1414 pSMB->ByteCount = cpu_to_le16(byte_count);
1415 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1416 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1419 ("Send error in SetPathInfo (create symlink) = %d",
1424 cifs_buf_release(pSMB);
1427 goto createSymLinkRetry;
1433 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1434 const char *fromName, const char *toName,
1435 const struct nls_table *nls_codepage, int remap)
1437 TRANSACTION2_SPI_REQ *pSMB = NULL;
1438 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1441 int name_len_target;
1443 int bytes_returned = 0;
1444 __u16 params, param_offset, offset, byte_count;
1446 cFYI(1, ("In Create Hard link Unix style"));
1447 createHardLinkRetry:
1448 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1453 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1454 name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName,
1455 PATH_MAX, nls_codepage, remap);
1456 name_len++; /* trailing null */
1459 } else { /* BB improve the check for buffer overruns BB */
1460 name_len = strnlen(toName, PATH_MAX);
1461 name_len++; /* trailing null */
1462 strncpy(pSMB->FileName, toName, name_len);
1464 params = 6 + name_len;
1465 pSMB->MaxSetupCount = 0;
1469 pSMB->Reserved2 = 0;
1470 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1471 InformationLevel) - 4;
1472 offset = param_offset + params;
1474 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1475 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1477 cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX,
1478 nls_codepage, remap);
1479 name_len_target++; /* trailing null */
1480 name_len_target *= 2;
1481 } else { /* BB improve the check for buffer overruns BB */
1482 name_len_target = strnlen(fromName, PATH_MAX);
1483 name_len_target++; /* trailing null */
1484 strncpy(data_offset, fromName, name_len_target);
1487 pSMB->MaxParameterCount = cpu_to_le16(2);
1488 /* BB find exact max on data count below from sess*/
1489 pSMB->MaxDataCount = cpu_to_le16(1000);
1490 pSMB->SetupCount = 1;
1491 pSMB->Reserved3 = 0;
1492 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1493 byte_count = 3 /* pad */ + params + name_len_target;
1494 pSMB->ParameterCount = cpu_to_le16(params);
1495 pSMB->TotalParameterCount = pSMB->ParameterCount;
1496 pSMB->DataCount = cpu_to_le16(name_len_target);
1497 pSMB->TotalDataCount = pSMB->DataCount;
1498 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1499 pSMB->DataOffset = cpu_to_le16(offset);
1500 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1501 pSMB->Reserved4 = 0;
1502 pSMB->hdr.smb_buf_length += byte_count;
1503 pSMB->ByteCount = cpu_to_le16(byte_count);
1504 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1505 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1507 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1510 cifs_buf_release(pSMB);
1512 goto createHardLinkRetry;
1518 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1519 const char *fromName, const char *toName,
1520 const struct nls_table *nls_codepage, int remap)
1523 NT_RENAME_REQ *pSMB = NULL;
1524 RENAME_RSP *pSMBr = NULL;
1526 int name_len, name_len2;
1529 cFYI(1, ("In CIFSCreateHardLink"));
1530 winCreateHardLinkRetry:
1532 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1537 pSMB->SearchAttributes =
1538 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1540 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1541 pSMB->ClusterCount = 0;
1543 pSMB->BufferFormat = 0x04;
1545 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1547 cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
1548 PATH_MAX, nls_codepage, remap);
1549 name_len++; /* trailing null */
1551 pSMB->OldFileName[name_len] = 0; /* pad */
1552 pSMB->OldFileName[name_len + 1] = 0x04;
1554 cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
1555 toName, PATH_MAX, nls_codepage, remap);
1556 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1557 name_len2 *= 2; /* convert to bytes */
1558 } else { /* BB improve the check for buffer overruns BB */
1559 name_len = strnlen(fromName, PATH_MAX);
1560 name_len++; /* trailing null */
1561 strncpy(pSMB->OldFileName, fromName, name_len);
1562 name_len2 = strnlen(toName, PATH_MAX);
1563 name_len2++; /* trailing null */
1564 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1565 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1566 name_len2++; /* trailing null */
1567 name_len2++; /* signature byte */
1570 count = 1 /* string type byte */ + name_len + name_len2;
1571 pSMB->hdr.smb_buf_length += count;
1572 pSMB->ByteCount = cpu_to_le16(count);
1574 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1575 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1577 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1579 cifs_buf_release(pSMB);
1581 goto winCreateHardLinkRetry;
1587 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1588 const unsigned char *searchName,
1589 char *symlinkinfo, const int buflen,
1590 const struct nls_table *nls_codepage)
1592 /* SMB_QUERY_FILE_UNIX_LINK */
1593 TRANSACTION2_QPI_REQ *pSMB = NULL;
1594 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1598 __u16 params, byte_count;
1600 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1603 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1608 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1610 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1611 /* find define for this maxpathcomponent */
1613 name_len++; /* trailing null */
1615 } else { /* BB improve the check for buffer overruns BB */
1616 name_len = strnlen(searchName, PATH_MAX);
1617 name_len++; /* trailing null */
1618 strncpy(pSMB->FileName, searchName, name_len);
1621 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1622 pSMB->TotalDataCount = 0;
1623 pSMB->MaxParameterCount = cpu_to_le16(2);
1624 /* BB find exact max data count below from sess structure BB */
1625 pSMB->MaxDataCount = cpu_to_le16(4000);
1626 pSMB->MaxSetupCount = 0;
1630 pSMB->Reserved2 = 0;
1631 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1632 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1633 pSMB->DataCount = 0;
1634 pSMB->DataOffset = 0;
1635 pSMB->SetupCount = 1;
1636 pSMB->Reserved3 = 0;
1637 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1638 byte_count = params + 1 /* pad */ ;
1639 pSMB->TotalParameterCount = cpu_to_le16(params);
1640 pSMB->ParameterCount = pSMB->TotalParameterCount;
1641 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1642 pSMB->Reserved4 = 0;
1643 pSMB->hdr.smb_buf_length += byte_count;
1644 pSMB->ByteCount = cpu_to_le16(byte_count);
1646 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1647 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1649 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1651 /* decode response */
1653 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1654 if (rc || (pSMBr->ByteCount < 2))
1655 /* BB also check enough total bytes returned */
1656 rc = -EIO; /* bad smb */
1658 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1659 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1661 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1662 name_len = UniStrnlen((wchar_t *) ((char *)
1663 &pSMBr->hdr.Protocol +data_offset),
1664 min_t(const int, buflen,count) / 2);
1665 /* BB FIXME investigate remapping reserved chars here */
1666 cifs_strfromUCS_le(symlinkinfo,
1667 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1669 name_len, nls_codepage);
1671 strncpy(symlinkinfo,
1672 (char *) &pSMBr->hdr.Protocol +
1674 min_t(const int, buflen, count));
1676 symlinkinfo[buflen] = 0;
1677 /* just in case so calling code does not go off the end of buffer */
1680 cifs_buf_release(pSMB);
1682 goto querySymLinkRetry;
1687 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1688 const unsigned char *searchName,
1689 char *symlinkinfo, const int buflen,__u16 fid,
1690 const struct nls_table *nls_codepage)
1695 struct smb_com_transaction_ioctl_req * pSMB;
1696 struct smb_com_transaction_ioctl_rsp * pSMBr;
1698 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1699 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1704 pSMB->TotalParameterCount = 0 ;
1705 pSMB->TotalDataCount = 0;
1706 pSMB->MaxParameterCount = cpu_to_le32(2);
1707 /* BB find exact data count max from sess structure BB */
1708 pSMB->MaxDataCount = cpu_to_le32(4000);
1709 pSMB->MaxSetupCount = 4;
1711 pSMB->ParameterOffset = 0;
1712 pSMB->DataCount = 0;
1713 pSMB->DataOffset = 0;
1714 pSMB->SetupCount = 4;
1715 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1716 pSMB->ParameterCount = pSMB->TotalParameterCount;
1717 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1718 pSMB->IsFsctl = 1; /* FSCTL */
1719 pSMB->IsRootFlag = 0;
1720 pSMB->Fid = fid; /* file handle always le */
1721 pSMB->ByteCount = 0;
1723 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1724 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1726 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1727 } else { /* decode response */
1728 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1729 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1730 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1731 /* BB also check enough total bytes returned */
1732 rc = -EIO; /* bad smb */
1734 if(data_count && (data_count < 2048)) {
1735 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1737 struct reparse_data * reparse_buf = (struct reparse_data *)
1738 ((char *)&pSMBr->hdr.Protocol + data_offset);
1739 if((char*)reparse_buf >= end_of_smb) {
1743 if((reparse_buf->LinkNamesBuf +
1744 reparse_buf->TargetNameOffset +
1745 reparse_buf->TargetNameLen) >
1747 cFYI(1,("reparse buf extended beyond SMB"));
1752 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1753 name_len = UniStrnlen((wchar_t *)
1754 (reparse_buf->LinkNamesBuf +
1755 reparse_buf->TargetNameOffset),
1756 min(buflen/2, reparse_buf->TargetNameLen / 2));
1757 cifs_strfromUCS_le(symlinkinfo,
1758 (wchar_t *) (reparse_buf->LinkNamesBuf +
1759 reparse_buf->TargetNameOffset),
1760 name_len, nls_codepage);
1761 } else { /* ASCII names */
1762 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1763 reparse_buf->TargetNameOffset,
1764 min_t(const int, buflen, reparse_buf->TargetNameLen));
1768 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1770 symlinkinfo[buflen] = 0; /* just in case so the caller
1771 does not go off the end of the buffer */
1772 cFYI(1,("readlink result - %s ",symlinkinfo));
1777 cifs_buf_release(pSMB);
1779 /* Note: On -EAGAIN error only caller can retry on handle based calls
1780 since file handle passed in no longer valid */
1785 #ifdef CONFIG_CIFS_POSIX
1787 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1788 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1790 /* u8 cifs fields do not need le conversion */
1791 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1792 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1793 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1794 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1799 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1800 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1801 const int acl_type,const int size_of_data_area)
1806 struct cifs_posix_ace * pACE;
1807 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1808 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1810 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1813 if(acl_type & ACL_TYPE_ACCESS) {
1814 count = le16_to_cpu(cifs_acl->access_entry_count);
1815 pACE = &cifs_acl->ace_array[0];
1816 size = sizeof(struct cifs_posix_acl);
1817 size += sizeof(struct cifs_posix_ace) * count;
1818 /* check if we would go beyond end of SMB */
1819 if(size_of_data_area < size) {
1820 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1823 } else if(acl_type & ACL_TYPE_DEFAULT) {
1824 count = le16_to_cpu(cifs_acl->access_entry_count);
1825 size = sizeof(struct cifs_posix_acl);
1826 size += sizeof(struct cifs_posix_ace) * count;
1827 /* skip past access ACEs to get to default ACEs */
1828 pACE = &cifs_acl->ace_array[count];
1829 count = le16_to_cpu(cifs_acl->default_entry_count);
1830 size += sizeof(struct cifs_posix_ace) * count;
1831 /* check if we would go beyond end of SMB */
1832 if(size_of_data_area < size)
1839 size = posix_acl_xattr_size(count);
1840 if((buflen == 0) || (local_acl == NULL)) {
1841 /* used to query ACL EA size */
1842 } else if(size > buflen) {
1844 } else /* buffer big enough */ {
1845 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1846 for(i = 0;i < count ;i++) {
1847 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1854 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1855 const posix_acl_xattr_entry * local_ace)
1857 __u16 rc = 0; /* 0 = ACL converted ok */
1859 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1860 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1861 /* BB is there a better way to handle the large uid? */
1862 if(local_ace->e_id == -1) {
1863 /* Probably no need to le convert -1 on any arch but can not hurt */
1864 cifs_ace->cifs_uid = cpu_to_le64(-1);
1866 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1867 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1871 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1872 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1876 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1877 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1881 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1884 count = posix_acl_xattr_count((size_t)buflen);
1885 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1886 count,buflen,local_acl->a_version));
1887 if(local_acl->a_version != 2) {
1888 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1891 cifs_acl->version = cpu_to_le16(1);
1892 if(acl_type == ACL_TYPE_ACCESS)
1893 cifs_acl->access_entry_count = count;
1894 else if(acl_type == ACL_TYPE_DEFAULT)
1895 cifs_acl->default_entry_count = count;
1897 cFYI(1,("unknown ACL type %d",acl_type));
1900 for(i=0;i<count;i++) {
1901 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1902 &local_acl->a_entries[i]);
1904 /* ACE not converted */
1909 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1910 rc += sizeof(struct cifs_posix_acl);
1911 /* BB add check to make sure ACL does not overflow SMB */
1917 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1918 const unsigned char *searchName,
1919 char *acl_inf, const int buflen, const int acl_type,
1920 const struct nls_table *nls_codepage, int remap)
1922 /* SMB_QUERY_POSIX_ACL */
1923 TRANSACTION2_QPI_REQ *pSMB = NULL;
1924 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1928 __u16 params, byte_count;
1930 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1933 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1938 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1940 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
1941 PATH_MAX, nls_codepage, remap);
1942 name_len++; /* trailing null */
1944 pSMB->FileName[name_len] = 0;
1945 pSMB->FileName[name_len+1] = 0;
1946 } else { /* BB improve the check for buffer overruns BB */
1947 name_len = strnlen(searchName, PATH_MAX);
1948 name_len++; /* trailing null */
1949 strncpy(pSMB->FileName, searchName, name_len);
1952 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1953 pSMB->TotalDataCount = 0;
1954 pSMB->MaxParameterCount = cpu_to_le16(2);
1955 /* BB find exact max data count below from sess structure BB */
1956 pSMB->MaxDataCount = cpu_to_le16(4000);
1957 pSMB->MaxSetupCount = 0;
1961 pSMB->Reserved2 = 0;
1962 pSMB->ParameterOffset = cpu_to_le16(
1963 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1964 pSMB->DataCount = 0;
1965 pSMB->DataOffset = 0;
1966 pSMB->SetupCount = 1;
1967 pSMB->Reserved3 = 0;
1968 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1969 byte_count = params + 1 /* pad */ ;
1970 pSMB->TotalParameterCount = cpu_to_le16(params);
1971 pSMB->ParameterCount = pSMB->TotalParameterCount;
1972 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
1973 pSMB->Reserved4 = 0;
1974 pSMB->hdr.smb_buf_length += byte_count;
1975 pSMB->ByteCount = cpu_to_le16(byte_count);
1977 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1978 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1980 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
1982 /* decode response */
1984 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1985 if (rc || (pSMBr->ByteCount < 2))
1986 /* BB also check enough total bytes returned */
1987 rc = -EIO; /* bad smb */
1989 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1990 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1991 rc = cifs_copy_posix_acl(acl_inf,
1992 (char *)&pSMBr->hdr.Protocol+data_offset,
1993 buflen,acl_type,count);
1996 cifs_buf_release(pSMB);
2003 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2004 const unsigned char *fileName,
2005 const char *local_acl, const int buflen,
2007 const struct nls_table *nls_codepage, int remap)
2009 struct smb_com_transaction2_spi_req *pSMB = NULL;
2010 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2014 int bytes_returned = 0;
2015 __u16 params, byte_count, data_count, param_offset, offset;
2017 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2019 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2023 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2025 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
2026 PATH_MAX, nls_codepage, remap);
2027 name_len++; /* trailing null */
2029 } else { /* BB improve the check for buffer overruns BB */
2030 name_len = strnlen(fileName, PATH_MAX);
2031 name_len++; /* trailing null */
2032 strncpy(pSMB->FileName, fileName, name_len);
2034 params = 6 + name_len;
2035 pSMB->MaxParameterCount = cpu_to_le16(2);
2036 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2037 pSMB->MaxSetupCount = 0;
2041 pSMB->Reserved2 = 0;
2042 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2043 InformationLevel) - 4;
2044 offset = param_offset + params;
2045 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2046 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2048 /* convert to on the wire format for POSIX ACL */
2049 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2051 if(data_count == 0) {
2053 goto setACLerrorExit;
2055 pSMB->DataOffset = cpu_to_le16(offset);
2056 pSMB->SetupCount = 1;
2057 pSMB->Reserved3 = 0;
2058 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2059 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2060 byte_count = 3 /* pad */ + params + data_count;
2061 pSMB->DataCount = cpu_to_le16(data_count);
2062 pSMB->TotalDataCount = pSMB->DataCount;
2063 pSMB->ParameterCount = cpu_to_le16(params);
2064 pSMB->TotalParameterCount = pSMB->ParameterCount;
2065 pSMB->Reserved4 = 0;
2066 pSMB->hdr.smb_buf_length += byte_count;
2067 pSMB->ByteCount = cpu_to_le16(byte_count);
2068 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2069 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2071 cFYI(1, ("Set POSIX ACL returned %d", rc));
2075 cifs_buf_release(pSMB);
2081 /* BB fix tabs in this function FIXME BB */
2083 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2084 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2087 struct smb_t2_qfi_req *pSMB = NULL;
2088 struct smb_t2_qfi_rsp *pSMBr = NULL;
2090 __u16 params, byte_count;
2092 cFYI(1,("In GetExtAttr"));
2097 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2102 params = 2 /* level */ +2 /* fid */;
2103 pSMB->t2.TotalDataCount = 0;
2104 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2105 /* BB find exact max data count below from sess structure BB */
2106 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2107 pSMB->t2.MaxSetupCount = 0;
2108 pSMB->t2.Reserved = 0;
2110 pSMB->t2.Timeout = 0;
2111 pSMB->t2.Reserved2 = 0;
2112 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2114 pSMB->t2.DataCount = 0;
2115 pSMB->t2.DataOffset = 0;
2116 pSMB->t2.SetupCount = 1;
2117 pSMB->t2.Reserved3 = 0;
2118 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2119 byte_count = params + 1 /* pad */ ;
2120 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2121 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2122 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2125 pSMB->hdr.smb_buf_length += byte_count;
2126 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2128 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2129 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2131 cFYI(1, ("error %d in GetExtAttr", rc));
2133 /* decode response */
2134 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2135 if (rc || (pSMBr->ByteCount < 2))
2136 /* BB also check enough total bytes returned */
2137 /* If rc should we check for EOPNOSUPP and
2138 disable the srvino flag? or in caller? */
2139 rc = -EIO; /* bad smb */
2141 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2142 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2143 struct file_chattr_info * pfinfo;
2144 /* BB Do we need a cast or hash here ? */
2146 cFYI(1, ("Illegal size ret in GetExtAttr"));
2150 pfinfo = (struct file_chattr_info *)
2151 (data_offset + (char *) &pSMBr->hdr.Protocol);
2152 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2153 *pMask = le64_to_cpu(pfinfo->mask);
2157 cifs_buf_release(pSMB);
2159 goto GetExtAttrRetry;
2164 #endif /* CONFIG_POSIX */
2167 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2168 const unsigned char *searchName,
2169 FILE_ALL_INFO * pFindData,
2170 const struct nls_table *nls_codepage, int remap)
2172 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2173 TRANSACTION2_QPI_REQ *pSMB = NULL;
2174 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2178 __u16 params, byte_count;
2180 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2182 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2187 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2189 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2190 PATH_MAX, nls_codepage, remap);
2191 name_len++; /* trailing null */
2193 } else { /* BB improve the check for buffer overruns BB */
2194 name_len = strnlen(searchName, PATH_MAX);
2195 name_len++; /* trailing null */
2196 strncpy(pSMB->FileName, searchName, name_len);
2199 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2200 pSMB->TotalDataCount = 0;
2201 pSMB->MaxParameterCount = cpu_to_le16(2);
2202 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2203 pSMB->MaxSetupCount = 0;
2207 pSMB->Reserved2 = 0;
2208 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2209 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2210 pSMB->DataCount = 0;
2211 pSMB->DataOffset = 0;
2212 pSMB->SetupCount = 1;
2213 pSMB->Reserved3 = 0;
2214 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2215 byte_count = params + 1 /* pad */ ;
2216 pSMB->TotalParameterCount = cpu_to_le16(params);
2217 pSMB->ParameterCount = pSMB->TotalParameterCount;
2218 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2219 pSMB->Reserved4 = 0;
2220 pSMB->hdr.smb_buf_length += byte_count;
2221 pSMB->ByteCount = cpu_to_le16(byte_count);
2223 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2224 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2226 cFYI(1, ("Send error in QPathInfo = %d", rc));
2227 } else { /* decode response */
2228 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2230 if (rc || (pSMBr->ByteCount < 40))
2231 rc = -EIO; /* bad smb */
2232 else if (pFindData){
2233 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2234 memcpy((char *) pFindData,
2235 (char *) &pSMBr->hdr.Protocol +
2236 data_offset, sizeof (FILE_ALL_INFO));
2240 cifs_buf_release(pSMB);
2242 goto QPathInfoRetry;
2248 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2249 const unsigned char *searchName,
2250 FILE_UNIX_BASIC_INFO * pFindData,
2251 const struct nls_table *nls_codepage, int remap)
2253 /* SMB_QUERY_FILE_UNIX_BASIC */
2254 TRANSACTION2_QPI_REQ *pSMB = NULL;
2255 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2257 int bytes_returned = 0;
2259 __u16 params, byte_count;
2261 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2263 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2268 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2270 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2271 PATH_MAX, nls_codepage, remap);
2272 name_len++; /* trailing null */
2274 } else { /* BB improve the check for buffer overruns BB */
2275 name_len = strnlen(searchName, PATH_MAX);
2276 name_len++; /* trailing null */
2277 strncpy(pSMB->FileName, searchName, name_len);
2280 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2281 pSMB->TotalDataCount = 0;
2282 pSMB->MaxParameterCount = cpu_to_le16(2);
2283 /* BB find exact max SMB PDU from sess structure BB */
2284 pSMB->MaxDataCount = cpu_to_le16(4000);
2285 pSMB->MaxSetupCount = 0;
2289 pSMB->Reserved2 = 0;
2290 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2291 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2292 pSMB->DataCount = 0;
2293 pSMB->DataOffset = 0;
2294 pSMB->SetupCount = 1;
2295 pSMB->Reserved3 = 0;
2296 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2297 byte_count = params + 1 /* pad */ ;
2298 pSMB->TotalParameterCount = cpu_to_le16(params);
2299 pSMB->ParameterCount = pSMB->TotalParameterCount;
2300 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2301 pSMB->Reserved4 = 0;
2302 pSMB->hdr.smb_buf_length += byte_count;
2303 pSMB->ByteCount = cpu_to_le16(byte_count);
2305 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2306 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2308 cFYI(1, ("Send error in QPathInfo = %d", rc));
2309 } else { /* decode response */
2310 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2312 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2313 rc = -EIO; /* bad smb */
2315 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2316 memcpy((char *) pFindData,
2317 (char *) &pSMBr->hdr.Protocol +
2319 sizeof (FILE_UNIX_BASIC_INFO));
2322 cifs_buf_release(pSMB);
2324 goto UnixQPathInfoRetry;
2329 #if 0 /* function unused at present */
2330 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2331 const char *searchName, FILE_ALL_INFO * findData,
2332 const struct nls_table *nls_codepage)
2334 /* level 257 SMB_ */
2335 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2336 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2340 __u16 params, byte_count;
2342 cFYI(1, ("In FindUnique"));
2344 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2349 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2351 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2352 /* find define for this maxpathcomponent */
2354 name_len++; /* trailing null */
2356 } else { /* BB improve the check for buffer overruns BB */
2357 name_len = strnlen(searchName, PATH_MAX);
2358 name_len++; /* trailing null */
2359 strncpy(pSMB->FileName, searchName, name_len);
2362 params = 12 + name_len /* includes null */ ;
2363 pSMB->TotalDataCount = 0; /* no EAs */
2364 pSMB->MaxParameterCount = cpu_to_le16(2);
2365 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2366 pSMB->MaxSetupCount = 0;
2370 pSMB->Reserved2 = 0;
2371 pSMB->ParameterOffset = cpu_to_le16(
2372 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2373 pSMB->DataCount = 0;
2374 pSMB->DataOffset = 0;
2375 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2376 pSMB->Reserved3 = 0;
2377 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2378 byte_count = params + 1 /* pad */ ;
2379 pSMB->TotalParameterCount = cpu_to_le16(params);
2380 pSMB->ParameterCount = pSMB->TotalParameterCount;
2381 pSMB->SearchAttributes =
2382 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2384 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2385 pSMB->SearchFlags = cpu_to_le16(1);
2386 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2387 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2388 pSMB->hdr.smb_buf_length += byte_count;
2389 pSMB->ByteCount = cpu_to_le16(byte_count);
2391 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2392 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2395 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2396 } else { /* decode response */
2401 cifs_buf_release(pSMB);
2403 goto findUniqueRetry;
2407 #endif /* end unused (temporarily) function */
2409 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2411 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2412 const char *searchName,
2413 const struct nls_table *nls_codepage,
2415 struct cifs_search_info * psrch_inf, int remap)
2417 /* level 257 SMB_ */
2418 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2419 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2420 T2_FFIRST_RSP_PARMS * parms;
2422 int bytes_returned = 0;
2424 __u16 params, byte_count;
2426 cFYI(1, ("In FindFirst for %s",searchName));
2429 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2434 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2436 cifsConvertToUCS((__u16 *) pSMB->FileName,searchName,
2437 PATH_MAX, nls_codepage, remap);
2438 /* We can not add the asterik earlier in case
2439 it got remapped to 0xF03A as if it were part of the
2440 directory name instead of a wildcard */
2442 pSMB->FileName[name_len] = '\\';
2443 pSMB->FileName[name_len+1] = 0;
2444 pSMB->FileName[name_len+2] = '*';
2445 pSMB->FileName[name_len+3] = 0;
2446 name_len += 4; /* now the trailing null */
2447 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2448 pSMB->FileName[name_len+1] = 0;
2450 } else { /* BB add check for overrun of SMB buf BB */
2451 name_len = strnlen(searchName, PATH_MAX);
2452 name_len++; /* trailing null */
2453 /* BB fix here and in unicode clause above ie
2454 if(name_len > buffersize-header)
2455 free buffer exit; BB */
2456 strncpy(pSMB->FileName, searchName, name_len);
2457 pSMB->FileName[name_len] = 0; /* just in case */
2460 params = 12 + name_len /* includes null */ ;
2461 pSMB->TotalDataCount = 0; /* no EAs */
2462 pSMB->MaxParameterCount = cpu_to_le16(10);
2463 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2464 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2465 pSMB->MaxSetupCount = 0;
2469 pSMB->Reserved2 = 0;
2470 byte_count = params + 1 /* pad */ ;
2471 pSMB->TotalParameterCount = cpu_to_le16(params);
2472 pSMB->ParameterCount = pSMB->TotalParameterCount;
2473 pSMB->ParameterOffset = cpu_to_le16(
2474 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2475 pSMB->DataCount = 0;
2476 pSMB->DataOffset = 0;
2477 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2478 pSMB->Reserved3 = 0;
2479 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2480 pSMB->SearchAttributes =
2481 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2483 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2484 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2485 CIFS_SEARCH_RETURN_RESUME);
2486 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2488 /* BB what should we set StorageType to? Does it matter? BB */
2489 pSMB->SearchStorageType = 0;
2490 pSMB->hdr.smb_buf_length += byte_count;
2491 pSMB->ByteCount = cpu_to_le16(byte_count);
2493 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2494 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2496 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2497 /* BB Add code to handle unsupported level rc */
2498 cFYI(1, ("Error in FindFirst = %d", rc));
2501 cifs_buf_release(pSMB);
2503 /* BB eventually could optimize out free and realloc of buf */
2506 goto findFirstRetry;
2507 } else { /* decode response */
2508 /* BB remember to free buffer if error BB */
2509 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2511 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2512 psrch_inf->unicode = TRUE;
2514 psrch_inf->unicode = FALSE;
2516 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2517 psrch_inf->srch_entries_start =
2518 (char *) &pSMBr->hdr.Protocol +
2519 le16_to_cpu(pSMBr->t2.DataOffset);
2520 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2521 le16_to_cpu(pSMBr->t2.ParameterOffset));
2523 if(parms->EndofSearch)
2524 psrch_inf->endOfSearch = TRUE;
2526 psrch_inf->endOfSearch = FALSE;
2528 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2529 psrch_inf->index_of_last_entry =
2530 psrch_inf->entries_in_buffer;
2531 *pnetfid = parms->SearchHandle;
2533 cifs_buf_release(pSMB);
2540 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2541 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2543 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2544 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2545 T2_FNEXT_RSP_PARMS * parms;
2546 char *response_data;
2548 int bytes_returned, name_len;
2549 __u16 params, byte_count;
2551 cFYI(1, ("In FindNext"));
2553 if(psrch_inf->endOfSearch == TRUE)
2556 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2561 params = 14; /* includes 2 bytes of null string, converted to LE below */
2563 pSMB->TotalDataCount = 0; /* no EAs */
2564 pSMB->MaxParameterCount = cpu_to_le16(8);
2565 pSMB->MaxDataCount =
2566 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2567 pSMB->MaxSetupCount = 0;
2571 pSMB->Reserved2 = 0;
2572 pSMB->ParameterOffset = cpu_to_le16(
2573 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2574 pSMB->DataCount = 0;
2575 pSMB->DataOffset = 0;
2576 pSMB->SetupCount = 1;
2577 pSMB->Reserved3 = 0;
2578 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2579 pSMB->SearchHandle = searchHandle; /* always kept as le */
2581 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2582 /* test for Unix extensions */
2583 /* if (tcon->ses->capabilities & CAP_UNIX) {
2584 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2585 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2587 pSMB->InformationLevel =
2588 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2589 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2591 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2592 pSMB->ResumeKey = psrch_inf->resume_key;
2594 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2596 name_len = psrch_inf->resume_name_len;
2598 if(name_len < PATH_MAX) {
2599 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2600 byte_count += name_len;
2603 goto FNext2_err_exit;
2605 byte_count = params + 1 /* pad */ ;
2606 pSMB->TotalParameterCount = cpu_to_le16(params);
2607 pSMB->ParameterCount = pSMB->TotalParameterCount;
2608 pSMB->hdr.smb_buf_length += byte_count;
2609 pSMB->ByteCount = cpu_to_le16(byte_count);
2611 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2612 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2616 psrch_inf->endOfSearch = TRUE;
2617 rc = 0; /* search probably was closed at end of search above */
2619 cFYI(1, ("FindNext returned = %d", rc));
2620 } else { /* decode response */
2621 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2624 /* BB fixme add lock for file (srch_info) struct here */
2625 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2626 psrch_inf->unicode = TRUE;
2628 psrch_inf->unicode = FALSE;
2629 response_data = (char *) &pSMBr->hdr.Protocol +
2630 le16_to_cpu(pSMBr->t2.ParameterOffset);
2631 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2632 response_data = (char *)&pSMBr->hdr.Protocol +
2633 le16_to_cpu(pSMBr->t2.DataOffset);
2634 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2635 psrch_inf->srch_entries_start = response_data;
2636 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2637 if(parms->EndofSearch)
2638 psrch_inf->endOfSearch = TRUE;
2640 psrch_inf->endOfSearch = FALSE;
2642 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2643 psrch_inf->index_of_last_entry +=
2644 psrch_inf->entries_in_buffer;
2645 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2647 /* BB fixme add unlock here */
2652 /* BB On error, should we leave previous search buf (and count and
2653 last entry fields) intact or free the previous one? */
2655 /* Note: On -EAGAIN error only caller can retry on handle based calls
2656 since file handle passed in no longer valid */
2659 cifs_buf_release(pSMB);
2665 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2668 FINDCLOSE_REQ *pSMB = NULL;
2669 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2672 cFYI(1, ("In CIFSSMBFindClose"));
2673 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2675 /* no sense returning error if session restarted
2676 as file handle has been closed */
2682 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2683 pSMB->FileID = searchHandle;
2684 pSMB->ByteCount = 0;
2685 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2686 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2688 cERROR(1, ("Send error in FindClose = %d", rc));
2690 cifs_small_buf_release(pSMB);
2692 /* Since session is dead, search handle closed on server already */
2699 #ifdef CONFIG_CIFS_EXPERIMENTAL
2701 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2702 const unsigned char *searchName,
2703 __u64 * inode_number,
2704 const struct nls_table *nls_codepage, int remap)
2707 TRANSACTION2_QPI_REQ *pSMB = NULL;
2708 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2709 int name_len, bytes_returned;
2710 __u16 params, byte_count;
2712 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2716 GetInodeNumberRetry:
2717 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2723 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2725 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
2726 PATH_MAX,nls_codepage, remap);
2727 name_len++; /* trailing null */
2729 } else { /* BB improve the check for buffer overruns BB */
2730 name_len = strnlen(searchName, PATH_MAX);
2731 name_len++; /* trailing null */
2732 strncpy(pSMB->FileName, searchName, name_len);
2735 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2736 pSMB->TotalDataCount = 0;
2737 pSMB->MaxParameterCount = cpu_to_le16(2);
2738 /* BB find exact max data count below from sess structure BB */
2739 pSMB->MaxDataCount = cpu_to_le16(4000);
2740 pSMB->MaxSetupCount = 0;
2744 pSMB->Reserved2 = 0;
2745 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2746 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2747 pSMB->DataCount = 0;
2748 pSMB->DataOffset = 0;
2749 pSMB->SetupCount = 1;
2750 pSMB->Reserved3 = 0;
2751 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2752 byte_count = params + 1 /* pad */ ;
2753 pSMB->TotalParameterCount = cpu_to_le16(params);
2754 pSMB->ParameterCount = pSMB->TotalParameterCount;
2755 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
2756 pSMB->Reserved4 = 0;
2757 pSMB->hdr.smb_buf_length += byte_count;
2758 pSMB->ByteCount = cpu_to_le16(byte_count);
2760 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2761 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2763 cFYI(1, ("error %d in QueryInternalInfo", rc));
2765 /* decode response */
2766 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2767 if (rc || (pSMBr->ByteCount < 2))
2768 /* BB also check enough total bytes returned */
2769 /* If rc should we check for EOPNOSUPP and
2770 disable the srvino flag? or in caller? */
2771 rc = -EIO; /* bad smb */
2773 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2774 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2775 struct file_internal_info * pfinfo;
2776 /* BB Do we need a cast or hash here ? */
2778 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2780 goto GetInodeNumOut;
2782 pfinfo = (struct file_internal_info *)
2783 (data_offset + (char *) &pSMBr->hdr.Protocol);
2784 *inode_number = pfinfo->UniqueId;
2788 cifs_buf_release(pSMB);
2790 goto GetInodeNumberRetry;
2793 #endif /* CIFS_EXPERIMENTAL */
2796 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2797 const unsigned char *searchName,
2798 unsigned char **targetUNCs,
2799 unsigned int *number_of_UNC_in_array,
2800 const struct nls_table *nls_codepage, int remap)
2802 /* TRANS2_GET_DFS_REFERRAL */
2803 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2804 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2805 struct dfs_referral_level_3 * referrals = NULL;
2811 __u16 params, byte_count;
2812 *number_of_UNC_in_array = 0;
2815 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2819 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2824 pSMB->hdr.Tid = ses->ipc_tid;
2825 pSMB->hdr.Uid = ses->Suid;
2826 if (ses->capabilities & CAP_STATUS32) {
2827 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2829 if (ses->capabilities & CAP_DFS) {
2830 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2833 if (ses->capabilities & CAP_UNICODE) {
2834 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2836 cifsConvertToUCS((__u16 *) pSMB->RequestFileName,
2837 searchName, PATH_MAX, nls_codepage, remap);
2838 name_len++; /* trailing null */
2840 } else { /* BB improve the check for buffer overruns BB */
2841 name_len = strnlen(searchName, PATH_MAX);
2842 name_len++; /* trailing null */
2843 strncpy(pSMB->RequestFileName, searchName, name_len);
2846 params = 2 /* level */ + name_len /*includes null */ ;
2847 pSMB->TotalDataCount = 0;
2848 pSMB->DataCount = 0;
2849 pSMB->DataOffset = 0;
2850 pSMB->MaxParameterCount = 0;
2851 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2852 pSMB->MaxSetupCount = 0;
2856 pSMB->Reserved2 = 0;
2857 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2858 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2859 pSMB->SetupCount = 1;
2860 pSMB->Reserved3 = 0;
2861 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2862 byte_count = params + 3 /* pad */ ;
2863 pSMB->ParameterCount = cpu_to_le16(params);
2864 pSMB->TotalParameterCount = pSMB->ParameterCount;
2865 pSMB->MaxReferralLevel = cpu_to_le16(3);
2866 pSMB->hdr.smb_buf_length += byte_count;
2867 pSMB->ByteCount = cpu_to_le16(byte_count);
2869 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2870 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2872 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2873 } else { /* decode response */
2874 /* BB Add logic to parse referrals here */
2875 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2877 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
2878 rc = -EIO; /* bad smb */
2880 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2881 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2884 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2885 pSMBr->ByteCount, data_offset));
2887 (struct dfs_referral_level_3 *)
2888 (8 /* sizeof start of data block */ +
2890 (char *) &pSMBr->hdr.Protocol);
2891 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",
2892 le16_to_cpu(pSMBr->NumberOfReferrals),le16_to_cpu(pSMBr->DFSFlags), le16_to_cpu(referrals->ReferralSize),le16_to_cpu(referrals->ServerType),le16_to_cpu(referrals->ReferralFlags),le16_to_cpu(referrals->TimeToLive)));
2893 /* BB This field is actually two bytes in from start of
2894 data block so we could do safety check that DataBlock
2895 begins at address of pSMBr->NumberOfReferrals */
2896 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2898 /* BB Fix below so can return more than one referral */
2899 if(*number_of_UNC_in_array > 1)
2900 *number_of_UNC_in_array = 1;
2902 /* get the length of the strings describing refs */
2904 for(i=0;i<*number_of_UNC_in_array;i++) {
2905 /* make sure that DfsPathOffset not past end */
2906 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2907 if (offset > data_count) {
2908 /* if invalid referral, stop here and do
2909 not try to copy any more */
2910 *number_of_UNC_in_array = i;
2913 temp = ((char *)referrals) + offset;
2915 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2916 name_len += UniStrnlen((wchar_t *)temp,data_count);
2918 name_len += strnlen(temp,data_count);
2921 /* BB add check that referral pointer does not fall off end PDU */
2924 /* BB add check for name_len bigger than bcc */
2926 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2927 if(*targetUNCs == NULL) {
2931 /* copy the ref strings */
2933 (struct dfs_referral_level_3 *)
2934 (8 /* sizeof data hdr */ +
2936 (char *) &pSMBr->hdr.Protocol);
2938 for(i=0;i<*number_of_UNC_in_array;i++) {
2939 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2940 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2941 cifs_strfromUCS_le(*targetUNCs,
2942 (wchar_t *) temp, name_len, nls_codepage);
2944 strncpy(*targetUNCs,temp,name_len);
2946 /* BB update target_uncs pointers */
2956 cifs_buf_release(pSMB);
2965 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
2967 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2968 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2969 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2970 FILE_SYSTEM_INFO *response_data;
2972 int bytes_returned = 0;
2973 __u16 params, byte_count;
2975 cFYI(1, ("In QFSInfo"));
2977 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2982 params = 2; /* level */
2983 pSMB->TotalDataCount = 0;
2984 pSMB->MaxParameterCount = cpu_to_le16(2);
2985 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2986 pSMB->MaxSetupCount = 0;
2990 pSMB->Reserved2 = 0;
2991 byte_count = params + 1 /* pad */ ;
2992 pSMB->TotalParameterCount = cpu_to_le16(params);
2993 pSMB->ParameterCount = pSMB->TotalParameterCount;
2994 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2995 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2996 pSMB->DataCount = 0;
2997 pSMB->DataOffset = 0;
2998 pSMB->SetupCount = 1;
2999 pSMB->Reserved3 = 0;
3000 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3001 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3002 pSMB->hdr.smb_buf_length += byte_count;
3003 pSMB->ByteCount = cpu_to_le16(byte_count);
3005 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3006 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3008 cERROR(1, ("Send error in QFSInfo = %d", rc));
3009 } else { /* decode response */
3010 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3012 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3013 rc = -EIO; /* bad smb */
3015 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3017 ("Decoding qfsinfo response. BCC: %d Offset %d",
3018 pSMBr->ByteCount, data_offset));
3022 *) (((char *) &pSMBr->hdr.Protocol) +
3025 le32_to_cpu(response_data->BytesPerSector) *
3026 le32_to_cpu(response_data->
3027 SectorsPerAllocationUnit);
3029 le64_to_cpu(response_data->TotalAllocationUnits);
3030 FSData->f_bfree = FSData->f_bavail =
3031 le64_to_cpu(response_data->FreeAllocationUnits);
3033 ("Blocks: %lld Free: %lld Block size %ld",
3034 (unsigned long long)FSData->f_blocks,
3035 (unsigned long long)FSData->f_bfree,
3039 cifs_buf_release(pSMB);
3048 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3050 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3051 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3052 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3053 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3055 int bytes_returned = 0;
3056 __u16 params, byte_count;
3058 cFYI(1, ("In QFSAttributeInfo"));
3060 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3065 params = 2; /* level */
3066 pSMB->TotalDataCount = 0;
3067 pSMB->MaxParameterCount = cpu_to_le16(2);
3068 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3069 pSMB->MaxSetupCount = 0;
3073 pSMB->Reserved2 = 0;
3074 byte_count = params + 1 /* pad */ ;
3075 pSMB->TotalParameterCount = cpu_to_le16(params);
3076 pSMB->ParameterCount = pSMB->TotalParameterCount;
3077 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3078 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3079 pSMB->DataCount = 0;
3080 pSMB->DataOffset = 0;
3081 pSMB->SetupCount = 1;
3082 pSMB->Reserved3 = 0;
3083 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3084 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3085 pSMB->hdr.smb_buf_length += byte_count;
3086 pSMB->ByteCount = cpu_to_le16(byte_count);
3088 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3089 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3091 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3092 } else { /* decode response */
3093 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3095 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3096 rc = -EIO; /* bad smb */
3098 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3100 (FILE_SYSTEM_ATTRIBUTE_INFO
3101 *) (((char *) &pSMBr->hdr.Protocol) +
3103 memcpy(&tcon->fsAttrInfo, response_data,
3104 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3107 cifs_buf_release(pSMB);
3110 goto QFSAttributeRetry;
3116 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3118 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3119 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3120 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3121 FILE_SYSTEM_DEVICE_INFO *response_data;
3123 int bytes_returned = 0;
3124 __u16 params, byte_count;
3126 cFYI(1, ("In QFSDeviceInfo"));
3128 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3133 params = 2; /* level */
3134 pSMB->TotalDataCount = 0;
3135 pSMB->MaxParameterCount = cpu_to_le16(2);
3136 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3137 pSMB->MaxSetupCount = 0;
3141 pSMB->Reserved2 = 0;
3142 byte_count = params + 1 /* pad */ ;
3143 pSMB->TotalParameterCount = cpu_to_le16(params);
3144 pSMB->ParameterCount = pSMB->TotalParameterCount;
3145 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3146 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3148 pSMB->DataCount = 0;
3149 pSMB->DataOffset = 0;
3150 pSMB->SetupCount = 1;
3151 pSMB->Reserved3 = 0;
3152 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3153 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3154 pSMB->hdr.smb_buf_length += byte_count;
3155 pSMB->ByteCount = cpu_to_le16(byte_count);
3157 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3158 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3160 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3161 } else { /* decode response */
3162 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3164 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3165 rc = -EIO; /* bad smb */
3167 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3169 (FILE_SYSTEM_DEVICE_INFO *)
3170 (((char *) &pSMBr->hdr.Protocol) +
3172 memcpy(&tcon->fsDevInfo, response_data,
3173 sizeof (FILE_SYSTEM_DEVICE_INFO));
3176 cifs_buf_release(pSMB);
3179 goto QFSDeviceRetry;
3185 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3187 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3188 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3189 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3190 FILE_SYSTEM_UNIX_INFO *response_data;
3192 int bytes_returned = 0;
3193 __u16 params, byte_count;
3195 cFYI(1, ("In QFSUnixInfo"));
3197 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3202 params = 2; /* level */
3203 pSMB->TotalDataCount = 0;
3204 pSMB->DataCount = 0;
3205 pSMB->DataOffset = 0;
3206 pSMB->MaxParameterCount = cpu_to_le16(2);
3207 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3208 pSMB->MaxSetupCount = 0;
3212 pSMB->Reserved2 = 0;
3213 byte_count = params + 1 /* pad */ ;
3214 pSMB->ParameterCount = cpu_to_le16(params);
3215 pSMB->TotalParameterCount = pSMB->ParameterCount;
3216 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3217 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3218 pSMB->SetupCount = 1;
3219 pSMB->Reserved3 = 0;
3220 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3221 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3222 pSMB->hdr.smb_buf_length += byte_count;
3223 pSMB->ByteCount = cpu_to_le16(byte_count);
3225 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3226 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3228 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3229 } else { /* decode response */
3230 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3232 if (rc || (pSMBr->ByteCount < 13)) {
3233 rc = -EIO; /* bad smb */
3235 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3237 (FILE_SYSTEM_UNIX_INFO
3238 *) (((char *) &pSMBr->hdr.Protocol) +
3240 memcpy(&tcon->fsUnixInfo, response_data,
3241 sizeof (FILE_SYSTEM_UNIX_INFO));
3244 cifs_buf_release(pSMB);
3255 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3256 struct kstatfs *FSData)
3258 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3259 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3260 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3261 FILE_SYSTEM_POSIX_INFO *response_data;
3263 int bytes_returned = 0;
3264 __u16 params, byte_count;
3266 cFYI(1, ("In QFSPosixInfo"));
3268 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3273 params = 2; /* level */
3274 pSMB->TotalDataCount = 0;
3275 pSMB->DataCount = 0;
3276 pSMB->DataOffset = 0;
3277 pSMB->MaxParameterCount = cpu_to_le16(2);
3278 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3279 pSMB->MaxSetupCount = 0;
3283 pSMB->Reserved2 = 0;
3284 byte_count = params + 1 /* pad */ ;
3285 pSMB->ParameterCount = cpu_to_le16(params);
3286 pSMB->TotalParameterCount = pSMB->ParameterCount;
3287 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3288 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3289 pSMB->SetupCount = 1;
3290 pSMB->Reserved3 = 0;
3291 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3292 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3293 pSMB->hdr.smb_buf_length += byte_count;
3294 pSMB->ByteCount = cpu_to_le16(byte_count);
3296 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3297 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3299 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3300 } else { /* decode response */
3301 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3303 if (rc || (pSMBr->ByteCount < 13)) {
3304 rc = -EIO; /* bad smb */
3306 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3308 (FILE_SYSTEM_POSIX_INFO
3309 *) (((char *) &pSMBr->hdr.Protocol) +
3312 le32_to_cpu(response_data->BlockSize);
3314 le64_to_cpu(response_data->TotalBlocks);
3316 le64_to_cpu(response_data->BlocksAvail);
3317 if(response_data->UserBlocksAvail == -1) {
3318 FSData->f_bavail = FSData->f_bfree;
3321 le64_to_cpu(response_data->UserBlocksAvail);
3323 if(response_data->TotalFileNodes != -1)
3325 le64_to_cpu(response_data->TotalFileNodes);
3326 if(response_data->FreeFileNodes != -1)
3328 le64_to_cpu(response_data->FreeFileNodes);
3331 cifs_buf_release(pSMB);
3340 /* We can not use write of zero bytes trick to
3341 set file size due to need for large file support. Also note that
3342 this SetPathInfo is preferred to SetFileInfo based method in next
3343 routine which is only needed to work around a sharing violation bug
3344 in Samba which this routine can run into */
3347 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3348 __u64 size, int SetAllocation,
3349 const struct nls_table *nls_codepage, int remap)
3351 struct smb_com_transaction2_spi_req *pSMB = NULL;
3352 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3353 struct file_end_of_file_info *parm_data;
3356 int bytes_returned = 0;
3357 __u16 params, byte_count, data_count, param_offset, offset;
3359 cFYI(1, ("In SetEOF"));
3361 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3366 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3368 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3369 PATH_MAX, nls_codepage, remap);
3370 name_len++; /* trailing null */
3372 } else { /* BB improve the check for buffer overruns BB */
3373 name_len = strnlen(fileName, PATH_MAX);
3374 name_len++; /* trailing null */
3375 strncpy(pSMB->FileName, fileName, name_len);
3377 params = 6 + name_len;
3378 data_count = sizeof (struct file_end_of_file_info);
3379 pSMB->MaxParameterCount = cpu_to_le16(2);
3380 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3381 pSMB->MaxSetupCount = 0;
3385 pSMB->Reserved2 = 0;
3386 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3387 InformationLevel) - 4;
3388 offset = param_offset + params;
3390 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3391 pSMB->InformationLevel =
3392 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3394 pSMB->InformationLevel =
3395 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3396 } else /* Set File Size */ {
3397 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3398 pSMB->InformationLevel =
3399 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3401 pSMB->InformationLevel =
3402 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3406 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3408 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3409 pSMB->DataOffset = cpu_to_le16(offset);
3410 pSMB->SetupCount = 1;
3411 pSMB->Reserved3 = 0;
3412 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3413 byte_count = 3 /* pad */ + params + data_count;
3414 pSMB->DataCount = cpu_to_le16(data_count);
3415 pSMB->TotalDataCount = pSMB->DataCount;
3416 pSMB->ParameterCount = cpu_to_le16(params);
3417 pSMB->TotalParameterCount = pSMB->ParameterCount;
3418 pSMB->Reserved4 = 0;
3419 pSMB->hdr.smb_buf_length += byte_count;
3420 parm_data->FileSize = cpu_to_le64(size);
3421 pSMB->ByteCount = cpu_to_le16(byte_count);
3422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3425 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3428 cifs_buf_release(pSMB);
3437 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3438 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3440 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3441 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3443 struct file_end_of_file_info *parm_data;
3445 int bytes_returned = 0;
3446 __u16 params, param_offset, offset, byte_count, count;
3448 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3450 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3455 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3457 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3458 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3461 pSMB->MaxSetupCount = 0;
3465 pSMB->Reserved2 = 0;
3466 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3467 offset = param_offset + params;
3469 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3471 count = sizeof(struct file_end_of_file_info);
3472 pSMB->MaxParameterCount = cpu_to_le16(2);
3473 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3474 pSMB->SetupCount = 1;
3475 pSMB->Reserved3 = 0;
3476 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3477 byte_count = 3 /* pad */ + params + count;
3478 pSMB->DataCount = cpu_to_le16(count);
3479 pSMB->ParameterCount = cpu_to_le16(params);
3480 pSMB->TotalDataCount = pSMB->DataCount;
3481 pSMB->TotalParameterCount = pSMB->ParameterCount;
3482 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3484 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3486 pSMB->DataOffset = cpu_to_le16(offset);
3487 parm_data->FileSize = cpu_to_le64(size);
3490 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3491 pSMB->InformationLevel =
3492 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3494 pSMB->InformationLevel =
3495 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3496 } else /* Set File Size */ {
3497 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3498 pSMB->InformationLevel =
3499 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3501 pSMB->InformationLevel =
3502 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3504 pSMB->Reserved4 = 0;
3505 pSMB->hdr.smb_buf_length += byte_count;
3506 pSMB->ByteCount = cpu_to_le16(byte_count);
3507 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3508 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3511 ("Send error in SetFileInfo (SetFileSize) = %d",
3516 cifs_small_buf_release(pSMB);
3518 /* Note: On -EAGAIN error only caller can retry on handle based calls
3519 since file handle passed in no longer valid */
3524 /* Some legacy servers such as NT4 require that the file times be set on
3525 an open handle, rather than by pathname - this is awkward due to
3526 potential access conflicts on the open, but it is unavoidable for these
3527 old servers since the only other choice is to go from 100 nanosecond DCE
3528 time and resort to the original setpathinfo level which takes the ancient
3529 DOS time format with 2 second granularity */
3531 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3534 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3535 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3538 int bytes_returned = 0;
3539 __u16 params, param_offset, offset, byte_count, count;
3541 cFYI(1, ("Set Times (via SetFileInfo)"));
3542 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3547 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3549 /* At this point there is no need to override the current pid
3550 with the pid of the opener, but that could change if we someday
3551 use an existing handle (rather than opening one on the fly) */
3552 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3553 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3556 pSMB->MaxSetupCount = 0;
3560 pSMB->Reserved2 = 0;
3561 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3562 offset = param_offset + params;
3564 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3566 count = sizeof (FILE_BASIC_INFO);
3567 pSMB->MaxParameterCount = cpu_to_le16(2);
3568 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3569 pSMB->SetupCount = 1;
3570 pSMB->Reserved3 = 0;
3571 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3572 byte_count = 3 /* pad */ + params + count;
3573 pSMB->DataCount = cpu_to_le16(count);
3574 pSMB->ParameterCount = cpu_to_le16(params);
3575 pSMB->TotalDataCount = pSMB->DataCount;
3576 pSMB->TotalParameterCount = pSMB->ParameterCount;
3577 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3578 pSMB->DataOffset = cpu_to_le16(offset);
3580 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3581 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3583 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3584 pSMB->Reserved4 = 0;
3585 pSMB->hdr.smb_buf_length += byte_count;
3586 pSMB->ByteCount = cpu_to_le16(byte_count);
3587 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3588 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3589 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3591 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3594 cifs_small_buf_release(pSMB);
3596 /* Note: On -EAGAIN error only caller can retry on handle based calls
3597 since file handle passed in no longer valid */
3604 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3605 const FILE_BASIC_INFO * data,
3606 const struct nls_table *nls_codepage, int remap)
3608 TRANSACTION2_SPI_REQ *pSMB = NULL;
3609 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3612 int bytes_returned = 0;
3614 __u16 params, param_offset, offset, byte_count, count;
3616 cFYI(1, ("In SetTimes"));
3619 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3624 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3626 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3627 PATH_MAX, nls_codepage, remap);
3628 name_len++; /* trailing null */
3630 } else { /* BB improve the check for buffer overruns BB */
3631 name_len = strnlen(fileName, PATH_MAX);
3632 name_len++; /* trailing null */
3633 strncpy(pSMB->FileName, fileName, name_len);
3636 params = 6 + name_len;
3637 count = sizeof (FILE_BASIC_INFO);
3638 pSMB->MaxParameterCount = cpu_to_le16(2);
3639 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3640 pSMB->MaxSetupCount = 0;
3644 pSMB->Reserved2 = 0;
3645 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3646 InformationLevel) - 4;
3647 offset = param_offset + params;
3648 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3649 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3650 pSMB->DataOffset = cpu_to_le16(offset);
3651 pSMB->SetupCount = 1;
3652 pSMB->Reserved3 = 0;
3653 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3654 byte_count = 3 /* pad */ + params + count;
3656 pSMB->DataCount = cpu_to_le16(count);
3657 pSMB->ParameterCount = cpu_to_le16(params);
3658 pSMB->TotalDataCount = pSMB->DataCount;
3659 pSMB->TotalParameterCount = pSMB->ParameterCount;
3660 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3661 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3663 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3664 pSMB->Reserved4 = 0;
3665 pSMB->hdr.smb_buf_length += byte_count;
3666 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3667 pSMB->ByteCount = cpu_to_le16(byte_count);
3668 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3669 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3671 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3674 cifs_buf_release(pSMB);
3682 /* Can not be used to set time stamps yet (due to old DOS time format) */
3683 /* Can be used to set attributes */
3684 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3685 handling it anyway and NT4 was what we thought it would be needed for
3686 Do not delete it until we prove whether needed for Win9x though */
3688 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3689 __u16 dos_attrs, const struct nls_table *nls_codepage)
3691 SETATTR_REQ *pSMB = NULL;
3692 SETATTR_RSP *pSMBr = NULL;
3697 cFYI(1, ("In SetAttrLegacy"));
3700 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
3705 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3707 ConvertToUCS((wchar_t *) pSMB->fileName, fileName,
3708 PATH_MAX, nls_codepage);
3709 name_len++; /* trailing null */
3711 } else { /* BB improve the check for buffer overruns BB */
3712 name_len = strnlen(fileName, PATH_MAX);
3713 name_len++; /* trailing null */
3714 strncpy(pSMB->fileName, fileName, name_len);
3716 pSMB->attr = cpu_to_le16(dos_attrs);
3717 pSMB->BufferFormat = 0x04;
3718 pSMB->hdr.smb_buf_length += name_len + 1;
3719 pSMB->ByteCount = cpu_to_le16(name_len + 1);
3720 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3721 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3723 cFYI(1, ("Error in LegacySetAttr = %d", rc));
3726 cifs_buf_release(pSMB);
3729 goto SetAttrLgcyRetry;
3733 #endif /* temporarily unneeded SetAttr legacy function */
3736 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3737 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3738 dev_t device, const struct nls_table *nls_codepage,
3741 TRANSACTION2_SPI_REQ *pSMB = NULL;
3742 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3745 int bytes_returned = 0;
3746 FILE_UNIX_BASIC_INFO *data_offset;
3747 __u16 params, param_offset, offset, count, byte_count;
3749 cFYI(1, ("In SetUID/GID/Mode"));
3751 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3756 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3758 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
3759 PATH_MAX, nls_codepage, remap);
3760 name_len++; /* trailing null */
3762 } else { /* BB improve the check for buffer overruns BB */
3763 name_len = strnlen(fileName, PATH_MAX);
3764 name_len++; /* trailing null */
3765 strncpy(pSMB->FileName, fileName, name_len);
3768 params = 6 + name_len;
3769 count = sizeof (FILE_UNIX_BASIC_INFO);
3770 pSMB->MaxParameterCount = cpu_to_le16(2);
3771 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3772 pSMB->MaxSetupCount = 0;
3776 pSMB->Reserved2 = 0;
3777 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3778 InformationLevel) - 4;
3779 offset = param_offset + params;
3781 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3783 memset(data_offset, 0, count);
3784 pSMB->DataOffset = cpu_to_le16(offset);
3785 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3786 pSMB->SetupCount = 1;
3787 pSMB->Reserved3 = 0;
3788 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3789 byte_count = 3 /* pad */ + params + count;
3790 pSMB->ParameterCount = cpu_to_le16(params);
3791 pSMB->DataCount = cpu_to_le16(count);
3792 pSMB->TotalParameterCount = pSMB->ParameterCount;
3793 pSMB->TotalDataCount = pSMB->DataCount;
3794 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3795 pSMB->Reserved4 = 0;
3796 pSMB->hdr.smb_buf_length += byte_count;
3797 data_offset->Uid = cpu_to_le64(uid);
3798 data_offset->Gid = cpu_to_le64(gid);
3799 /* better to leave device as zero when it is */
3800 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3801 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3802 data_offset->Permissions = cpu_to_le64(mode);
3805 data_offset->Type = cpu_to_le32(UNIX_FILE);
3806 else if(S_ISDIR(mode))
3807 data_offset->Type = cpu_to_le32(UNIX_DIR);
3808 else if(S_ISLNK(mode))
3809 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3810 else if(S_ISCHR(mode))
3811 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3812 else if(S_ISBLK(mode))
3813 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3814 else if(S_ISFIFO(mode))
3815 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3816 else if(S_ISSOCK(mode))
3817 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3820 pSMB->ByteCount = cpu_to_le16(byte_count);
3821 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3822 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3824 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3828 cifs_buf_release(pSMB);
3834 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3835 const int notify_subdirs, const __u16 netfid,
3836 __u32 filter, const struct nls_table *nls_codepage)
3839 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3840 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3843 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3844 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3849 pSMB->TotalParameterCount = 0 ;
3850 pSMB->TotalDataCount = 0;
3851 pSMB->MaxParameterCount = cpu_to_le32(2);
3852 /* BB find exact data count max from sess structure BB */
3853 pSMB->MaxDataCount = 0; /* same in little endian or be */
3854 pSMB->MaxSetupCount = 4;
3856 pSMB->ParameterOffset = 0;
3857 pSMB->DataCount = 0;
3858 pSMB->DataOffset = 0;
3859 pSMB->SetupCount = 4; /* single byte does not need le conversion */
3860 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
3861 pSMB->ParameterCount = pSMB->TotalParameterCount;
3863 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
3864 pSMB->Reserved2 = 0;
3865 pSMB->CompletionFilter = cpu_to_le32(filter);
3866 pSMB->Fid = netfid; /* file handle always le */
3867 pSMB->ByteCount = 0;
3869 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3870 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3872 cFYI(1, ("Error in Notify = %d", rc));
3874 cifs_buf_release(pSMB);
3877 #ifdef CONFIG_CIFS_XATTR
3879 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3880 const unsigned char *searchName,
3881 char * EAData, size_t buf_size,
3882 const struct nls_table *nls_codepage, int remap)
3884 /* BB assumes one setup word */
3885 TRANSACTION2_QPI_REQ *pSMB = NULL;
3886 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3890 struct fea * temp_fea;
3892 __u16 params, byte_count;
3894 cFYI(1, ("In Query All EAs path %s", searchName));
3896 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3901 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3903 cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName,
3904 PATH_MAX, nls_codepage, remap);
3905 name_len++; /* trailing null */
3907 } else { /* BB improve the check for buffer overruns BB */
3908 name_len = strnlen(searchName, PATH_MAX);
3909 name_len++; /* trailing null */
3910 strncpy(pSMB->FileName, searchName, name_len);
3913 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3914 pSMB->TotalDataCount = 0;
3915 pSMB->MaxParameterCount = cpu_to_le16(2);
3916 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3917 pSMB->MaxSetupCount = 0;
3921 pSMB->Reserved2 = 0;
3922 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3923 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3924 pSMB->DataCount = 0;
3925 pSMB->DataOffset = 0;
3926 pSMB->SetupCount = 1;
3927 pSMB->Reserved3 = 0;
3928 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3929 byte_count = params + 1 /* pad */ ;
3930 pSMB->TotalParameterCount = cpu_to_le16(params);
3931 pSMB->ParameterCount = pSMB->TotalParameterCount;
3932 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3933 pSMB->Reserved4 = 0;
3934 pSMB->hdr.smb_buf_length += byte_count;
3935 pSMB->ByteCount = cpu_to_le16(byte_count);
3937 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3938 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3940 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
3941 } else { /* decode response */
3942 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3944 /* BB also check enough total bytes returned */
3945 /* BB we need to improve the validity checking
3946 of these trans2 responses */
3947 if (rc || (pSMBr->ByteCount < 4))
3948 rc = -EIO; /* bad smb */
3949 /* else if (pFindData){
3950 memcpy((char *) pFindData,
3951 (char *) &pSMBr->hdr.Protocol +
3954 /* check that length of list is not more than bcc */
3955 /* check that each entry does not go beyond length
3957 /* check that each element of each entry does not
3958 go beyond end of list */
3959 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3960 struct fealist * ea_response_data;
3962 /* validate_trans2_offsets() */
3963 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3964 ea_response_data = (struct fealist *)
3965 (((char *) &pSMBr->hdr.Protocol) +
3967 name_len = le32_to_cpu(ea_response_data->list_len);
3968 cFYI(1,("ea length %d", name_len));
3970 /* returned EA size zeroed at top of function */
3971 cFYI(1,("empty EA list returned from server"));
3973 /* account for ea list len */
3975 temp_fea = ea_response_data->list;
3976 temp_ptr = (char *)temp_fea;
3977 while(name_len > 0) {
3981 rc += temp_fea->name_len;
3982 /* account for prefix user. and trailing null */
3984 if(rc<(int)buf_size) {
3985 memcpy(EAData,"user.",5);
3987 memcpy(EAData,temp_ptr,temp_fea->name_len);
3988 EAData+=temp_fea->name_len;
3989 /* null terminate name */
3991 EAData = EAData + 1;
3992 } else if(buf_size == 0) {
3993 /* skip copy - calc size only */
3995 /* stop before overrun buffer */
3999 name_len -= temp_fea->name_len;
4000 temp_ptr += temp_fea->name_len;
4001 /* account for trailing null */
4004 value_len = le16_to_cpu(temp_fea->value_len);
4005 name_len -= value_len;
4006 temp_ptr += value_len;
4007 /* BB check that temp_ptr is still within smb BB*/
4008 /* no trailing null to account for in value len */
4009 /* go on to next EA */
4010 temp_fea = (struct fea *)temp_ptr;
4016 cifs_buf_release(pSMB);
4023 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4024 const unsigned char * searchName,const unsigned char * ea_name,
4025 unsigned char * ea_value, size_t buf_size,
4026 const struct nls_table *nls_codepage, int remap)
4028 TRANSACTION2_QPI_REQ *pSMB = NULL;
4029 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4033 struct fea * temp_fea;
4035 __u16 params, byte_count;
4037 cFYI(1, ("In Query EA path %s", searchName));
4039 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4044 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4046 cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
4047 PATH_MAX, nls_codepage, remap);
4048 name_len++; /* trailing null */
4050 } else { /* BB improve the check for buffer overruns BB */
4051 name_len = strnlen(searchName, PATH_MAX);
4052 name_len++; /* trailing null */
4053 strncpy(pSMB->FileName, searchName, name_len);
4056 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4057 pSMB->TotalDataCount = 0;
4058 pSMB->MaxParameterCount = cpu_to_le16(2);
4059 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4060 pSMB->MaxSetupCount = 0;
4064 pSMB->Reserved2 = 0;
4065 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4066 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4067 pSMB->DataCount = 0;
4068 pSMB->DataOffset = 0;
4069 pSMB->SetupCount = 1;
4070 pSMB->Reserved3 = 0;
4071 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4072 byte_count = params + 1 /* pad */ ;
4073 pSMB->TotalParameterCount = cpu_to_le16(params);
4074 pSMB->ParameterCount = pSMB->TotalParameterCount;
4075 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4076 pSMB->Reserved4 = 0;
4077 pSMB->hdr.smb_buf_length += byte_count;
4078 pSMB->ByteCount = cpu_to_le16(byte_count);
4080 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4081 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4083 cFYI(1, ("Send error in Query EA = %d", rc));
4084 } else { /* decode response */
4085 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4087 /* BB also check enough total bytes returned */
4088 /* BB we need to improve the validity checking
4089 of these trans2 responses */
4090 if (rc || (pSMBr->ByteCount < 4))
4091 rc = -EIO; /* bad smb */
4092 /* else if (pFindData){
4093 memcpy((char *) pFindData,
4094 (char *) &pSMBr->hdr.Protocol +
4097 /* check that length of list is not more than bcc */
4098 /* check that each entry does not go beyond length
4100 /* check that each element of each entry does not
4101 go beyond end of list */
4102 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4103 struct fealist * ea_response_data;
4105 /* validate_trans2_offsets() */
4106 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4107 ea_response_data = (struct fealist *)
4108 (((char *) &pSMBr->hdr.Protocol) +
4110 name_len = le32_to_cpu(ea_response_data->list_len);
4111 cFYI(1,("ea length %d", name_len));
4113 /* returned EA size zeroed at top of function */
4114 cFYI(1,("empty EA list returned from server"));
4116 /* account for ea list len */
4118 temp_fea = ea_response_data->list;
4119 temp_ptr = (char *)temp_fea;
4120 /* loop through checking if we have a matching
4121 name and then return the associated value */
4122 while(name_len > 0) {
4126 value_len = le16_to_cpu(temp_fea->value_len);
4127 /* BB validate that value_len falls within SMB,
4128 even though maximum for name_len is 255 */
4129 if(memcmp(temp_fea->name,ea_name,
4130 temp_fea->name_len) == 0) {
4133 /* account for prefix user. and trailing null */
4134 if(rc<=(int)buf_size) {
4136 temp_fea->name+temp_fea->name_len+1,
4138 /* ea values, unlike ea names,
4139 are not null terminated */
4140 } else if(buf_size == 0) {
4141 /* skip copy - calc size only */
4143 /* stop before overrun buffer */
4148 name_len -= temp_fea->name_len;
4149 temp_ptr += temp_fea->name_len;
4150 /* account for trailing null */
4153 name_len -= value_len;
4154 temp_ptr += value_len;
4155 /* no trailing null to account for in value len */
4156 /* go on to next EA */
4157 temp_fea = (struct fea *)temp_ptr;
4163 cifs_buf_release(pSMB);
4171 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4172 const char * ea_name, const void * ea_value,
4173 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4176 struct smb_com_transaction2_spi_req *pSMB = NULL;
4177 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4178 struct fealist *parm_data;
4181 int bytes_returned = 0;
4182 __u16 params, param_offset, byte_count, offset, count;
4184 cFYI(1, ("In SetEA"));
4186 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4191 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4193 cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
4194 PATH_MAX, nls_codepage, remap);
4195 name_len++; /* trailing null */
4197 } else { /* BB improve the check for buffer overruns BB */
4198 name_len = strnlen(fileName, PATH_MAX);
4199 name_len++; /* trailing null */
4200 strncpy(pSMB->FileName, fileName, name_len);
4203 params = 6 + name_len;
4205 /* done calculating parms using name_len of file name,
4206 now use name_len to calculate length of ea name
4207 we are going to create in the inode xattrs */
4211 name_len = strnlen(ea_name,255);
4213 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4214 pSMB->MaxParameterCount = cpu_to_le16(2);
4215 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4216 pSMB->MaxSetupCount = 0;
4220 pSMB->Reserved2 = 0;
4221 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4222 InformationLevel) - 4;
4223 offset = param_offset + params;
4224 pSMB->InformationLevel =
4225 cpu_to_le16(SMB_SET_FILE_EA);
4228 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4230 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4231 pSMB->DataOffset = cpu_to_le16(offset);
4232 pSMB->SetupCount = 1;
4233 pSMB->Reserved3 = 0;
4234 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4235 byte_count = 3 /* pad */ + params + count;
4236 pSMB->DataCount = cpu_to_le16(count);
4237 parm_data->list_len = cpu_to_le32(count);
4238 parm_data->list[0].EA_flags = 0;
4239 /* we checked above that name len is less than 255 */
4240 parm_data->list[0].name_len = (__u8)name_len;;
4241 /* EA names are always ASCII */
4243 strncpy(parm_data->list[0].name,ea_name,name_len);
4244 parm_data->list[0].name[name_len] = 0;
4245 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4246 /* caller ensures that ea_value_len is less than 64K but
4247 we need to ensure that it fits within the smb */
4249 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4250 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4252 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4254 pSMB->TotalDataCount = pSMB->DataCount;
4255 pSMB->ParameterCount = cpu_to_le16(params);
4256 pSMB->TotalParameterCount = pSMB->ParameterCount;
4257 pSMB->Reserved4 = 0;
4258 pSMB->hdr.smb_buf_length += byte_count;
4259 pSMB->ByteCount = cpu_to_le16(byte_count);
4260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4261 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4263 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4266 cifs_buf_release(pSMB);