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 to this tcon */
81 /* If the return code is zero, this function must fill in request_buf pointer */
83 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
84 void **request_buf /* returned */)
88 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
89 check for tcp and smb session status done differently
90 for those three - in the calling routine */
92 if((tcon->ses) && (tcon->ses->server)){
93 struct nls_table *nls_codepage;
94 /* Give Demultiplex thread up to 10 seconds to
95 reconnect, should be greater than cifs socket
96 timeout which is 7 seconds */
97 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
98 wait_event_interruptible_timeout(tcon->ses->server->response_q,
99 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
100 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
101 /* on "soft" mounts we wait once */
102 if((tcon->retry == FALSE) ||
103 (tcon->ses->status == CifsExiting)) {
104 cFYI(1,("gave up waiting on reconnect in smb_init"));
106 } /* else "hard" mount - keep retrying until
107 process is killed or server comes back up */
108 } else /* TCP session is reestablished now */
113 nls_codepage = load_nls_default();
114 /* need to prevent multiple threads trying to
115 simultaneously reconnect the same SMB session */
116 down(&tcon->ses->sesSem);
117 if(tcon->ses->status == CifsNeedReconnect)
118 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
119 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
120 mark_open_files_invalid(tcon);
121 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
123 up(&tcon->ses->sesSem);
125 atomic_inc(&tconInfoReconnectCount);
127 cFYI(1, ("reconnect tcon rc = %d", rc));
128 /* Removed call to reopen open files here -
129 it is safer (and faster) to reopen files
130 one at a time as needed in read and write */
132 /* Check if handle based operation so we
133 know whether we can continue or not without
134 returning to caller to reset file handle */
135 switch(smb_command) {
136 case SMB_COM_READ_ANDX:
137 case SMB_COM_WRITE_ANDX:
139 case SMB_COM_FIND_CLOSE2:
140 case SMB_COM_LOCKING_ANDX: {
141 unload_nls(nls_codepage);
146 up(&tcon->ses->sesSem);
148 unload_nls(nls_codepage);
157 *request_buf = cifs_small_buf_get();
158 if (*request_buf == NULL) {
159 /* BB should we add a retry in here if not a writepage? */
163 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
165 #ifdef CONFIG_CIFS_STATS
167 atomic_inc(&tcon->num_smbs_sent);
169 #endif /* CONFIG_CIFS_STATS */
173 /* If the return code is zero, this function must fill in request_buf pointer */
175 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
176 void **request_buf /* returned */ ,
177 void **response_buf /* returned */ )
181 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
182 check for tcp and smb session status done differently
183 for those three - in the calling routine */
185 if((tcon->ses) && (tcon->ses->server)){
186 struct nls_table *nls_codepage;
187 /* Give Demultiplex thread up to 10 seconds to
188 reconnect, should be greater than cifs socket
189 timeout which is 7 seconds */
190 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
191 wait_event_interruptible_timeout(tcon->ses->server->response_q,
192 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
193 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
194 /* on "soft" mounts we wait once */
195 if((tcon->retry == FALSE) ||
196 (tcon->ses->status == CifsExiting)) {
197 cFYI(1,("gave up waiting on reconnect in smb_init"));
199 } /* else "hard" mount - keep retrying until
200 process is killed or server comes back up */
201 } else /* TCP session is reestablished now */
206 nls_codepage = load_nls_default();
207 /* need to prevent multiple threads trying to
208 simultaneously reconnect the same SMB session */
209 down(&tcon->ses->sesSem);
210 if(tcon->ses->status == CifsNeedReconnect)
211 rc = cifs_setup_session(0, tcon->ses, nls_codepage);
212 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
213 mark_open_files_invalid(tcon);
214 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon,
216 up(&tcon->ses->sesSem);
218 atomic_inc(&tconInfoReconnectCount);
220 cFYI(1, ("reconnect tcon rc = %d", rc));
221 /* Removed call to reopen open files here -
222 it is safer (and faster) to reopen files
223 one at a time as needed in read and write */
225 /* Check if handle based operation so we
226 know whether we can continue or not without
227 returning to caller to reset file handle */
228 switch(smb_command) {
229 case SMB_COM_READ_ANDX:
230 case SMB_COM_WRITE_ANDX:
232 case SMB_COM_FIND_CLOSE2:
233 case SMB_COM_LOCKING_ANDX: {
234 unload_nls(nls_codepage);
239 up(&tcon->ses->sesSem);
241 unload_nls(nls_codepage);
250 *request_buf = cifs_buf_get();
251 if (*request_buf == NULL) {
252 /* BB should we add a retry in here if not a writepage? */
255 /* Although the original thought was we needed the response buf for */
256 /* potential retries of smb operations it turns out we can determine */
257 /* from the mid flags when the request buffer can be resent without */
258 /* having to use a second distinct buffer for the response */
259 *response_buf = *request_buf;
261 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
264 #ifdef CONFIG_CIFS_STATS
266 atomic_inc(&tcon->num_smbs_sent);
268 #endif /* CONFIG_CIFS_STATS */
272 static int validate_t2(struct smb_t2_rsp * pSMB)
278 /* check for plausible wct, bcc and t2 data and parm sizes */
279 /* check for parm and data offset going beyond end of smb */
280 if(pSMB->hdr.WordCount >= 10) {
281 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
282 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
283 /* check that bcc is at least as big as parms + data */
284 /* check that bcc is less than negotiated smb buffer */
285 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
286 if(total_size < 512) {
287 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
288 /* BCC le converted in SendReceive */
289 pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) +
291 if((total_size <= (*(u16 *)pBCC)) &&
293 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
300 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
301 sizeof(struct smb_t2_rsp) + 16);
305 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
308 NEGOTIATE_RSP *pSMBr;
311 struct TCP_Server_Info * server;
315 server = ses->server;
320 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
321 (void **) &pSMB, (void **) &pSMBr);
325 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
326 if (extended_security)
327 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
329 count = strlen(protocols[0].name) + 1;
330 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
331 /* null guaranteed to be at end of source and target buffers anyway */
333 pSMB->hdr.smb_buf_length += count;
334 pSMB->ByteCount = cpu_to_le16(count);
336 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
337 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
339 server->secMode = pSMBr->SecurityMode;
340 server->secType = NTLM; /* BB override default for NTLMv2 or krb*/
341 /* one byte - no need to convert this or EncryptionKeyLen from le,*/
342 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
343 /* probably no need to store and check maxvcs */
345 min(le32_to_cpu(pSMBr->MaxBufferSize),
346 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
347 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
348 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
349 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
350 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
351 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
352 /* BB with UTC do we ever need to be using srvr timezone? */
353 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
354 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
355 CIFS_CRYPTO_KEY_SIZE);
356 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
357 && (pSMBr->EncryptionKeyLength == 0)) {
358 /* decode security blob */
362 /* BB might be helpful to save off the domain of server here */
364 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
365 (server->capabilities & CAP_EXTENDED_SECURITY)) {
366 count = pSMBr->ByteCount;
369 else if (count == 16) {
370 server->secType = RawNTLMSSP;
371 if (server->socketUseCount.counter > 1) {
373 (server->server_GUID,
374 pSMBr->u.extended_response.
377 ("UID of server does not match previous connection to same ip address"));
385 memcpy(server->server_GUID,
386 pSMBr->u.extended_response.
389 rc = decode_negTokenInit(pSMBr->u.
395 /* BB Need to fill struct for sessetup here */
402 server->capabilities &= ~CAP_EXTENDED_SECURITY;
403 if(sign_CIFS_PDUs == FALSE) {
404 if(server->secMode & SECMODE_SIGN_REQUIRED)
406 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
407 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
408 } else if(sign_CIFS_PDUs == 1) {
409 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
410 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
415 cifs_buf_release(pSMB);
420 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
422 struct smb_hdr *smb_buffer;
423 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
427 cFYI(1, ("In tree disconnect"));
429 * If last user of the connection and
430 * connection alive - disconnect it
431 * If this is the last connection on the server session disconnect it
432 * (and inside session disconnect we should check if tcp socket needs
433 * to be freed and kernel thread woken up).
436 down(&tcon->tconSem);
440 atomic_dec(&tcon->useCount);
441 if (atomic_read(&tcon->useCount) > 0) {
446 /* No need to return error on this operation if tid invalidated and
447 closed on server already e.g. due to tcp session crashing */
448 if(tcon->tidStatus == CifsNeedReconnect) {
453 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
457 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer);
462 smb_buffer_response = smb_buffer; /* BB removeme BB */
464 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
467 cFYI(1, (" Tree disconnect failed %d", rc));
470 cifs_small_buf_release(smb_buffer);
473 /* No need to return error on this operation if tid invalidated and
474 closed on server already e.g. due to tcp session crashing */
482 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
484 struct smb_hdr *smb_buffer_response;
485 LOGOFF_ANDX_REQ *pSMB;
489 cFYI(1, ("In SMBLogoff for session disconnect"));
495 atomic_dec(&ses->inUse);
496 if (atomic_read(&ses->inUse) > 0) {
500 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
506 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
509 if(ses->server->secMode &
510 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
511 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
514 pSMB->hdr.Uid = ses->Suid;
516 pSMB->AndXCommand = 0xFF;
517 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
518 smb_buffer_response, &length, 0);
520 atomic_dec(&ses->server->socketUseCount);
521 if (atomic_read(&ses->server->socketUseCount) == 0) {
522 spin_lock(&GlobalMid_Lock);
523 ses->server->tcpStatus = CifsExiting;
524 spin_unlock(&GlobalMid_Lock);
529 cifs_small_buf_release(pSMB);
532 /* if session dead then we do not need to do ulogoff,
533 since server closed smb session, no sense reporting
541 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon,
542 const char *fileName, const struct nls_table *nls_codepage)
544 DELETE_FILE_REQ *pSMB = NULL;
545 DELETE_FILE_RSP *pSMBr = NULL;
551 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
556 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
558 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX
559 /* find define for this maxpathcomponent */
561 name_len++; /* trailing null */
563 } else { /* BB improve the check for buffer overruns BB */
564 name_len = strnlen(fileName, PATH_MAX);
565 name_len++; /* trailing null */
566 strncpy(pSMB->fileName, fileName, name_len);
568 pSMB->SearchAttributes =
569 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
570 pSMB->BufferFormat = 0x04;
571 pSMB->hdr.smb_buf_length += name_len + 1;
572 pSMB->ByteCount = cpu_to_le16(name_len + 1);
573 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
574 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
576 cFYI(1, ("Error in RMFile = %d", rc));
578 #ifdef CONFIG_CIFS_STATS
580 atomic_inc(&tcon->num_deletes);
584 cifs_buf_release(pSMB);
592 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon,
593 const char *dirName, const struct nls_table *nls_codepage)
595 DELETE_DIRECTORY_REQ *pSMB = NULL;
596 DELETE_DIRECTORY_RSP *pSMBr = NULL;
601 cFYI(1, ("In CIFSSMBRmDir"));
603 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
608 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
609 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX
610 /* find define for this maxpathcomponent */
612 name_len++; /* trailing null */
614 } else { /* BB improve the check for buffer overruns BB */
615 name_len = strnlen(dirName, PATH_MAX);
616 name_len++; /* trailing null */
617 strncpy(pSMB->DirName, dirName, name_len);
620 pSMB->BufferFormat = 0x04;
621 pSMB->hdr.smb_buf_length += name_len + 1;
622 pSMB->ByteCount = cpu_to_le16(name_len + 1);
623 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
624 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
626 cFYI(1, ("Error in RMDir = %d", rc));
628 #ifdef CONFIG_CIFS_STATS
630 atomic_inc(&tcon->num_rmdirs);
634 cifs_buf_release(pSMB);
641 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
642 const char *name, const struct nls_table *nls_codepage)
645 CREATE_DIRECTORY_REQ *pSMB = NULL;
646 CREATE_DIRECTORY_RSP *pSMBr = NULL;
650 cFYI(1, ("In CIFSSMBMkDir"));
652 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
657 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
658 name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX
659 /* find define for this maxpathcomponent */
661 name_len++; /* trailing null */
663 } else { /* BB improve the check for buffer overruns BB */
664 name_len = strnlen(name, PATH_MAX);
665 name_len++; /* trailing null */
666 strncpy(pSMB->DirName, name, name_len);
669 pSMB->BufferFormat = 0x04;
670 pSMB->hdr.smb_buf_length += name_len + 1;
671 pSMB->ByteCount = cpu_to_le16(name_len + 1);
672 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
673 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
675 cFYI(1, ("Error in Mkdir = %d", rc));
677 #ifdef CONFIG_CIFS_STATS
679 atomic_inc(&tcon->num_mkdirs);
682 cifs_buf_release(pSMB);
689 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
690 const char *fileName, const int openDisposition,
691 const int access_flags, const int create_options, __u16 * netfid,
692 int *pOplock, FILE_ALL_INFO * pfile_info,
693 const struct nls_table *nls_codepage)
696 OPEN_REQ *pSMB = NULL;
697 OPEN_RSP *pSMBr = NULL;
703 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
708 pSMB->AndXCommand = 0xFF; /* none */
710 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
711 count = 1; /* account for one byte pad to word boundary */
713 cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1),
715 /* find define for this maxpathcomponent */
717 name_len++; /* trailing null */
719 pSMB->NameLength = cpu_to_le16(name_len);
720 } else { /* BB improve the check for buffer overruns BB */
721 count = 0; /* no pad */
722 name_len = strnlen(fileName, PATH_MAX);
723 name_len++; /* trailing null */
724 pSMB->NameLength = cpu_to_le16(name_len);
725 strncpy(pSMB->fileName, fileName, name_len);
727 if (*pOplock & REQ_OPLOCK)
728 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
729 else if (*pOplock & REQ_BATCHOPLOCK) {
730 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
732 pSMB->DesiredAccess = cpu_to_le32(access_flags);
733 pSMB->AllocationSize = 0;
734 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
735 /* XP does not handle ATTR_POSIX_SEMANTICS */
736 /* but it helps speed up case sensitive checks for other
737 servers such as Samba */
738 if (tcon->ses->capabilities & CAP_UNIX)
739 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
741 /* if ((omode & S_IWUGO) == 0)
742 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
743 /* Above line causes problems due to vfs splitting create into two
744 pieces - need to set mode after file created not while it is
746 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
747 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
748 pSMB->CreateOptions = cpu_to_le32(create_options);
749 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/
750 pSMB->SecurityFlags =
751 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
754 pSMB->hdr.smb_buf_length += count;
756 pSMB->ByteCount = cpu_to_le16(count);
757 /* long_op set to 1 to allow for oplock break timeouts */
758 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
759 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
761 cFYI(1, ("Error in Open = %d", rc));
763 *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */
764 *netfid = pSMBr->Fid; /* cifs fid stays in le */
765 /* Let caller know file was created so we can set the mode. */
766 /* Do we care about the CreateAction in any other cases? */
767 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
768 *pOplock |= CIFS_CREATE_ACTION;
770 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
771 36 /* CreationTime to Attributes */);
772 /* the file_info buf is endian converted by caller */
773 pfile_info->AllocationSize = pSMBr->AllocationSize;
774 pfile_info->EndOfFile = pSMBr->EndOfFile;
775 pfile_info->NumberOfLinks = cpu_to_le32(1);
778 #ifdef CONFIG_CIFS_STATS
779 atomic_inc(&tcon->num_opens);
782 cifs_buf_release(pSMB);
788 /* If no buffer passed in, then caller wants to do the copy
789 as in the case of readpages so the SMB buffer must be
790 freed by the caller */
793 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
794 const int netfid, const unsigned int count,
795 const __u64 lseek, unsigned int *nbytes, char **buf)
798 READ_REQ *pSMB = NULL;
799 READ_RSP *pSMBr = NULL;
800 char *pReadData = NULL;
803 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
806 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
811 /* tcon and ses pointer are checked in smb_init */
812 if (tcon->ses->server == NULL)
813 return -ECONNABORTED;
815 pSMB->AndXCommand = 0xFF; /* none */
817 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
818 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
820 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
821 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
822 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
824 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
825 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
827 cERROR(1, ("Send error in read = %d", rc));
829 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
830 data_length = data_length << 16;
831 data_length += le16_to_cpu(pSMBr->DataLength);
832 *nbytes = data_length;
834 /*check that DataLength would not go beyond end of SMB */
835 if ((data_length > CIFSMaxBufSize)
836 || (data_length > count)) {
837 cFYI(1,("bad length %d for count %d",data_length,count));
842 (char *) (&pSMBr->hdr.Protocol) +
843 le16_to_cpu(pSMBr->DataOffset);
844 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
845 cERROR(1,("Faulting on read rc = %d",rc));
847 }*/ /* can not use copy_to_user when using page cache*/
849 memcpy(*buf,pReadData,data_length);
853 cifs_buf_release(pSMB);
857 /* Note: On -EAGAIN error only caller can retry on handle based calls
858 since file handle passed in no longer valid */
863 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
864 const int netfid, const unsigned int count,
865 const __u64 offset, unsigned int *nbytes, const char *buf,
866 const char __user * ubuf, const int long_op)
869 WRITE_REQ *pSMB = NULL;
870 WRITE_RSP *pSMBr = NULL;
875 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
876 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
880 /* tcon and ses pointer are checked in smb_init */
881 if (tcon->ses->server == NULL)
882 return -ECONNABORTED;
884 pSMB->AndXCommand = 0xFF; /* none */
886 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
887 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
888 pSMB->Reserved = 0xFFFFFFFF;
892 /* Can increase buffer size if buffer is big enough in some cases - ie we
893 can send more if LARGE_WRITE_X capability returned by the server and if
894 our buffer is big enough or if we convert to iovecs on socket writes
895 and eliminate the copy to the CIFS buffer */
896 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
897 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
899 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
903 if (bytes_sent > count)
906 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
908 memcpy(pSMB->Data,buf,bytes_sent);
910 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
911 cifs_buf_release(pSMB);
916 cifs_buf_release(pSMB);
920 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
921 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
922 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
923 pSMB->hdr.smb_buf_length += bytes_sent+1;
924 pSMB->ByteCount = cpu_to_le16(byte_count);
926 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
927 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
929 cFYI(1, ("Send error in write = %d", rc));
932 *nbytes = le16_to_cpu(pSMBr->CountHigh);
933 *nbytes = (*nbytes) << 16;
934 *nbytes += le16_to_cpu(pSMBr->Count);
937 cifs_buf_release(pSMB);
939 /* Note: On -EAGAIN error only caller can retry on handle based calls
940 since file handle passed in no longer valid */
945 #ifdef CONFIG_CIFS_EXPERIMENTAL
946 int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
947 const int netfid, const unsigned int count,
948 const __u64 offset, unsigned int *nbytes, const char __user *buf,
952 WRITE_REQ *pSMB = NULL;
953 WRITE_RSP *pSMBr = NULL;
954 /*int bytes_returned;*/
958 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
963 pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
965 /* tcon and ses pointer are checked in smb_init */
966 if (tcon->ses->server == NULL)
967 return -ECONNABORTED;
969 pSMB->AndXCommand = 0xFF; /* none */
971 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
972 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
973 pSMB->Reserved = 0xFFFFFFFF;
976 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
977 if (bytes_sent > count)
979 pSMB->DataLengthHigh = 0;
981 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
983 byte_count = bytes_sent + 1 /* pad */ ;
984 pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
985 pSMB->DataLengthHigh = 0;
986 pSMB->hdr.smb_buf_length += byte_count;
987 pSMB->ByteCount = cpu_to_le16(byte_count);
989 /* rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
990 (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */ /* BB fixme BB */
992 cFYI(1, ("Send error in write2 (large write) = %d", rc));
995 *nbytes = le16_to_cpu(pSMBr->Count);
997 cifs_small_buf_release(pSMB);
999 /* Note: On -EAGAIN error only caller can retry on handle based calls
1000 since file handle passed in no longer valid */
1004 #endif /* CIFS_EXPERIMENTAL */
1007 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1008 const __u16 smb_file_id, const __u64 len,
1009 const __u64 offset, const __u32 numUnlock,
1010 const __u32 numLock, const __u8 lockType, const int waitFlag)
1013 LOCK_REQ *pSMB = NULL;
1014 LOCK_RSP *pSMBr = NULL;
1019 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1020 rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB,
1025 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1026 timeout = -1; /* no response expected */
1028 } else if (waitFlag == TRUE) {
1029 timeout = 3; /* blocking operation, no timeout */
1030 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1035 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1036 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1037 pSMB->LockType = lockType;
1038 pSMB->AndXCommand = 0xFF; /* none */
1039 pSMB->Fid = smb_file_id; /* netfid stays le */
1041 if((numLock != 0) || (numUnlock != 0)) {
1042 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1043 /* BB where to store pid high? */
1044 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1045 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1046 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1047 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1048 count = sizeof(LOCKING_ANDX_RANGE);
1053 pSMB->hdr.smb_buf_length += count;
1054 pSMB->ByteCount = cpu_to_le16(count);
1056 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1057 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1060 cFYI(1, ("Send error in Lock = %d", rc));
1062 cifs_buf_release(pSMB);
1064 /* Note: On -EAGAIN error only caller can retry on handle based calls
1065 since file handle passed in no longer valid */
1070 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1073 CLOSE_REQ *pSMB = NULL;
1074 CLOSE_RSP *pSMBr = NULL;
1076 cFYI(1, ("In CIFSSMBClose"));
1078 /* do not retry on dead session on close */
1079 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1085 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1087 pSMB->FileID = (__u16) smb_file_id;
1088 pSMB->LastWriteTime = 0;
1089 pSMB->ByteCount = 0;
1090 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1091 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1094 /* EINTR is expected when user ctl-c to kill app */
1095 cERROR(1, ("Send error in Close = %d", rc));
1099 cifs_small_buf_release(pSMB);
1101 /* Since session is dead, file will be closed on server already */
1109 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1110 const char *fromName, const char *toName,
1111 const struct nls_table *nls_codepage)
1114 RENAME_REQ *pSMB = NULL;
1115 RENAME_RSP *pSMBr = NULL;
1117 int name_len, name_len2;
1120 cFYI(1, ("In CIFSSMBRename"));
1122 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1127 pSMB->BufferFormat = 0x04;
1128 pSMB->SearchAttributes =
1129 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1132 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1134 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
1135 /* find define for this maxpathcomponent */
1137 name_len++; /* trailing null */
1139 pSMB->OldFileName[name_len] = 0x04; /* pad */
1140 /* protocol requires ASCII signature byte on Unicode string */
1141 pSMB->OldFileName[name_len + 1] = 0x00;
1143 cifs_strtoUCS((wchar_t *) & pSMB->
1144 OldFileName[name_len + 2], toName, PATH_MAX,
1146 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1147 name_len2 *= 2; /* convert to bytes */
1148 } else { /* BB improve the check for buffer overruns BB */
1149 name_len = strnlen(fromName, PATH_MAX);
1150 name_len++; /* trailing null */
1151 strncpy(pSMB->OldFileName, fromName, name_len);
1152 name_len2 = strnlen(toName, PATH_MAX);
1153 name_len2++; /* trailing null */
1154 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1155 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1156 name_len2++; /* trailing null */
1157 name_len2++; /* signature byte */
1160 count = 1 /* 1st signature byte */ + name_len + name_len2;
1161 pSMB->hdr.smb_buf_length += count;
1162 pSMB->ByteCount = cpu_to_le16(count);
1164 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1165 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1167 cFYI(1, ("Send error in rename = %d", rc));
1170 #ifdef CONFIG_CIFS_STATS
1172 atomic_inc(&tcon->num_renames);
1176 cifs_buf_release(pSMB);
1184 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1185 int netfid, char * target_name, const struct nls_table * nls_codepage)
1187 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1188 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1189 struct set_file_rename * rename_info;
1191 char dummy_string[30];
1193 int bytes_returned = 0;
1195 __u16 params, param_offset, offset, count, byte_count;
1197 cFYI(1, ("Rename to File by handle"));
1198 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1204 pSMB->MaxSetupCount = 0;
1208 pSMB->Reserved2 = 0;
1209 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1210 offset = param_offset + params;
1212 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1213 rename_info = (struct set_file_rename *) data_offset;
1214 pSMB->MaxParameterCount = cpu_to_le16(2);
1215 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1216 pSMB->SetupCount = 1;
1217 pSMB->Reserved3 = 0;
1218 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1219 byte_count = 3 /* pad */ + params;
1220 pSMB->ParameterCount = cpu_to_le16(params);
1221 pSMB->TotalParameterCount = pSMB->ParameterCount;
1222 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1223 pSMB->DataOffset = cpu_to_le16(offset);
1224 /* construct random name ".cifs_tmp<inodenum><mid>" */
1225 rename_info->overwrite = cpu_to_le32(1);
1226 rename_info->root_fid = 0;
1227 /* unicode only call */
1228 if(target_name == NULL) {
1229 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1230 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage);
1232 len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage);
1234 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1235 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1236 byte_count += count;
1237 pSMB->DataCount = cpu_to_le16(count);
1238 pSMB->TotalDataCount = pSMB->DataCount;
1240 pSMB->InformationLevel =
1241 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1242 pSMB->Reserved4 = 0;
1243 pSMB->hdr.smb_buf_length += byte_count;
1244 pSMB->ByteCount = cpu_to_le16(byte_count);
1245 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1246 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1248 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1250 #ifdef CONFIG_CIFS_STATS
1252 atomic_inc(&pTcon->num_t2renames);
1255 cifs_buf_release(pSMB);
1257 /* Note: On -EAGAIN error only caller can retry on handle based calls
1258 since file handle passed in no longer valid */
1264 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1265 const __u16 target_tid, const char *toName, const int flags,
1266 const struct nls_table *nls_codepage)
1269 COPY_REQ *pSMB = NULL;
1270 COPY_RSP *pSMBr = NULL;
1272 int name_len, name_len2;
1275 cFYI(1, ("In CIFSSMBCopy"));
1277 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1282 pSMB->BufferFormat = 0x04;
1283 pSMB->Tid2 = target_tid;
1285 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1287 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1288 name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName,
1290 PATH_MAX /* find define for this maxpathcomponent */,
1292 name_len++; /* trailing null */
1294 pSMB->OldFileName[name_len] = 0x04; /* pad */
1295 /* protocol requires ASCII signature byte on Unicode string */
1296 pSMB->OldFileName[name_len + 1] = 0x00;
1297 name_len2 = cifs_strtoUCS((wchar_t *) & pSMB->
1298 OldFileName[name_len + 2], toName, PATH_MAX,
1300 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1301 name_len2 *= 2; /* convert to bytes */
1302 } else { /* BB improve the check for buffer overruns BB */
1303 name_len = strnlen(fromName, PATH_MAX);
1304 name_len++; /* trailing null */
1305 strncpy(pSMB->OldFileName, fromName, name_len);
1306 name_len2 = strnlen(toName, PATH_MAX);
1307 name_len2++; /* trailing null */
1308 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1309 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1310 name_len2++; /* trailing null */
1311 name_len2++; /* signature byte */
1314 count = 1 /* 1st signature byte */ + name_len + name_len2;
1315 pSMB->hdr.smb_buf_length += count;
1316 pSMB->ByteCount = cpu_to_le16(count);
1318 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1319 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1321 cFYI(1, ("Send error in copy = %d with %d files copied",
1322 rc, le16_to_cpu(pSMBr->CopyCount)));
1325 cifs_buf_release(pSMB);
1334 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1335 const char *fromName, const char *toName,
1336 const struct nls_table *nls_codepage)
1338 TRANSACTION2_SPI_REQ *pSMB = NULL;
1339 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1342 int name_len_target;
1344 int bytes_returned = 0;
1345 __u16 params, param_offset, offset, byte_count;
1347 cFYI(1, ("In Symlink Unix style"));
1349 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1354 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1356 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1357 /* find define for this maxpathcomponent */
1359 name_len++; /* trailing null */
1362 } else { /* BB improve the check for buffer overruns BB */
1363 name_len = strnlen(fromName, PATH_MAX);
1364 name_len++; /* trailing null */
1365 strncpy(pSMB->FileName, fromName, name_len);
1367 params = 6 + name_len;
1368 pSMB->MaxSetupCount = 0;
1372 pSMB->Reserved2 = 0;
1373 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1374 InformationLevel) - 4;
1375 offset = param_offset + params;
1377 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1378 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1380 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1381 /* find define for this maxpathcomponent */
1383 name_len_target++; /* trailing null */
1384 name_len_target *= 2;
1385 } else { /* BB improve the check for buffer overruns BB */
1386 name_len_target = strnlen(toName, PATH_MAX);
1387 name_len_target++; /* trailing null */
1388 strncpy(data_offset, toName, name_len_target);
1391 pSMB->MaxParameterCount = cpu_to_le16(2);
1392 /* BB find exact max on data count below from sess */
1393 pSMB->MaxDataCount = cpu_to_le16(1000);
1394 pSMB->SetupCount = 1;
1395 pSMB->Reserved3 = 0;
1396 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1397 byte_count = 3 /* pad */ + params + name_len_target;
1398 pSMB->DataCount = cpu_to_le16(name_len_target);
1399 pSMB->ParameterCount = cpu_to_le16(params);
1400 pSMB->TotalDataCount = pSMB->DataCount;
1401 pSMB->TotalParameterCount = pSMB->ParameterCount;
1402 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1403 pSMB->DataOffset = cpu_to_le16(offset);
1404 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1405 pSMB->Reserved4 = 0;
1406 pSMB->hdr.smb_buf_length += byte_count;
1407 pSMB->ByteCount = cpu_to_le16(byte_count);
1408 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1409 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1412 ("Send error in SetPathInfo (create symlink) = %d",
1417 cifs_buf_release(pSMB);
1420 goto createSymLinkRetry;
1426 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1427 const char *fromName, const char *toName,
1428 const struct nls_table *nls_codepage)
1430 TRANSACTION2_SPI_REQ *pSMB = NULL;
1431 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1434 int name_len_target;
1436 int bytes_returned = 0;
1437 __u16 params, param_offset, offset, byte_count;
1439 cFYI(1, ("In Create Hard link Unix style"));
1440 createHardLinkRetry:
1441 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1446 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1447 name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX
1448 /* find define for this maxpathcomponent */
1450 name_len++; /* trailing null */
1453 } else { /* BB improve the check for buffer overruns BB */
1454 name_len = strnlen(toName, PATH_MAX);
1455 name_len++; /* trailing null */
1456 strncpy(pSMB->FileName, toName, name_len);
1458 params = 6 + name_len;
1459 pSMB->MaxSetupCount = 0;
1463 pSMB->Reserved2 = 0;
1464 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1465 InformationLevel) - 4;
1466 offset = param_offset + params;
1468 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1469 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1471 cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX
1472 /* find define for this maxpathcomponent */
1474 name_len_target++; /* trailing null */
1475 name_len_target *= 2;
1476 } else { /* BB improve the check for buffer overruns BB */
1477 name_len_target = strnlen(fromName, PATH_MAX);
1478 name_len_target++; /* trailing null */
1479 strncpy(data_offset, fromName, name_len_target);
1482 pSMB->MaxParameterCount = cpu_to_le16(2);
1483 /* BB find exact max on data count below from sess*/
1484 pSMB->MaxDataCount = cpu_to_le16(1000);
1485 pSMB->SetupCount = 1;
1486 pSMB->Reserved3 = 0;
1487 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1488 byte_count = 3 /* pad */ + params + name_len_target;
1489 pSMB->ParameterCount = cpu_to_le16(params);
1490 pSMB->TotalParameterCount = pSMB->ParameterCount;
1491 pSMB->DataCount = cpu_to_le16(name_len_target);
1492 pSMB->TotalDataCount = pSMB->DataCount;
1493 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1494 pSMB->DataOffset = cpu_to_le16(offset);
1495 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1496 pSMB->Reserved4 = 0;
1497 pSMB->hdr.smb_buf_length += byte_count;
1498 pSMB->ByteCount = cpu_to_le16(byte_count);
1499 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1500 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1502 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1505 cifs_buf_release(pSMB);
1507 goto createHardLinkRetry;
1513 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1514 const char *fromName, const char *toName,
1515 const struct nls_table *nls_codepage)
1518 NT_RENAME_REQ *pSMB = NULL;
1519 RENAME_RSP *pSMBr = NULL;
1521 int name_len, name_len2;
1524 cFYI(1, ("In CIFSCreateHardLink"));
1525 winCreateHardLinkRetry:
1527 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1532 pSMB->SearchAttributes =
1533 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1535 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1536 pSMB->ClusterCount = 0;
1538 pSMB->BufferFormat = 0x04;
1540 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1542 cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX
1543 /* find define for this maxpathcomponent */
1545 name_len++; /* trailing null */
1547 pSMB->OldFileName[name_len] = 0; /* pad */
1548 pSMB->OldFileName[name_len + 1] = 0x04;
1550 cifs_strtoUCS((wchar_t *) & pSMB->
1551 OldFileName[name_len + 2], toName, PATH_MAX,
1553 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1554 name_len2 *= 2; /* convert to bytes */
1555 } else { /* BB improve the check for buffer overruns BB */
1556 name_len = strnlen(fromName, PATH_MAX);
1557 name_len++; /* trailing null */
1558 strncpy(pSMB->OldFileName, fromName, name_len);
1559 name_len2 = strnlen(toName, PATH_MAX);
1560 name_len2++; /* trailing null */
1561 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1562 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1563 name_len2++; /* trailing null */
1564 name_len2++; /* signature byte */
1567 count = 1 /* string type byte */ + name_len + name_len2;
1568 pSMB->hdr.smb_buf_length += count;
1569 pSMB->ByteCount = cpu_to_le16(count);
1571 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1572 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1574 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1576 cifs_buf_release(pSMB);
1578 goto winCreateHardLinkRetry;
1584 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1585 const unsigned char *searchName,
1586 char *symlinkinfo, const int buflen,
1587 const struct nls_table *nls_codepage)
1589 /* SMB_QUERY_FILE_UNIX_LINK */
1590 TRANSACTION2_QPI_REQ *pSMB = NULL;
1591 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1595 __u16 params, byte_count;
1597 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1600 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1605 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1607 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1608 /* find define for this maxpathcomponent */
1610 name_len++; /* trailing null */
1612 } else { /* BB improve the check for buffer overruns BB */
1613 name_len = strnlen(searchName, PATH_MAX);
1614 name_len++; /* trailing null */
1615 strncpy(pSMB->FileName, searchName, name_len);
1618 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1619 pSMB->TotalDataCount = 0;
1620 pSMB->MaxParameterCount = cpu_to_le16(2);
1621 /* BB find exact max data count below from sess structure BB */
1622 pSMB->MaxDataCount = cpu_to_le16(4000);
1623 pSMB->MaxSetupCount = 0;
1627 pSMB->Reserved2 = 0;
1628 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1629 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1630 pSMB->DataCount = 0;
1631 pSMB->DataOffset = 0;
1632 pSMB->SetupCount = 1;
1633 pSMB->Reserved3 = 0;
1634 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1635 byte_count = params + 1 /* pad */ ;
1636 pSMB->TotalParameterCount = cpu_to_le16(params);
1637 pSMB->ParameterCount = pSMB->TotalParameterCount;
1638 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1639 pSMB->Reserved4 = 0;
1640 pSMB->hdr.smb_buf_length += byte_count;
1641 pSMB->ByteCount = cpu_to_le16(byte_count);
1643 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1644 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1646 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1648 /* decode response */
1650 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1651 if (rc || (pSMBr->ByteCount < 2))
1652 /* BB also check enough total bytes returned */
1653 rc = -EIO; /* bad smb */
1655 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1656 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1658 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1659 name_len = UniStrnlen((wchar_t *) ((char *)
1660 &pSMBr->hdr.Protocol +data_offset),
1661 min_t(const int, buflen,count) / 2);
1662 cifs_strfromUCS_le(symlinkinfo,
1663 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1665 name_len, nls_codepage);
1667 strncpy(symlinkinfo,
1668 (char *) &pSMBr->hdr.Protocol +
1670 min_t(const int, buflen, count));
1672 symlinkinfo[buflen] = 0;
1673 /* just in case so calling code does not go off the end of buffer */
1676 cifs_buf_release(pSMB);
1678 goto querySymLinkRetry;
1683 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1684 const unsigned char *searchName,
1685 char *symlinkinfo, const int buflen,__u16 fid,
1686 const struct nls_table *nls_codepage)
1691 struct smb_com_transaction_ioctl_req * pSMB;
1692 struct smb_com_transaction_ioctl_rsp * pSMBr;
1694 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1695 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1700 pSMB->TotalParameterCount = 0 ;
1701 pSMB->TotalDataCount = 0;
1702 pSMB->MaxParameterCount = cpu_to_le32(2);
1703 /* BB find exact data count max from sess structure BB */
1704 pSMB->MaxDataCount = cpu_to_le32(4000);
1705 pSMB->MaxSetupCount = 4;
1707 pSMB->ParameterOffset = 0;
1708 pSMB->DataCount = 0;
1709 pSMB->DataOffset = 0;
1710 pSMB->SetupCount = 4;
1711 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1712 pSMB->ParameterCount = pSMB->TotalParameterCount;
1713 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1714 pSMB->IsFsctl = 1; /* FSCTL */
1715 pSMB->IsRootFlag = 0;
1716 pSMB->Fid = fid; /* file handle always le */
1717 pSMB->ByteCount = 0;
1719 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1720 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1722 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1723 } else { /* decode response */
1724 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1725 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1726 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1727 /* BB also check enough total bytes returned */
1728 rc = -EIO; /* bad smb */
1730 if(data_count && (data_count < 2048)) {
1731 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1733 struct reparse_data * reparse_buf = (struct reparse_data *)
1734 ((char *)&pSMBr->hdr.Protocol + data_offset);
1735 if((char*)reparse_buf >= end_of_smb) {
1739 if((reparse_buf->LinkNamesBuf +
1740 reparse_buf->TargetNameOffset +
1741 reparse_buf->TargetNameLen) >
1743 cFYI(1,("reparse buf extended beyond SMB"));
1748 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1749 name_len = UniStrnlen((wchar_t *)
1750 (reparse_buf->LinkNamesBuf +
1751 reparse_buf->TargetNameOffset),
1752 min(buflen/2, reparse_buf->TargetNameLen / 2));
1753 cifs_strfromUCS_le(symlinkinfo,
1754 (wchar_t *) (reparse_buf->LinkNamesBuf +
1755 reparse_buf->TargetNameOffset),
1756 name_len, nls_codepage);
1757 } else { /* ASCII names */
1758 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1759 reparse_buf->TargetNameOffset,
1760 min_t(const int, buflen, reparse_buf->TargetNameLen));
1764 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1766 symlinkinfo[buflen] = 0; /* just in case so the caller
1767 does not go off the end of the buffer */
1768 cFYI(1,("readlink result - %s ",symlinkinfo));
1773 cifs_buf_release(pSMB);
1775 /* Note: On -EAGAIN error only caller can retry on handle based calls
1776 since file handle passed in no longer valid */
1781 #ifdef CONFIG_CIFS_POSIX
1783 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1784 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1786 /* u8 cifs fields do not need le conversion */
1787 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1788 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1789 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1790 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1795 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1796 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area)
1801 struct cifs_posix_ace * pACE;
1802 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1803 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1805 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1808 if(acl_type & ACL_TYPE_ACCESS) {
1809 count = le16_to_cpu(cifs_acl->access_entry_count);
1810 pACE = &cifs_acl->ace_array[0];
1811 size = sizeof(struct cifs_posix_acl);
1812 size += sizeof(struct cifs_posix_ace) * count;
1813 /* check if we would go beyond end of SMB */
1814 if(size_of_data_area < size) {
1815 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1818 } else if(acl_type & ACL_TYPE_DEFAULT) {
1819 count = le16_to_cpu(cifs_acl->access_entry_count);
1820 size = sizeof(struct cifs_posix_acl);
1821 size += sizeof(struct cifs_posix_ace) * count;
1822 /* skip past access ACEs to get to default ACEs */
1823 pACE = &cifs_acl->ace_array[count];
1824 count = le16_to_cpu(cifs_acl->default_entry_count);
1825 size += sizeof(struct cifs_posix_ace) * count;
1826 /* check if we would go beyond end of SMB */
1827 if(size_of_data_area < size)
1834 size = posix_acl_xattr_size(count);
1835 if((buflen == 0) || (local_acl == NULL)) {
1836 /* used to query ACL EA size */
1837 } else if(size > buflen) {
1839 } else /* buffer big enough */ {
1840 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1841 for(i = 0;i < count ;i++) {
1842 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1849 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1850 const posix_acl_xattr_entry * local_ace)
1852 __u16 rc = 0; /* 0 = ACL converted ok */
1854 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1855 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1856 /* BB is there a better way to handle the large uid? */
1857 if(local_ace->e_id == -1) {
1858 /* Probably no need to le convert -1 on any arch but can not hurt */
1859 cifs_ace->cifs_uid = cpu_to_le64(-1);
1861 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1862 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1866 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1867 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1871 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1872 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1876 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1879 count = posix_acl_xattr_count((size_t)buflen);
1880 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1881 count,buflen,local_acl->a_version));
1882 if(local_acl->a_version != 2) {
1883 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1886 cifs_acl->version = cpu_to_le16(1);
1887 if(acl_type == ACL_TYPE_ACCESS)
1888 cifs_acl->access_entry_count = count;
1889 else if(acl_type == ACL_TYPE_DEFAULT)
1890 cifs_acl->default_entry_count = count;
1892 cFYI(1,("unknown ACL type %d",acl_type));
1895 for(i=0;i<count;i++) {
1896 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1897 &local_acl->a_entries[i]);
1899 /* ACE not converted */
1904 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1905 rc += sizeof(struct cifs_posix_acl);
1906 /* BB add check to make sure ACL does not overflow SMB */
1912 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1913 const unsigned char *searchName,
1914 char *acl_inf, const int buflen, const int acl_type,
1915 const struct nls_table *nls_codepage)
1917 /* SMB_QUERY_POSIX_ACL */
1918 TRANSACTION2_QPI_REQ *pSMB = NULL;
1919 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1923 __u16 params, byte_count;
1925 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1928 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1933 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1935 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1937 name_len++; /* trailing null */
1939 pSMB->FileName[name_len] = 0;
1940 pSMB->FileName[name_len+1] = 0;
1941 } else { /* BB improve the check for buffer overruns BB */
1942 name_len = strnlen(searchName, PATH_MAX);
1943 name_len++; /* trailing null */
1944 strncpy(pSMB->FileName, searchName, name_len);
1947 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1948 pSMB->TotalDataCount = 0;
1949 pSMB->MaxParameterCount = cpu_to_le16(2);
1950 /* BB find exact max data count below from sess structure BB */
1951 pSMB->MaxDataCount = cpu_to_le16(4000);
1952 pSMB->MaxSetupCount = 0;
1956 pSMB->Reserved2 = 0;
1957 pSMB->ParameterOffset = cpu_to_le16(
1958 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1959 pSMB->DataCount = 0;
1960 pSMB->DataOffset = 0;
1961 pSMB->SetupCount = 1;
1962 pSMB->Reserved3 = 0;
1963 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1964 byte_count = params + 1 /* pad */ ;
1965 pSMB->TotalParameterCount = cpu_to_le16(params);
1966 pSMB->ParameterCount = pSMB->TotalParameterCount;
1967 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
1968 pSMB->Reserved4 = 0;
1969 pSMB->hdr.smb_buf_length += byte_count;
1970 pSMB->ByteCount = cpu_to_le16(byte_count);
1972 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1973 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1975 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
1977 /* decode response */
1979 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1980 if (rc || (pSMBr->ByteCount < 2))
1981 /* BB also check enough total bytes returned */
1982 rc = -EIO; /* bad smb */
1984 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1985 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1986 rc = cifs_copy_posix_acl(acl_inf,
1987 (char *)&pSMBr->hdr.Protocol+data_offset,
1988 buflen,acl_type,count);
1991 cifs_buf_release(pSMB);
1998 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
1999 const unsigned char *fileName,
2000 const char *local_acl, const int buflen, const int acl_type,
2001 const struct nls_table *nls_codepage)
2003 struct smb_com_transaction2_spi_req *pSMB = NULL;
2004 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2008 int bytes_returned = 0;
2009 __u16 params, byte_count, data_count, param_offset, offset;
2011 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2013 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2017 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2019 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
2021 name_len++; /* trailing null */
2023 } else { /* BB improve the check for buffer overruns BB */
2024 name_len = strnlen(fileName, PATH_MAX);
2025 name_len++; /* trailing null */
2026 strncpy(pSMB->FileName, fileName, name_len);
2028 params = 6 + name_len;
2029 pSMB->MaxParameterCount = cpu_to_le16(2);
2030 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2031 pSMB->MaxSetupCount = 0;
2035 pSMB->Reserved2 = 0;
2036 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2037 InformationLevel) - 4;
2038 offset = param_offset + params;
2039 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2040 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2042 /* convert to on the wire format for POSIX ACL */
2043 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2045 if(data_count == 0) {
2047 goto setACLerrorExit;
2049 pSMB->DataOffset = cpu_to_le16(offset);
2050 pSMB->SetupCount = 1;
2051 pSMB->Reserved3 = 0;
2052 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2053 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2054 byte_count = 3 /* pad */ + params + data_count;
2055 pSMB->DataCount = cpu_to_le16(data_count);
2056 pSMB->TotalDataCount = pSMB->DataCount;
2057 pSMB->ParameterCount = cpu_to_le16(params);
2058 pSMB->TotalParameterCount = pSMB->ParameterCount;
2059 pSMB->Reserved4 = 0;
2060 pSMB->hdr.smb_buf_length += byte_count;
2061 pSMB->ByteCount = cpu_to_le16(byte_count);
2062 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2063 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2065 cFYI(1, ("Set POSIX ACL returned %d", rc));
2069 cifs_buf_release(pSMB);
2075 /* BB fix tabs in this function FIXME BB */
2077 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2078 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2081 struct smb_t2_qfi_req *pSMB = NULL;
2082 struct smb_t2_qfi_rsp *pSMBr = NULL;
2084 __u16 params, byte_count;
2086 cFYI(1,("In GetExtAttr"));
2091 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2096 params = 2 /* level */ +2 /* fid */ + 2 /* rsrvd */;
2097 pSMB->t2.TotalDataCount = 0;
2098 pSMB->t2.MaxParameterCount = cpu_to_le16(2);
2099 /* BB find exact max data count below from sess structure BB */
2100 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2101 pSMB->t2.MaxSetupCount = 0;
2102 pSMB->t2.Reserved = 0;
2104 pSMB->t2.Timeout = 0;
2105 pSMB->t2.Reserved2 = 0;
2106 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(
2107 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2108 pSMB->t2.DataCount = 0;
2109 pSMB->t2.DataOffset = 0;
2110 pSMB->t2.SetupCount = 1;
2111 pSMB->t2.Reserved3 = 0;
2112 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2113 byte_count = params + 3 /* pad */ ;
2114 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2115 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2116 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2120 pSMB->hdr.smb_buf_length += byte_count;
2121 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2123 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2124 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2126 cFYI(1, ("error %d in GetExtAttr", rc));
2128 /* decode response */
2129 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2130 if (rc || (pSMBr->ByteCount < 2))
2131 /* BB also check enough total bytes returned */
2132 /* If rc should we check for EOPNOSUPP and
2133 disable the srvino flag? or in caller? */
2134 rc = -EIO; /* bad smb */
2136 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2137 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2138 struct file_chattr_info * pfinfo;
2139 /* BB Do we need a cast or hash here ? */
2141 cFYI(1, ("Illegal size ret in GetExtAttr"));
2145 pfinfo = (struct file_chattr_info *)
2146 (data_offset + (char *) &pSMBr->hdr.Protocol);
2147 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2148 *pMask = le64_to_cpu(pfinfo->mask);
2152 cifs_buf_release(pSMB);
2154 goto GetExtAttrRetry;
2159 #endif /* CONFIG_POSIX */
2162 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2163 const unsigned char *searchName,
2164 FILE_ALL_INFO * pFindData,
2165 const struct nls_table *nls_codepage)
2167 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2168 TRANSACTION2_QPI_REQ *pSMB = NULL;
2169 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2173 __u16 params, byte_count;
2175 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2177 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2182 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2184 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2185 /* find define for this maxpathcomponent */
2187 name_len++; /* trailing null */
2189 } else { /* BB improve the check for buffer overruns BB */
2190 name_len = strnlen(searchName, PATH_MAX);
2191 name_len++; /* trailing null */
2192 strncpy(pSMB->FileName, searchName, name_len);
2195 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2196 pSMB->TotalDataCount = 0;
2197 pSMB->MaxParameterCount = cpu_to_le16(2);
2198 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2199 pSMB->MaxSetupCount = 0;
2203 pSMB->Reserved2 = 0;
2204 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2205 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2206 pSMB->DataCount = 0;
2207 pSMB->DataOffset = 0;
2208 pSMB->SetupCount = 1;
2209 pSMB->Reserved3 = 0;
2210 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2211 byte_count = params + 1 /* pad */ ;
2212 pSMB->TotalParameterCount = cpu_to_le16(params);
2213 pSMB->ParameterCount = pSMB->TotalParameterCount;
2214 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2215 pSMB->Reserved4 = 0;
2216 pSMB->hdr.smb_buf_length += byte_count;
2217 pSMB->ByteCount = cpu_to_le16(byte_count);
2219 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2220 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2222 cFYI(1, ("Send error in QPathInfo = %d", rc));
2223 } else { /* decode response */
2224 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2226 if (rc || (pSMBr->ByteCount < 40))
2227 rc = -EIO; /* bad smb */
2228 else if (pFindData){
2229 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2230 memcpy((char *) pFindData,
2231 (char *) &pSMBr->hdr.Protocol +
2232 data_offset, sizeof (FILE_ALL_INFO));
2236 cifs_buf_release(pSMB);
2238 goto QPathInfoRetry;
2244 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2245 const unsigned char *searchName,
2246 FILE_UNIX_BASIC_INFO * pFindData,
2247 const struct nls_table *nls_codepage)
2249 /* SMB_QUERY_FILE_UNIX_BASIC */
2250 TRANSACTION2_QPI_REQ *pSMB = NULL;
2251 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2253 int bytes_returned = 0;
2255 __u16 params, byte_count;
2257 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2259 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2264 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2266 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2267 /* find define for this maxpathcomponent */
2269 name_len++; /* trailing null */
2271 } else { /* BB improve the check for buffer overruns BB */
2272 name_len = strnlen(searchName, PATH_MAX);
2273 name_len++; /* trailing null */
2274 strncpy(pSMB->FileName, searchName, name_len);
2277 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2278 pSMB->TotalDataCount = 0;
2279 pSMB->MaxParameterCount = cpu_to_le16(2);
2280 /* BB find exact max SMB PDU from sess structure BB */
2281 pSMB->MaxDataCount = cpu_to_le16(4000);
2282 pSMB->MaxSetupCount = 0;
2286 pSMB->Reserved2 = 0;
2287 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2288 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2289 pSMB->DataCount = 0;
2290 pSMB->DataOffset = 0;
2291 pSMB->SetupCount = 1;
2292 pSMB->Reserved3 = 0;
2293 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2294 byte_count = params + 1 /* pad */ ;
2295 pSMB->TotalParameterCount = cpu_to_le16(params);
2296 pSMB->ParameterCount = pSMB->TotalParameterCount;
2297 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2298 pSMB->Reserved4 = 0;
2299 pSMB->hdr.smb_buf_length += byte_count;
2300 pSMB->ByteCount = cpu_to_le16(byte_count);
2302 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2303 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2305 cFYI(1, ("Send error in QPathInfo = %d", rc));
2306 } else { /* decode response */
2307 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2309 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2310 rc = -EIO; /* bad smb */
2312 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2313 memcpy((char *) pFindData,
2314 (char *) &pSMBr->hdr.Protocol +
2316 sizeof (FILE_UNIX_BASIC_INFO));
2319 cifs_buf_release(pSMB);
2321 goto UnixQPathInfoRetry;
2326 #if 0 /* function unused at present */
2327 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2328 const char *searchName, FILE_ALL_INFO * findData,
2329 const struct nls_table *nls_codepage)
2331 /* level 257 SMB_ */
2332 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2333 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2337 __u16 params, byte_count;
2339 cFYI(1, ("In FindUnique"));
2341 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2346 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2348 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
2349 /* find define for this maxpathcomponent */
2351 name_len++; /* trailing null */
2353 } else { /* BB improve the check for buffer overruns BB */
2354 name_len = strnlen(searchName, PATH_MAX);
2355 name_len++; /* trailing null */
2356 strncpy(pSMB->FileName, searchName, name_len);
2359 params = 12 + name_len /* includes null */ ;
2360 pSMB->TotalDataCount = 0; /* no EAs */
2361 pSMB->MaxParameterCount = cpu_to_le16(2);
2362 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2363 pSMB->MaxSetupCount = 0;
2367 pSMB->Reserved2 = 0;
2368 pSMB->ParameterOffset = cpu_to_le16(
2369 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2370 pSMB->DataCount = 0;
2371 pSMB->DataOffset = 0;
2372 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2373 pSMB->Reserved3 = 0;
2374 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2375 byte_count = params + 1 /* pad */ ;
2376 pSMB->TotalParameterCount = cpu_to_le16(params);
2377 pSMB->ParameterCount = pSMB->TotalParameterCount;
2378 pSMB->SearchAttributes =
2379 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2381 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2382 pSMB->SearchFlags = cpu_to_le16(1);
2383 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2384 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2385 pSMB->hdr.smb_buf_length += byte_count;
2386 pSMB->ByteCount = cpu_to_le16(byte_count);
2388 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2389 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2392 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2393 } else { /* decode response */
2398 cifs_buf_release(pSMB);
2400 goto findUniqueRetry;
2404 #endif /* end unused (temporarily) function */
2406 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2408 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2409 const char *searchName,
2410 const struct nls_table *nls_codepage,
2412 struct cifs_search_info * psrch_inf)
2414 /* level 257 SMB_ */
2415 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2416 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2417 T2_FFIRST_RSP_PARMS * parms;
2419 int bytes_returned = 0;
2421 __u16 params, byte_count;
2423 cFYI(1, ("In FindFirst"));
2426 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2431 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2433 cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName,
2434 PATH_MAX, nls_codepage);
2435 name_len++; /* trailing null */
2437 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2438 pSMB->FileName[name_len+1] = 0;
2439 } else { /* BB add check for overrun of SMB buf BB */
2440 name_len = strnlen(searchName, PATH_MAX);
2441 name_len++; /* trailing null */
2442 /* BB fix here and in unicode clause above ie
2443 if(name_len > buffersize-header)
2444 free buffer exit; BB */
2445 strncpy(pSMB->FileName, searchName, name_len);
2446 pSMB->FileName[name_len] = 0; /* just in case */
2449 params = 12 + name_len /* includes null */ ;
2450 pSMB->TotalDataCount = 0; /* no EAs */
2451 pSMB->MaxParameterCount = cpu_to_le16(10);
2452 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2453 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2454 pSMB->MaxSetupCount = 0;
2458 pSMB->Reserved2 = 0;
2459 byte_count = params + 1 /* pad */ ;
2460 pSMB->TotalParameterCount = cpu_to_le16(params);
2461 pSMB->ParameterCount = pSMB->TotalParameterCount;
2462 pSMB->ParameterOffset = cpu_to_le16(
2463 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2464 pSMB->DataCount = 0;
2465 pSMB->DataOffset = 0;
2466 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2467 pSMB->Reserved3 = 0;
2468 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2469 pSMB->SearchAttributes =
2470 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2472 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2473 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2474 CIFS_SEARCH_RETURN_RESUME);
2475 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2477 /* BB what should we set StorageType to? Does it matter? BB */
2478 pSMB->SearchStorageType = 0;
2479 pSMB->hdr.smb_buf_length += byte_count;
2480 pSMB->ByteCount = cpu_to_le16(byte_count);
2482 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2483 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2485 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2486 /* BB Add code to handle unsupported level rc */
2487 cFYI(1, ("Error in FindFirst = %d", rc));
2490 cifs_buf_release(pSMB);
2492 /* BB eventually could optimize out free and realloc of buf */
2495 goto findFirstRetry;
2496 } else { /* decode response */
2497 /* BB remember to free buffer if error BB */
2498 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2500 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2501 psrch_inf->unicode = TRUE;
2503 psrch_inf->unicode = FALSE;
2505 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2506 psrch_inf->srch_entries_start =
2507 (char *) &pSMBr->hdr.Protocol +
2508 le16_to_cpu(pSMBr->t2.DataOffset);
2510 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2511 le16_to_cpu(pSMBr->t2.ParameterOffset));
2513 if(parms->EndofSearch)
2514 psrch_inf->endOfSearch = TRUE;
2516 psrch_inf->endOfSearch = FALSE;
2518 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2519 psrch_inf->index_of_last_entry =
2520 psrch_inf->entries_in_buffer;
2521 /*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2522 *pnetfid = parms->SearchHandle;
2524 cifs_buf_release(pSMB);
2531 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2532 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2534 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2535 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2536 T2_FNEXT_RSP_PARMS * parms;
2537 char *response_data;
2539 int bytes_returned, name_len;
2540 __u16 params, byte_count;
2542 cFYI(1, ("In FindNext"));
2544 if(psrch_inf->endOfSearch == TRUE)
2547 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2552 params = 14; /* includes 2 bytes of null string, converted to LE below */
2554 pSMB->TotalDataCount = 0; /* no EAs */
2555 pSMB->MaxParameterCount = cpu_to_le16(8);
2556 pSMB->MaxDataCount =
2557 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2558 pSMB->MaxSetupCount = 0;
2562 pSMB->Reserved2 = 0;
2563 pSMB->ParameterOffset = cpu_to_le16(
2564 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2565 pSMB->DataCount = 0;
2566 pSMB->DataOffset = 0;
2567 pSMB->SetupCount = 1;
2568 pSMB->Reserved3 = 0;
2569 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2570 pSMB->SearchHandle = searchHandle; /* always kept as le */
2572 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2573 /* test for Unix extensions */
2574 /* if (tcon->ses->capabilities & CAP_UNIX) {
2575 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2576 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2578 pSMB->InformationLevel =
2579 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2580 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2582 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2583 pSMB->ResumeKey = psrch_inf->resume_key;
2585 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2587 name_len = psrch_inf->resume_name_len;
2589 if(name_len < PATH_MAX) {
2590 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2591 byte_count += name_len;
2594 goto FNext2_err_exit;
2596 byte_count = params + 1 /* pad */ ;
2597 pSMB->TotalParameterCount = cpu_to_le16(params);
2598 pSMB->ParameterCount = pSMB->TotalParameterCount;
2599 pSMB->hdr.smb_buf_length += byte_count;
2600 pSMB->ByteCount = cpu_to_le16(byte_count);
2602 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2603 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2607 psrch_inf->endOfSearch = TRUE;
2608 rc = 0; /* search probably was closed at end of search above */
2610 cFYI(1, ("FindNext returned = %d", rc));
2611 } else { /* decode response */
2612 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2615 /* BB fixme add lock for file (srch_info) struct here */
2616 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2617 psrch_inf->unicode = TRUE;
2619 psrch_inf->unicode = FALSE;
2620 response_data = (char *) &pSMBr->hdr.Protocol +
2621 le16_to_cpu(pSMBr->t2.ParameterOffset);
2622 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2623 response_data = (char *)&pSMBr->hdr.Protocol +
2624 le16_to_cpu(pSMBr->t2.DataOffset);
2625 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2626 psrch_inf->srch_entries_start = response_data;
2627 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2628 if(parms->EndofSearch)
2629 psrch_inf->endOfSearch = TRUE;
2631 psrch_inf->endOfSearch = FALSE;
2633 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2634 psrch_inf->index_of_last_entry +=
2635 psrch_inf->entries_in_buffer;
2636 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2638 /* BB fixme add unlock here */
2643 /* BB On error, should we leave previous search buf (and count and
2644 last entry fields) intact or free the previous one? */
2646 /* Note: On -EAGAIN error only caller can retry on handle based calls
2647 since file handle passed in no longer valid */
2650 cifs_buf_release(pSMB);
2656 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2659 FINDCLOSE_REQ *pSMB = NULL;
2660 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2663 cFYI(1, ("In CIFSSMBFindClose"));
2664 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2666 /* no sense returning error if session restarted
2667 as file handle has been closed */
2673 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2674 pSMB->FileID = searchHandle;
2675 pSMB->ByteCount = 0;
2676 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2677 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2679 cERROR(1, ("Send error in FindClose = %d", rc));
2681 cifs_small_buf_release(pSMB);
2683 /* Since session is dead, search handle closed on server already */
2690 #ifdef CONFIG_CIFS_EXPERIMENTAL
2692 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2693 const unsigned char *searchName,
2694 __u64 * inode_number,
2695 const struct nls_table *nls_codepage)
2698 TRANSACTION2_QPI_REQ *pSMB = NULL;
2699 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2700 int name_len, bytes_returned;
2701 __u16 params, byte_count;
2703 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2707 GetInodeNumberRetry:
2708 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2714 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2716 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName,
2717 PATH_MAX,nls_codepage);
2718 name_len++; /* trailing null */
2720 } else { /* BB improve the check for buffer overruns BB */
2721 name_len = strnlen(searchName, PATH_MAX);
2722 name_len++; /* trailing null */
2723 strncpy(pSMB->FileName, searchName, name_len);
2726 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2727 pSMB->TotalDataCount = 0;
2728 pSMB->MaxParameterCount = cpu_to_le16(2);
2729 /* BB find exact max data count below from sess structure BB */
2730 pSMB->MaxDataCount = cpu_to_le16(4000);
2731 pSMB->MaxSetupCount = 0;
2735 pSMB->Reserved2 = 0;
2736 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2737 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2738 pSMB->DataCount = 0;
2739 pSMB->DataOffset = 0;
2740 pSMB->SetupCount = 1;
2741 pSMB->Reserved3 = 0;
2742 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2743 byte_count = params + 1 /* pad */ ;
2744 pSMB->TotalParameterCount = cpu_to_le16(params);
2745 pSMB->ParameterCount = pSMB->TotalParameterCount;
2746 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
2747 pSMB->Reserved4 = 0;
2748 pSMB->hdr.smb_buf_length += byte_count;
2749 pSMB->ByteCount = cpu_to_le16(byte_count);
2751 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2752 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2754 cFYI(1, ("error %d in QueryInternalInfo", rc));
2756 /* decode response */
2757 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2758 if (rc || (pSMBr->ByteCount < 2))
2759 /* BB also check enough total bytes returned */
2760 /* If rc should we check for EOPNOSUPP and
2761 disable the srvino flag? or in caller? */
2762 rc = -EIO; /* bad smb */
2764 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2765 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2766 struct file_internal_info * pfinfo;
2767 /* BB Do we need a cast or hash here ? */
2769 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2771 goto GetInodeNumOut;
2773 pfinfo = (struct file_internal_info *)
2774 (data_offset + (char *) &pSMBr->hdr.Protocol);
2775 *inode_number = pfinfo->UniqueId;
2779 cifs_buf_release(pSMB);
2781 goto GetInodeNumberRetry;
2784 #endif /* CIFS_EXPERIMENTAL */
2787 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2788 const unsigned char *searchName,
2789 unsigned char **targetUNCs,
2790 unsigned int *number_of_UNC_in_array,
2791 const struct nls_table *nls_codepage)
2793 /* TRANS2_GET_DFS_REFERRAL */
2794 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2795 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2796 struct dfs_referral_level_3 * referrals = NULL;
2802 __u16 params, byte_count;
2803 *number_of_UNC_in_array = 0;
2806 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2810 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2815 pSMB->hdr.Tid = ses->ipc_tid;
2816 pSMB->hdr.Uid = ses->Suid;
2817 if (ses->capabilities & CAP_STATUS32) {
2818 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2820 if (ses->capabilities & CAP_DFS) {
2821 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2824 if (ses->capabilities & CAP_UNICODE) {
2825 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2827 cifs_strtoUCS((wchar_t *) pSMB->RequestFileName,
2828 searchName, PATH_MAX
2829 /* find define for this maxpathcomponent */
2831 name_len++; /* trailing null */
2833 } else { /* BB improve the check for buffer overruns BB */
2834 name_len = strnlen(searchName, PATH_MAX);
2835 name_len++; /* trailing null */
2836 strncpy(pSMB->RequestFileName, searchName, name_len);
2839 params = 2 /* level */ + name_len /*includes null */ ;
2840 pSMB->TotalDataCount = 0;
2841 pSMB->DataCount = 0;
2842 pSMB->DataOffset = 0;
2843 pSMB->MaxParameterCount = 0;
2844 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2845 pSMB->MaxSetupCount = 0;
2849 pSMB->Reserved2 = 0;
2850 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2851 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2852 pSMB->SetupCount = 1;
2853 pSMB->Reserved3 = 0;
2854 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2855 byte_count = params + 3 /* pad */ ;
2856 pSMB->ParameterCount = cpu_to_le16(params);
2857 pSMB->TotalParameterCount = pSMB->ParameterCount;
2858 pSMB->MaxReferralLevel = cpu_to_le16(3);
2859 pSMB->hdr.smb_buf_length += byte_count;
2860 pSMB->ByteCount = cpu_to_le16(byte_count);
2862 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2863 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2865 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2866 } else { /* decode response */
2867 /* BB Add logic to parse referrals here */
2868 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2870 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
2871 rc = -EIO; /* bad smb */
2873 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2874 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2877 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2878 pSMBr->ByteCount, data_offset));
2880 (struct dfs_referral_level_3 *)
2881 (8 /* sizeof start of data block */ +
2883 (char *) &pSMBr->hdr.Protocol);
2884 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",
2885 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)));
2886 /* BB This field is actually two bytes in from start of
2887 data block so we could do safety check that DataBlock
2888 begins at address of pSMBr->NumberOfReferrals */
2889 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2891 /* BB Fix below so can return more than one referral */
2892 if(*number_of_UNC_in_array > 1)
2893 *number_of_UNC_in_array = 1;
2895 /* get the length of the strings describing refs */
2897 for(i=0;i<*number_of_UNC_in_array;i++) {
2898 /* make sure that DfsPathOffset not past end */
2899 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2900 if (offset > data_count) {
2901 /* if invalid referral, stop here and do
2902 not try to copy any more */
2903 *number_of_UNC_in_array = i;
2906 temp = ((char *)referrals) + offset;
2908 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2909 name_len += UniStrnlen((wchar_t *)temp,data_count);
2911 name_len += strnlen(temp,data_count);
2914 /* BB add check that referral pointer does not fall off end PDU */
2917 /* BB add check for name_len bigger than bcc */
2919 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2920 if(*targetUNCs == NULL) {
2924 /* copy the ref strings */
2926 (struct dfs_referral_level_3 *)
2927 (8 /* sizeof data hdr */ +
2929 (char *) &pSMBr->hdr.Protocol);
2931 for(i=0;i<*number_of_UNC_in_array;i++) {
2932 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2933 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2934 cifs_strfromUCS_le(*targetUNCs,
2935 (wchar_t *) temp, name_len, nls_codepage);
2937 strncpy(*targetUNCs,temp,name_len);
2939 /* BB update target_uncs pointers */
2949 cifs_buf_release(pSMB);
2958 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
2959 struct kstatfs *FSData, const struct nls_table *nls_codepage)
2961 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
2962 TRANSACTION2_QFSI_REQ *pSMB = NULL;
2963 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
2964 FILE_SYSTEM_INFO *response_data;
2966 int bytes_returned = 0;
2967 __u16 params, byte_count;
2969 cFYI(1, ("In QFSInfo"));
2971 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2976 params = 2; /* level */
2977 pSMB->TotalDataCount = 0;
2978 pSMB->MaxParameterCount = cpu_to_le16(2);
2979 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
2980 pSMB->MaxSetupCount = 0;
2984 pSMB->Reserved2 = 0;
2985 byte_count = params + 1 /* pad */ ;
2986 pSMB->TotalParameterCount = cpu_to_le16(params);
2987 pSMB->ParameterCount = pSMB->TotalParameterCount;
2988 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2989 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
2990 pSMB->DataCount = 0;
2991 pSMB->DataOffset = 0;
2992 pSMB->SetupCount = 1;
2993 pSMB->Reserved3 = 0;
2994 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
2995 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
2996 pSMB->hdr.smb_buf_length += byte_count;
2997 pSMB->ByteCount = cpu_to_le16(byte_count);
2999 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3000 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3002 cERROR(1, ("Send error in QFSInfo = %d", rc));
3003 } else { /* decode response */
3004 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3006 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3007 rc = -EIO; /* bad smb */
3009 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3011 ("Decoding qfsinfo response. BCC: %d Offset %d",
3012 pSMBr->ByteCount, data_offset));
3016 *) (((char *) &pSMBr->hdr.Protocol) +
3019 le32_to_cpu(response_data->BytesPerSector) *
3020 le32_to_cpu(response_data->
3021 SectorsPerAllocationUnit);
3023 le64_to_cpu(response_data->TotalAllocationUnits);
3024 FSData->f_bfree = FSData->f_bavail =
3025 le64_to_cpu(response_data->FreeAllocationUnits);
3027 ("Blocks: %lld Free: %lld Block size %ld",
3028 (unsigned long long)FSData->f_blocks,
3029 (unsigned long long)FSData->f_bfree,
3033 cifs_buf_release(pSMB);
3042 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon,
3043 const struct nls_table *nls_codepage)
3045 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3046 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3047 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3048 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3050 int bytes_returned = 0;
3051 __u16 params, byte_count;
3053 cFYI(1, ("In QFSAttributeInfo"));
3055 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3060 params = 2; /* level */
3061 pSMB->TotalDataCount = 0;
3062 pSMB->MaxParameterCount = cpu_to_le16(2);
3063 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3064 pSMB->MaxSetupCount = 0;
3068 pSMB->Reserved2 = 0;
3069 byte_count = params + 1 /* pad */ ;
3070 pSMB->TotalParameterCount = cpu_to_le16(params);
3071 pSMB->ParameterCount = pSMB->TotalParameterCount;
3072 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3073 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3074 pSMB->DataCount = 0;
3075 pSMB->DataOffset = 0;
3076 pSMB->SetupCount = 1;
3077 pSMB->Reserved3 = 0;
3078 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3079 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3080 pSMB->hdr.smb_buf_length += byte_count;
3081 pSMB->ByteCount = cpu_to_le16(byte_count);
3083 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3084 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3086 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3087 } else { /* decode response */
3088 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3090 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3091 rc = -EIO; /* bad smb */
3093 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3095 (FILE_SYSTEM_ATTRIBUTE_INFO
3096 *) (((char *) &pSMBr->hdr.Protocol) +
3098 memcpy(&tcon->fsAttrInfo, response_data,
3099 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3102 cifs_buf_release(pSMB);
3105 goto QFSAttributeRetry;
3111 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon,
3112 const struct nls_table *nls_codepage)
3114 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3115 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3116 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3117 FILE_SYSTEM_DEVICE_INFO *response_data;
3119 int bytes_returned = 0;
3120 __u16 params, byte_count;
3122 cFYI(1, ("In QFSDeviceInfo"));
3124 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3129 params = 2; /* level */
3130 pSMB->TotalDataCount = 0;
3131 pSMB->MaxParameterCount = cpu_to_le16(2);
3132 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3133 pSMB->MaxSetupCount = 0;
3137 pSMB->Reserved2 = 0;
3138 byte_count = params + 1 /* pad */ ;
3139 pSMB->TotalParameterCount = cpu_to_le16(params);
3140 pSMB->ParameterCount = pSMB->TotalParameterCount;
3141 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3142 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3144 pSMB->DataCount = 0;
3145 pSMB->DataOffset = 0;
3146 pSMB->SetupCount = 1;
3147 pSMB->Reserved3 = 0;
3148 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3149 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3150 pSMB->hdr.smb_buf_length += byte_count;
3151 pSMB->ByteCount = cpu_to_le16(byte_count);
3153 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3154 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3156 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3157 } else { /* decode response */
3158 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3160 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3161 rc = -EIO; /* bad smb */
3163 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3165 (FILE_SYSTEM_DEVICE_INFO
3166 *) (((char *) &pSMBr->hdr.Protocol) +
3168 memcpy(&tcon->fsDevInfo, response_data,
3169 sizeof (FILE_SYSTEM_DEVICE_INFO));
3172 cifs_buf_release(pSMB);
3175 goto QFSDeviceRetry;
3181 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
3182 const struct nls_table *nls_codepage)
3184 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3185 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3186 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3187 FILE_SYSTEM_UNIX_INFO *response_data;
3189 int bytes_returned = 0;
3190 __u16 params, byte_count;
3192 cFYI(1, ("In QFSUnixInfo"));
3194 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3199 params = 2; /* level */
3200 pSMB->TotalDataCount = 0;
3201 pSMB->DataCount = 0;
3202 pSMB->DataOffset = 0;
3203 pSMB->MaxParameterCount = cpu_to_le16(2);
3204 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3205 pSMB->MaxSetupCount = 0;
3209 pSMB->Reserved2 = 0;
3210 byte_count = params + 1 /* pad */ ;
3211 pSMB->ParameterCount = cpu_to_le16(params);
3212 pSMB->TotalParameterCount = pSMB->ParameterCount;
3213 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3214 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3215 pSMB->SetupCount = 1;
3216 pSMB->Reserved3 = 0;
3217 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3218 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3219 pSMB->hdr.smb_buf_length += byte_count;
3220 pSMB->ByteCount = cpu_to_le16(byte_count);
3222 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3223 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3225 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3226 } else { /* decode response */
3227 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3229 if (rc || (pSMBr->ByteCount < 13)) {
3230 rc = -EIO; /* bad smb */
3232 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3234 (FILE_SYSTEM_UNIX_INFO
3235 *) (((char *) &pSMBr->hdr.Protocol) +
3237 memcpy(&tcon->fsUnixInfo, response_data,
3238 sizeof (FILE_SYSTEM_UNIX_INFO));
3241 cifs_buf_release(pSMB);
3252 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3253 struct kstatfs *FSData, const struct nls_table *nls_codepage)
3255 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3256 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3257 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3258 FILE_SYSTEM_POSIX_INFO *response_data;
3260 int bytes_returned = 0;
3261 __u16 params, byte_count;
3263 cFYI(1, ("In QFSPosixInfo"));
3265 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3270 params = 2; /* level */
3271 pSMB->TotalDataCount = 0;
3272 pSMB->DataCount = 0;
3273 pSMB->DataOffset = 0;
3274 pSMB->MaxParameterCount = cpu_to_le16(2);
3275 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3276 pSMB->MaxSetupCount = 0;
3280 pSMB->Reserved2 = 0;
3281 byte_count = params + 1 /* pad */ ;
3282 pSMB->ParameterCount = cpu_to_le16(params);
3283 pSMB->TotalParameterCount = pSMB->ParameterCount;
3284 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3285 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3286 pSMB->SetupCount = 1;
3287 pSMB->Reserved3 = 0;
3288 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3289 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3290 pSMB->hdr.smb_buf_length += byte_count;
3291 pSMB->ByteCount = cpu_to_le16(byte_count);
3293 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3294 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3296 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3297 } else { /* decode response */
3298 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3300 if (rc || (pSMBr->ByteCount < 13)) {
3301 rc = -EIO; /* bad smb */
3303 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3305 (FILE_SYSTEM_POSIX_INFO
3306 *) (((char *) &pSMBr->hdr.Protocol) +
3309 le32_to_cpu(response_data->BlockSize);
3311 le64_to_cpu(response_data->TotalBlocks);
3313 le64_to_cpu(response_data->BlocksAvail);
3314 if(response_data->UserBlocksAvail == -1) {
3315 FSData->f_bavail = FSData->f_bfree;
3318 le64_to_cpu(response_data->UserBlocksAvail);
3320 if(response_data->TotalFileNodes != -1)
3322 le64_to_cpu(response_data->TotalFileNodes);
3323 if(response_data->FreeFileNodes != -1)
3325 le64_to_cpu(response_data->FreeFileNodes);
3328 cifs_buf_release(pSMB);
3337 /* We can not use write of zero bytes trick to
3338 set file size due to need for large file support. Also note that
3339 this SetPathInfo is preferred to SetFileInfo based method in next
3340 routine which is only needed to work around a sharing violation bug
3341 in Samba which this routine can run into */
3344 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3345 __u64 size, int SetAllocation, const struct nls_table *nls_codepage)
3347 struct smb_com_transaction2_spi_req *pSMB = NULL;
3348 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3349 struct file_end_of_file_info *parm_data;
3352 int bytes_returned = 0;
3353 __u16 params, byte_count, data_count, param_offset, offset;
3355 cFYI(1, ("In SetEOF"));
3357 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3362 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3364 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3365 /* find define for this maxpathcomponent */
3367 name_len++; /* trailing null */
3369 } else { /* BB improve the check for buffer overruns BB */
3370 name_len = strnlen(fileName, PATH_MAX);
3371 name_len++; /* trailing null */
3372 strncpy(pSMB->FileName, fileName, name_len);
3374 params = 6 + name_len;
3375 data_count = sizeof (struct file_end_of_file_info);
3376 pSMB->MaxParameterCount = cpu_to_le16(2);
3377 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3378 pSMB->MaxSetupCount = 0;
3382 pSMB->Reserved2 = 0;
3383 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3384 InformationLevel) - 4;
3385 offset = param_offset + params;
3387 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3388 pSMB->InformationLevel =
3389 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3391 pSMB->InformationLevel =
3392 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3393 } else /* Set File Size */ {
3394 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3395 pSMB->InformationLevel =
3396 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3398 pSMB->InformationLevel =
3399 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3403 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3405 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3406 pSMB->DataOffset = cpu_to_le16(offset);
3407 pSMB->SetupCount = 1;
3408 pSMB->Reserved3 = 0;
3409 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3410 byte_count = 3 /* pad */ + params + data_count;
3411 pSMB->DataCount = cpu_to_le16(data_count);
3412 pSMB->TotalDataCount = pSMB->DataCount;
3413 pSMB->ParameterCount = cpu_to_le16(params);
3414 pSMB->TotalParameterCount = pSMB->ParameterCount;
3415 pSMB->Reserved4 = 0;
3416 pSMB->hdr.smb_buf_length += byte_count;
3417 parm_data->FileSize = cpu_to_le64(size);
3418 pSMB->ByteCount = cpu_to_le16(byte_count);
3419 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3420 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3422 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3425 cifs_buf_release(pSMB);
3434 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3435 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3437 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3438 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3440 struct file_end_of_file_info *parm_data;
3442 int bytes_returned = 0;
3443 __u16 params, param_offset, offset, byte_count, count;
3445 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3447 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3452 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3453 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3456 pSMB->MaxSetupCount = 0;
3460 pSMB->Reserved2 = 0;
3461 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3462 offset = param_offset + params;
3464 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3466 count = sizeof(struct file_end_of_file_info);
3467 pSMB->MaxParameterCount = cpu_to_le16(2);
3468 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3469 pSMB->SetupCount = 1;
3470 pSMB->Reserved3 = 0;
3471 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3472 byte_count = 3 /* pad */ + params + count;
3473 pSMB->DataCount = cpu_to_le16(count);
3474 pSMB->ParameterCount = cpu_to_le16(params);
3475 pSMB->TotalDataCount = pSMB->DataCount;
3476 pSMB->TotalParameterCount = pSMB->ParameterCount;
3477 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3479 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3481 pSMB->DataOffset = cpu_to_le16(offset);
3482 parm_data->FileSize = cpu_to_le64(size);
3485 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3486 pSMB->InformationLevel =
3487 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3489 pSMB->InformationLevel =
3490 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3491 } else /* Set File Size */ {
3492 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3493 pSMB->InformationLevel =
3494 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3496 pSMB->InformationLevel =
3497 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3499 pSMB->Reserved4 = 0;
3500 pSMB->hdr.smb_buf_length += byte_count;
3501 pSMB->ByteCount = cpu_to_le16(byte_count);
3502 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3503 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3506 ("Send error in SetFileInfo (SetFileSize) = %d",
3511 cifs_buf_release(pSMB);
3513 /* Note: On -EAGAIN error only caller can retry on handle based calls
3514 since file handle passed in no longer valid */
3519 /* Some legacy servers such as NT4 require that the file times be set on
3520 an open handle, rather than by pathname - this is awkward due to
3521 potential access conflicts on the open, but it is unavoidable for these
3522 old servers since the only other choice is to go from 100 nanosecond DCE
3523 time and resort to the original setpathinfo level which takes the ancient
3524 DOS time format with 2 second granularity */
3526 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3529 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3530 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3533 int bytes_returned = 0;
3534 __u16 params, param_offset, offset, byte_count, count;
3536 cFYI(1, ("Set Times (via SetFileInfo)"));
3537 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3542 /* At this point there is no need to override the current pid
3543 with the pid of the opener, but that could change if we someday
3544 use an existing handle (rather than opening one on the fly) */
3545 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3546 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3549 pSMB->MaxSetupCount = 0;
3553 pSMB->Reserved2 = 0;
3554 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3555 offset = param_offset + params;
3557 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3559 count = sizeof (FILE_BASIC_INFO);
3560 pSMB->MaxParameterCount = cpu_to_le16(2);
3561 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3562 pSMB->SetupCount = 1;
3563 pSMB->Reserved3 = 0;
3564 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3565 byte_count = 3 /* pad */ + params + count;
3566 pSMB->DataCount = cpu_to_le16(count);
3567 pSMB->ParameterCount = cpu_to_le16(params);
3568 pSMB->TotalDataCount = pSMB->DataCount;
3569 pSMB->TotalParameterCount = pSMB->ParameterCount;
3570 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3571 pSMB->DataOffset = cpu_to_le16(offset);
3573 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3574 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3576 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3577 pSMB->Reserved4 = 0;
3578 pSMB->hdr.smb_buf_length += byte_count;
3579 pSMB->ByteCount = cpu_to_le16(byte_count);
3580 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3581 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3582 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3584 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3587 cifs_buf_release(pSMB);
3589 /* Note: On -EAGAIN error only caller can retry on handle based calls
3590 since file handle passed in no longer valid */
3597 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3598 const FILE_BASIC_INFO * data,
3599 const struct nls_table *nls_codepage)
3601 TRANSACTION2_SPI_REQ *pSMB = NULL;
3602 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3605 int bytes_returned = 0;
3607 __u16 params, param_offset, offset, byte_count, count;
3609 cFYI(1, ("In SetTimes"));
3612 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3617 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3619 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3620 /* find define for this maxpathcomponent */
3622 name_len++; /* trailing null */
3624 } else { /* BB improve the check for buffer overruns BB */
3625 name_len = strnlen(fileName, PATH_MAX);
3626 name_len++; /* trailing null */
3627 strncpy(pSMB->FileName, fileName, name_len);
3630 params = 6 + name_len;
3631 count = sizeof (FILE_BASIC_INFO);
3632 pSMB->MaxParameterCount = cpu_to_le16(2);
3633 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3634 pSMB->MaxSetupCount = 0;
3638 pSMB->Reserved2 = 0;
3639 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3640 InformationLevel) - 4;
3641 offset = param_offset + params;
3642 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3643 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3644 pSMB->DataOffset = cpu_to_le16(offset);
3645 pSMB->SetupCount = 1;
3646 pSMB->Reserved3 = 0;
3647 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3648 byte_count = 3 /* pad */ + params + count;
3650 pSMB->DataCount = cpu_to_le16(count);
3651 pSMB->ParameterCount = cpu_to_le16(params);
3652 pSMB->TotalDataCount = pSMB->DataCount;
3653 pSMB->TotalParameterCount = pSMB->ParameterCount;
3654 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3655 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3657 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3658 pSMB->Reserved4 = 0;
3659 pSMB->hdr.smb_buf_length += byte_count;
3660 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3661 pSMB->ByteCount = cpu_to_le16(byte_count);
3662 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3663 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3665 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3668 cifs_buf_release(pSMB);
3676 /* Can not be used to set time stamps yet (due to old DOS time format) */
3677 /* Can be used to set attributes */
3678 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3679 handling it anyway and NT4 was what we thought it would be needed for
3680 Do not delete it until we prove whether needed for Win9x though */
3682 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3683 __u16 dos_attrs, const struct nls_table *nls_codepage)
3685 SETATTR_REQ *pSMB = NULL;
3686 SETATTR_RSP *pSMBr = NULL;
3691 cFYI(1, ("In SetAttrLegacy"));
3694 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
3699 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3701 cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName,
3702 PATH_MAX, nls_codepage);
3703 name_len++; /* trailing null */
3705 } else { /* BB improve the check for buffer overruns BB */
3706 name_len = strnlen(fileName, PATH_MAX);
3707 name_len++; /* trailing null */
3708 strncpy(pSMB->fileName, fileName, name_len);
3710 pSMB->attr = cpu_to_le16(dos_attrs);
3711 pSMB->BufferFormat = 0x04;
3712 pSMB->hdr.smb_buf_length += name_len + 1;
3713 pSMB->ByteCount = cpu_to_le16(name_len + 1);
3714 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3715 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3717 cFYI(1, ("Error in LegacySetAttr = %d", rc));
3720 cifs_buf_release(pSMB);
3723 goto SetAttrLgcyRetry;
3727 #endif /* temporarily unneeded SetAttr legacy function */
3730 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3731 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3732 dev_t device, const struct nls_table *nls_codepage)
3734 TRANSACTION2_SPI_REQ *pSMB = NULL;
3735 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3738 int bytes_returned = 0;
3739 FILE_UNIX_BASIC_INFO *data_offset;
3740 __u16 params, param_offset, offset, count, byte_count;
3742 cFYI(1, ("In SetUID/GID/Mode"));
3744 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3749 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3751 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
3752 /* find define for this maxpathcomponent */
3754 name_len++; /* trailing null */
3756 } else { /* BB improve the check for buffer overruns BB */
3757 name_len = strnlen(fileName, PATH_MAX);
3758 name_len++; /* trailing null */
3759 strncpy(pSMB->FileName, fileName, name_len);
3762 params = 6 + name_len;
3763 count = sizeof (FILE_UNIX_BASIC_INFO);
3764 pSMB->MaxParameterCount = cpu_to_le16(2);
3765 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3766 pSMB->MaxSetupCount = 0;
3770 pSMB->Reserved2 = 0;
3771 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3772 InformationLevel) - 4;
3773 offset = param_offset + params;
3775 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3777 memset(data_offset, 0, count);
3778 pSMB->DataOffset = cpu_to_le16(offset);
3779 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3780 pSMB->SetupCount = 1;
3781 pSMB->Reserved3 = 0;
3782 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3783 byte_count = 3 /* pad */ + params + count;
3784 pSMB->ParameterCount = cpu_to_le16(params);
3785 pSMB->DataCount = cpu_to_le16(count);
3786 pSMB->TotalParameterCount = pSMB->ParameterCount;
3787 pSMB->TotalDataCount = pSMB->DataCount;
3788 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3789 pSMB->Reserved4 = 0;
3790 pSMB->hdr.smb_buf_length += byte_count;
3791 data_offset->Uid = cpu_to_le64(uid);
3792 data_offset->Gid = cpu_to_le64(gid);
3793 /* better to leave device as zero when it is */
3794 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3795 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3796 data_offset->Permissions = cpu_to_le64(mode);
3799 data_offset->Type = cpu_to_le32(UNIX_FILE);
3800 else if(S_ISDIR(mode))
3801 data_offset->Type = cpu_to_le32(UNIX_DIR);
3802 else if(S_ISLNK(mode))
3803 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3804 else if(S_ISCHR(mode))
3805 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3806 else if(S_ISBLK(mode))
3807 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3808 else if(S_ISFIFO(mode))
3809 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3810 else if(S_ISSOCK(mode))
3811 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3814 pSMB->ByteCount = cpu_to_le16(byte_count);
3815 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3816 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3818 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3822 cifs_buf_release(pSMB);
3828 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3829 const int notify_subdirs, const __u16 netfid,
3830 __u32 filter, const struct nls_table *nls_codepage)
3833 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3834 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3837 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3838 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3843 pSMB->TotalParameterCount = 0 ;
3844 pSMB->TotalDataCount = 0;
3845 pSMB->MaxParameterCount = cpu_to_le32(2);
3846 /* BB find exact data count max from sess structure BB */
3847 pSMB->MaxDataCount = 0; /* same in little endian or be */
3848 pSMB->MaxSetupCount = 4;
3850 pSMB->ParameterOffset = 0;
3851 pSMB->DataCount = 0;
3852 pSMB->DataOffset = 0;
3853 pSMB->SetupCount = 4; /* single byte does not need le conversion */
3854 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
3855 pSMB->ParameterCount = pSMB->TotalParameterCount;
3857 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
3858 pSMB->Reserved2 = 0;
3859 pSMB->CompletionFilter = cpu_to_le32(filter);
3860 pSMB->Fid = netfid; /* file handle always le */
3861 pSMB->ByteCount = 0;
3863 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3864 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3866 cFYI(1, ("Error in Notify = %d", rc));
3868 cifs_buf_release(pSMB);
3871 #ifdef CONFIG_CIFS_XATTR
3873 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
3874 const unsigned char *searchName,
3875 char * EAData, size_t buf_size,
3876 const struct nls_table *nls_codepage)
3878 /* BB assumes one setup word */
3879 TRANSACTION2_QPI_REQ *pSMB = NULL;
3880 TRANSACTION2_QPI_RSP *pSMBr = NULL;
3884 struct fea * temp_fea;
3886 __u16 params, byte_count;
3888 cFYI(1, ("In Query All EAs path %s", searchName));
3890 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3895 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3897 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
3898 /* find define for this maxpathcomponent */
3900 name_len++; /* trailing null */
3902 } else { /* BB improve the check for buffer overruns BB */
3903 name_len = strnlen(searchName, PATH_MAX);
3904 name_len++; /* trailing null */
3905 strncpy(pSMB->FileName, searchName, name_len);
3908 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
3909 pSMB->TotalDataCount = 0;
3910 pSMB->MaxParameterCount = cpu_to_le16(2);
3911 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
3912 pSMB->MaxSetupCount = 0;
3916 pSMB->Reserved2 = 0;
3917 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3918 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
3919 pSMB->DataCount = 0;
3920 pSMB->DataOffset = 0;
3921 pSMB->SetupCount = 1;
3922 pSMB->Reserved3 = 0;
3923 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
3924 byte_count = params + 1 /* pad */ ;
3925 pSMB->TotalParameterCount = cpu_to_le16(params);
3926 pSMB->ParameterCount = pSMB->TotalParameterCount;
3927 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
3928 pSMB->Reserved4 = 0;
3929 pSMB->hdr.smb_buf_length += byte_count;
3930 pSMB->ByteCount = cpu_to_le16(byte_count);
3932 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3933 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3935 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
3936 } else { /* decode response */
3937 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3939 /* BB also check enough total bytes returned */
3940 /* BB we need to improve the validity checking
3941 of these trans2 responses */
3942 if (rc || (pSMBr->ByteCount < 4))
3943 rc = -EIO; /* bad smb */
3944 /* else if (pFindData){
3945 memcpy((char *) pFindData,
3946 (char *) &pSMBr->hdr.Protocol +
3949 /* check that length of list is not more than bcc */
3950 /* check that each entry does not go beyond length
3952 /* check that each element of each entry does not
3953 go beyond end of list */
3954 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3955 struct fealist * ea_response_data;
3957 /* validate_trans2_offsets() */
3958 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
3959 ea_response_data = (struct fealist *)
3960 (((char *) &pSMBr->hdr.Protocol) +
3962 name_len = le32_to_cpu(ea_response_data->list_len);
3963 cFYI(1,("ea length %d", name_len));
3965 /* returned EA size zeroed at top of function */
3966 cFYI(1,("empty EA list returned from server"));
3968 /* account for ea list len */
3970 temp_fea = ea_response_data->list;
3971 temp_ptr = (char *)temp_fea;
3972 while(name_len > 0) {
3976 rc += temp_fea->name_len;
3977 /* account for prefix user. and trailing null */
3979 if(rc<(int)buf_size) {
3980 memcpy(EAData,"user.",5);
3982 memcpy(EAData,temp_ptr,temp_fea->name_len);
3983 EAData+=temp_fea->name_len;
3984 /* null terminate name */
3986 EAData = EAData + 1;
3987 } else if(buf_size == 0) {
3988 /* skip copy - calc size only */
3990 /* stop before overrun buffer */
3994 name_len -= temp_fea->name_len;
3995 temp_ptr += temp_fea->name_len;
3996 /* account for trailing null */
3999 value_len = le16_to_cpu(temp_fea->value_len);
4000 name_len -= value_len;
4001 temp_ptr += value_len;
4002 /* BB check that temp_ptr is still within smb BB*/
4003 /* no trailing null to account for in value len */
4004 /* go on to next EA */
4005 temp_fea = (struct fea *)temp_ptr;
4011 cifs_buf_release(pSMB);
4018 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4019 const unsigned char * searchName,const unsigned char * ea_name,
4020 unsigned char * ea_value, size_t buf_size,
4021 const struct nls_table *nls_codepage)
4023 TRANSACTION2_QPI_REQ *pSMB = NULL;
4024 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4028 struct fea * temp_fea;
4030 __u16 params, byte_count;
4032 cFYI(1, ("In Query EA path %s", searchName));
4034 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4039 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4041 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
4042 /* find define for this maxpathcomponent */
4044 name_len++; /* trailing null */
4046 } else { /* BB improve the check for buffer overruns BB */
4047 name_len = strnlen(searchName, PATH_MAX);
4048 name_len++; /* trailing null */
4049 strncpy(pSMB->FileName, searchName, name_len);
4052 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4053 pSMB->TotalDataCount = 0;
4054 pSMB->MaxParameterCount = cpu_to_le16(2);
4055 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4056 pSMB->MaxSetupCount = 0;
4060 pSMB->Reserved2 = 0;
4061 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4062 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4063 pSMB->DataCount = 0;
4064 pSMB->DataOffset = 0;
4065 pSMB->SetupCount = 1;
4066 pSMB->Reserved3 = 0;
4067 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4068 byte_count = params + 1 /* pad */ ;
4069 pSMB->TotalParameterCount = cpu_to_le16(params);
4070 pSMB->ParameterCount = pSMB->TotalParameterCount;
4071 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4072 pSMB->Reserved4 = 0;
4073 pSMB->hdr.smb_buf_length += byte_count;
4074 pSMB->ByteCount = cpu_to_le16(byte_count);
4076 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4077 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4079 cFYI(1, ("Send error in Query EA = %d", rc));
4080 } else { /* decode response */
4081 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4083 /* BB also check enough total bytes returned */
4084 /* BB we need to improve the validity checking
4085 of these trans2 responses */
4086 if (rc || (pSMBr->ByteCount < 4))
4087 rc = -EIO; /* bad smb */
4088 /* else if (pFindData){
4089 memcpy((char *) pFindData,
4090 (char *) &pSMBr->hdr.Protocol +
4093 /* check that length of list is not more than bcc */
4094 /* check that each entry does not go beyond length
4096 /* check that each element of each entry does not
4097 go beyond end of list */
4098 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4099 struct fealist * ea_response_data;
4101 /* validate_trans2_offsets() */
4102 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4103 ea_response_data = (struct fealist *)
4104 (((char *) &pSMBr->hdr.Protocol) +
4106 name_len = le32_to_cpu(ea_response_data->list_len);
4107 cFYI(1,("ea length %d", name_len));
4109 /* returned EA size zeroed at top of function */
4110 cFYI(1,("empty EA list returned from server"));
4112 /* account for ea list len */
4114 temp_fea = ea_response_data->list;
4115 temp_ptr = (char *)temp_fea;
4116 /* loop through checking if we have a matching
4117 name and then return the associated value */
4118 while(name_len > 0) {
4122 value_len = le16_to_cpu(temp_fea->value_len);
4123 /* BB validate that value_len falls within SMB,
4124 even though maximum for name_len is 255 */
4125 if(memcmp(temp_fea->name,ea_name,
4126 temp_fea->name_len) == 0) {
4129 /* account for prefix user. and trailing null */
4130 if(rc<=(int)buf_size) {
4132 temp_fea->name+temp_fea->name_len+1,
4134 /* ea values, unlike ea names,
4135 are not null terminated */
4136 } else if(buf_size == 0) {
4137 /* skip copy - calc size only */
4139 /* stop before overrun buffer */
4144 name_len -= temp_fea->name_len;
4145 temp_ptr += temp_fea->name_len;
4146 /* account for trailing null */
4149 name_len -= value_len;
4150 temp_ptr += value_len;
4151 /* no trailing null to account for in value len */
4152 /* go on to next EA */
4153 temp_fea = (struct fea *)temp_ptr;
4159 cifs_buf_release(pSMB);
4167 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4168 const char * ea_name, const void * ea_value,
4169 const __u16 ea_value_len, const struct nls_table *nls_codepage)
4171 struct smb_com_transaction2_spi_req *pSMB = NULL;
4172 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4173 struct fealist *parm_data;
4176 int bytes_returned = 0;
4177 __u16 params, param_offset, byte_count, offset, count;
4179 cFYI(1, ("In SetEA"));
4181 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4186 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4188 cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX
4189 /* find define for this maxpathcomponent */
4191 name_len++; /* trailing null */
4193 } else { /* BB improve the check for buffer overruns BB */
4194 name_len = strnlen(fileName, PATH_MAX);
4195 name_len++; /* trailing null */
4196 strncpy(pSMB->FileName, fileName, name_len);
4199 params = 6 + name_len;
4201 /* done calculating parms using name_len of file name,
4202 now use name_len to calculate length of ea name
4203 we are going to create in the inode xattrs */
4207 name_len = strnlen(ea_name,255);
4209 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4210 pSMB->MaxParameterCount = cpu_to_le16(2);
4211 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4212 pSMB->MaxSetupCount = 0;
4216 pSMB->Reserved2 = 0;
4217 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4218 InformationLevel) - 4;
4219 offset = param_offset + params;
4220 pSMB->InformationLevel =
4221 cpu_to_le16(SMB_SET_FILE_EA);
4224 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4226 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4227 pSMB->DataOffset = cpu_to_le16(offset);
4228 pSMB->SetupCount = 1;
4229 pSMB->Reserved3 = 0;
4230 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4231 byte_count = 3 /* pad */ + params + count;
4232 pSMB->DataCount = cpu_to_le16(count);
4233 parm_data->list_len = cpu_to_le32(count);
4234 parm_data->list[0].EA_flags = 0;
4235 /* we checked above that name len is less than 255 */
4236 parm_data->list[0].name_len = (__u8)name_len;;
4237 /* EA names are always ASCII */
4239 strncpy(parm_data->list[0].name,ea_name,name_len);
4240 parm_data->list[0].name[name_len] = 0;
4241 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4242 /* caller ensures that ea_value_len is less than 64K but
4243 we need to ensure that it fits within the smb */
4245 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4246 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4248 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4250 pSMB->TotalDataCount = pSMB->DataCount;
4251 pSMB->ParameterCount = cpu_to_le16(params);
4252 pSMB->TotalParameterCount = pSMB->ParameterCount;
4253 pSMB->Reserved4 = 0;
4254 pSMB->hdr.smb_buf_length += byte_count;
4255 pSMB->ByteCount = cpu_to_le16(byte_count);
4256 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4257 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4259 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4262 cifs_buf_release(pSMB);