4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * Contains the routines for constructing the SMB PDUs themselves
9 * This library is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published
11 * by the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* SMB/CIFS PDU handling routines here - except for leftovers in connect.c */
25 /* These are mostly routines that operate on a pathname, or on a tree id */
26 /* (mounted volume), but there are eight handle based routines which must be */
27 /* treated slightly different for reconnection purposes since we never want */
28 /* to reuse a stale file handle and the caller knows the file handle */
31 #include <linux/kernel.h>
32 #include <linux/vfs.h>
33 #include <linux/posix_acl_xattr.h>
34 #include <asm/uaccess.h>
37 #include "cifsproto.h"
38 #include "cifs_unicode.h"
39 #include "cifs_debug.h"
41 #ifdef CONFIG_CIFS_POSIX
46 {CIFS_PROT, "\2NT LM 0.12"},
47 {CIFS_PROT, "\2POSIX 2"},
55 {CIFS_PROT, "\2NT LM 0.12"},
61 /* Mark as invalid, all open files on tree connections since they
62 were closed when session to server was lost */
63 static void mark_open_files_invalid(struct cifsTconInfo * pTcon)
65 struct cifsFileInfo *open_file = NULL;
66 struct list_head * tmp;
67 struct list_head * tmp1;
69 /* list all files open on tree connection and mark them invalid */
70 write_lock(&GlobalSMBSeslock);
71 list_for_each_safe(tmp, tmp1, &pTcon->openFileList) {
72 open_file = list_entry(tmp,struct cifsFileInfo, tlist);
74 open_file->invalidHandle = TRUE;
77 write_unlock(&GlobalSMBSeslock);
78 /* BB Add call to invalidate_inodes(sb) for all superblocks mounted
82 /* If the return code is zero, this function must fill in request_buf pointer */
84 small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
85 void **request_buf /* returned */)
89 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
90 check for tcp and smb session status done differently
91 for those three - in the calling routine */
93 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
95 struct nls_table *nls_codepage;
96 /* Give Demultiplex thread up to 10 seconds to
97 reconnect, should be greater than cifs socket
98 timeout which is 7 seconds */
99 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
100 wait_event_interruptible_timeout(tcon->ses->server->response_q,
101 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
102 if(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
103 /* on "soft" mounts we wait once */
104 if((tcon->retry == FALSE) ||
105 (tcon->ses->status == CifsExiting)) {
106 cFYI(1,("gave up waiting on reconnect in smb_init"));
108 } /* else "hard" mount - keep retrying
109 until process is killed or server
110 comes back on-line */
111 } else /* TCP session is reestablished now */
116 nls_codepage = load_nls_default();
117 /* need to prevent multiple threads trying to
118 simultaneously reconnect the same SMB session */
119 down(&tcon->ses->sesSem);
120 if(tcon->ses->status == CifsNeedReconnect)
121 rc = cifs_setup_session(0, tcon->ses,
123 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
124 mark_open_files_invalid(tcon);
125 rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon
127 up(&tcon->ses->sesSem);
129 atomic_inc(&tconInfoReconnectCount);
131 cFYI(1, ("reconnect tcon rc = %d", rc));
132 /* Removed call to reopen open files here -
133 it is safer (and faster) to reopen files
134 one at a time as needed in read and write */
136 /* Check if handle based operation so we
137 know whether we can continue or not without
138 returning to caller to reset file handle */
139 switch(smb_command) {
140 case SMB_COM_READ_ANDX:
141 case SMB_COM_WRITE_ANDX:
143 case SMB_COM_FIND_CLOSE2:
144 case SMB_COM_LOCKING_ANDX: {
145 unload_nls(nls_codepage);
150 up(&tcon->ses->sesSem);
152 unload_nls(nls_codepage);
161 *request_buf = cifs_small_buf_get();
162 if (*request_buf == NULL) {
163 /* BB should we add a retry in here if not a writepage? */
167 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,wct);
169 #ifdef CONFIG_CIFS_STATS
171 atomic_inc(&tcon->num_smbs_sent);
173 #endif /* CONFIG_CIFS_STATS */
177 /* If the return code is zero, this function must fill in request_buf pointer */
179 smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
180 void **request_buf /* returned */ ,
181 void **response_buf /* returned */ )
185 /* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so
186 check for tcp and smb session status done differently
187 for those three - in the calling routine */
189 if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
190 (tcon->ses->server)){
191 struct nls_table *nls_codepage;
192 /* Give Demultiplex thread up to 10 seconds to
193 reconnect, should be greater than cifs socket
194 timeout which is 7 seconds */
195 while(tcon->ses->server->tcpStatus == CifsNeedReconnect) {
196 wait_event_interruptible_timeout(tcon->ses->server->response_q,
197 (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ);
198 if(tcon->ses->server->tcpStatus ==
200 /* on "soft" mounts we wait once */
201 if((tcon->retry == FALSE) ||
202 (tcon->ses->status == CifsExiting)) {
203 cFYI(1,("gave up waiting on reconnect in smb_init"));
205 } /* else "hard" mount - keep retrying
206 until process is killed or server
208 } else /* TCP session is reestablished now */
213 nls_codepage = load_nls_default();
214 /* need to prevent multiple threads trying to
215 simultaneously reconnect the same SMB session */
216 down(&tcon->ses->sesSem);
217 if(tcon->ses->status == CifsNeedReconnect)
218 rc = cifs_setup_session(0, tcon->ses,
220 if(!rc && (tcon->tidStatus == CifsNeedReconnect)) {
221 mark_open_files_invalid(tcon);
222 rc = CIFSTCon(0, tcon->ses, tcon->treeName,
224 up(&tcon->ses->sesSem);
226 atomic_inc(&tconInfoReconnectCount);
228 cFYI(1, ("reconnect tcon rc = %d", rc));
229 /* Removed call to reopen open files here -
230 it is safer (and faster) to reopen files
231 one at a time as needed in read and write */
233 /* Check if handle based operation so we
234 know whether we can continue or not without
235 returning to caller to reset file handle */
236 switch(smb_command) {
237 case SMB_COM_READ_ANDX:
238 case SMB_COM_WRITE_ANDX:
240 case SMB_COM_FIND_CLOSE2:
241 case SMB_COM_LOCKING_ANDX: {
242 unload_nls(nls_codepage);
247 up(&tcon->ses->sesSem);
249 unload_nls(nls_codepage);
258 *request_buf = cifs_buf_get();
259 if (*request_buf == NULL) {
260 /* BB should we add a retry in here if not a writepage? */
263 /* Although the original thought was we needed the response buf for */
264 /* potential retries of smb operations it turns out we can determine */
265 /* from the mid flags when the request buffer can be resent without */
266 /* having to use a second distinct buffer for the response */
267 *response_buf = *request_buf;
269 header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
272 #ifdef CONFIG_CIFS_STATS
274 atomic_inc(&tcon->num_smbs_sent);
276 #endif /* CONFIG_CIFS_STATS */
280 static int validate_t2(struct smb_t2_rsp * pSMB)
286 /* check for plausible wct, bcc and t2 data and parm sizes */
287 /* check for parm and data offset going beyond end of smb */
288 if(pSMB->hdr.WordCount >= 10) {
289 if((le16_to_cpu(pSMB->t2_rsp.ParameterOffset) <= 1024) &&
290 (le16_to_cpu(pSMB->t2_rsp.DataOffset) <= 1024)) {
291 /* check that bcc is at least as big as parms + data */
292 /* check that bcc is less than negotiated smb buffer */
293 total_size = le16_to_cpu(pSMB->t2_rsp.ParameterCount);
294 if(total_size < 512) {
295 total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount);
296 /* BCC le converted in SendReceive */
297 pBCC = (pSMB->hdr.WordCount * 2) +
298 sizeof(struct smb_hdr) +
300 if((total_size <= (*(u16 *)pBCC)) &&
302 CIFSMaxBufSize+MAX_CIFS_HDR_SIZE)) {
309 cifs_dump_mem("Invalid transact2 SMB: ",(char *)pSMB,
310 sizeof(struct smb_t2_rsp) + 16);
314 CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
317 NEGOTIATE_RSP *pSMBr;
320 struct TCP_Server_Info * server;
324 server = ses->server;
329 rc = smb_init(SMB_COM_NEGOTIATE, 0, NULL /* no tcon yet */ ,
330 (void **) &pSMB, (void **) &pSMBr);
333 pSMB->hdr.Mid = GetNextMid(server);
334 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
335 if (extended_security)
336 pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
338 count = strlen(protocols[0].name) + 1;
339 strncpy(pSMB->DialectsArray, protocols[0].name, 30);
340 /* null guaranteed to be at end of source and target buffers anyway */
342 pSMB->hdr.smb_buf_length += count;
343 pSMB->ByteCount = cpu_to_le16(count);
345 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
346 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
348 server->secMode = pSMBr->SecurityMode;
349 server->secType = NTLM; /* BB override default for
350 NTLMv2 or kerberos v5 */
351 /* one byte - no need to convert this or EncryptionKeyLen
352 from little endian */
353 server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
354 /* probably no need to store and check maxvcs */
356 min(le32_to_cpu(pSMBr->MaxBufferSize),
357 (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
358 server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
359 cFYI(0, ("Max buf = %d ", ses->server->maxBuf));
360 GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
361 server->capabilities = le32_to_cpu(pSMBr->Capabilities);
362 server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);
363 /* BB with UTC do we ever need to be using srvr timezone? */
364 if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
365 memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
366 CIFS_CRYPTO_KEY_SIZE);
367 } else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
368 && (pSMBr->EncryptionKeyLength == 0)) {
369 /* decode security blob */
373 /* BB might be helpful to save off the domain of server here */
375 if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) &&
376 (server->capabilities & CAP_EXTENDED_SECURITY)) {
377 count = pSMBr->ByteCount;
380 else if (count == 16) {
381 server->secType = RawNTLMSSP;
382 if (server->socketUseCount.counter > 1) {
384 (server->server_GUID,
385 pSMBr->u.extended_response.
388 ("UID of server does not match previous connection to same ip address"));
396 memcpy(server->server_GUID,
397 pSMBr->u.extended_response.
400 rc = decode_negTokenInit(pSMBr->u.
406 /* BB Need to fill struct for sessetup here */
413 server->capabilities &= ~CAP_EXTENDED_SECURITY;
414 if(sign_CIFS_PDUs == FALSE) {
415 if(server->secMode & SECMODE_SIGN_REQUIRED)
417 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
418 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
419 } else if(sign_CIFS_PDUs == 1) {
420 if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
421 server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
426 cifs_buf_release(pSMB);
431 CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon)
433 struct smb_hdr *smb_buffer;
434 struct smb_hdr *smb_buffer_response; /* BB removeme BB */
438 cFYI(1, ("In tree disconnect"));
440 * If last user of the connection and
441 * connection alive - disconnect it
442 * If this is the last connection on the server session disconnect it
443 * (and inside session disconnect we should check if tcp socket needs
444 * to be freed and kernel thread woken up).
447 down(&tcon->tconSem);
451 atomic_dec(&tcon->useCount);
452 if (atomic_read(&tcon->useCount) > 0) {
457 /* No need to return error on this operation if tid invalidated and
458 closed on server already e.g. due to tcp session crashing */
459 if(tcon->tidStatus == CifsNeedReconnect) {
464 if((tcon->ses == NULL) || (tcon->ses->server == NULL)) {
468 rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon,
469 (void **)&smb_buffer);
474 smb_buffer_response = smb_buffer; /* BB removeme BB */
476 rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response,
479 cFYI(1, ("Tree disconnect failed %d", rc));
482 cifs_small_buf_release(smb_buffer);
485 /* No need to return error on this operation if tid invalidated and
486 closed on server already e.g. due to tcp session crashing */
494 CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
496 struct smb_hdr *smb_buffer_response;
497 LOGOFF_ANDX_REQ *pSMB;
501 cFYI(1, ("In SMBLogoff for session disconnect"));
507 atomic_dec(&ses->inUse);
508 if (atomic_read(&ses->inUse) > 0) {
512 rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB);
518 smb_buffer_response = (struct smb_hdr *)pSMB; /* BB removeme BB */
521 pSMB->hdr.Mid = GetNextMid(ses->server);
523 if(ses->server->secMode &
524 (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
525 pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
528 pSMB->hdr.Uid = ses->Suid;
530 pSMB->AndXCommand = 0xFF;
531 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
532 smb_buffer_response, &length, 0);
534 atomic_dec(&ses->server->socketUseCount);
535 if (atomic_read(&ses->server->socketUseCount) == 0) {
536 spin_lock(&GlobalMid_Lock);
537 ses->server->tcpStatus = CifsExiting;
538 spin_unlock(&GlobalMid_Lock);
543 cifs_small_buf_release(pSMB);
545 /* if session dead then we do not need to do ulogoff,
546 since server closed smb session, no sense reporting
554 CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName,
555 const struct nls_table *nls_codepage, int remap)
557 DELETE_FILE_REQ *pSMB = NULL;
558 DELETE_FILE_RSP *pSMBr = NULL;
564 rc = smb_init(SMB_COM_DELETE, 1, tcon, (void **) &pSMB,
569 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
571 cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
572 PATH_MAX, nls_codepage, remap);
573 name_len++; /* trailing null */
575 } else { /* BB improve check for buffer overruns BB */
576 name_len = strnlen(fileName, PATH_MAX);
577 name_len++; /* trailing null */
578 strncpy(pSMB->fileName, fileName, name_len);
580 pSMB->SearchAttributes =
581 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM);
582 pSMB->BufferFormat = 0x04;
583 pSMB->hdr.smb_buf_length += name_len + 1;
584 pSMB->ByteCount = cpu_to_le16(name_len + 1);
585 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
586 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
587 #ifdef CONFIG_CIFS_STATS
588 atomic_inc(&tcon->num_deletes);
591 cFYI(1, ("Error in RMFile = %d", rc));
594 cifs_buf_release(pSMB);
602 CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName,
603 const struct nls_table *nls_codepage, int remap)
605 DELETE_DIRECTORY_REQ *pSMB = NULL;
606 DELETE_DIRECTORY_RSP *pSMBr = NULL;
611 cFYI(1, ("In CIFSSMBRmDir"));
613 rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB,
618 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
619 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName,
620 PATH_MAX, nls_codepage, remap);
621 name_len++; /* trailing null */
623 } else { /* BB improve check for buffer overruns BB */
624 name_len = strnlen(dirName, PATH_MAX);
625 name_len++; /* trailing null */
626 strncpy(pSMB->DirName, dirName, name_len);
629 pSMB->BufferFormat = 0x04;
630 pSMB->hdr.smb_buf_length += name_len + 1;
631 pSMB->ByteCount = cpu_to_le16(name_len + 1);
632 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
633 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
634 #ifdef CONFIG_CIFS_STATS
635 atomic_inc(&tcon->num_rmdirs);
638 cFYI(1, ("Error in RMDir = %d", rc));
641 cifs_buf_release(pSMB);
648 CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon,
649 const char *name, const struct nls_table *nls_codepage, int remap)
652 CREATE_DIRECTORY_REQ *pSMB = NULL;
653 CREATE_DIRECTORY_RSP *pSMBr = NULL;
657 cFYI(1, ("In CIFSSMBMkDir"));
659 rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB,
664 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
665 name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
666 PATH_MAX, nls_codepage, remap);
667 name_len++; /* trailing null */
669 } else { /* BB improve check for buffer overruns BB */
670 name_len = strnlen(name, PATH_MAX);
671 name_len++; /* trailing null */
672 strncpy(pSMB->DirName, name, name_len);
675 pSMB->BufferFormat = 0x04;
676 pSMB->hdr.smb_buf_length += name_len + 1;
677 pSMB->ByteCount = cpu_to_le16(name_len + 1);
678 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
679 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
680 #ifdef CONFIG_CIFS_STATS
681 atomic_inc(&tcon->num_mkdirs);
684 cFYI(1, ("Error in Mkdir = %d", rc));
687 cifs_buf_release(pSMB);
694 CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon,
695 const char *fileName, const int openDisposition,
696 const int access_flags, const int create_options, __u16 * netfid,
697 int *pOplock, FILE_ALL_INFO * pfile_info,
698 const struct nls_table *nls_codepage, int remap)
701 OPEN_REQ *pSMB = NULL;
702 OPEN_RSP *pSMBr = NULL;
708 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB,
713 pSMB->AndXCommand = 0xFF; /* none */
715 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
716 count = 1; /* account for one byte pad to word boundary */
718 cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
719 fileName, PATH_MAX, nls_codepage, remap);
720 name_len++; /* trailing null */
722 pSMB->NameLength = cpu_to_le16(name_len);
723 } else { /* BB improve check for buffer overruns BB */
724 count = 0; /* no pad */
725 name_len = strnlen(fileName, PATH_MAX);
726 name_len++; /* trailing null */
727 pSMB->NameLength = cpu_to_le16(name_len);
728 strncpy(pSMB->fileName, fileName, name_len);
730 if (*pOplock & REQ_OPLOCK)
731 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK);
732 else if (*pOplock & REQ_BATCHOPLOCK) {
733 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
735 pSMB->DesiredAccess = cpu_to_le32(access_flags);
736 pSMB->AllocationSize = 0;
737 /* set file as system file if special file such
738 as fifo and server expecting SFU style and
739 no Unix extensions */
740 if(create_options & CREATE_OPTION_SPECIAL)
741 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
743 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL);
744 /* XP does not handle ATTR_POSIX_SEMANTICS */
745 /* but it helps speed up case sensitive checks for other
746 servers such as Samba */
747 if (tcon->ses->capabilities & CAP_UNIX)
748 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
750 /* if ((omode & S_IWUGO) == 0)
751 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY);*/
752 /* Above line causes problems due to vfs splitting create into two
753 pieces - need to set mode after file created not while it is
755 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
756 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
757 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
758 /* BB Expirement with various impersonation levels and verify */
759 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
760 pSMB->SecurityFlags =
761 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
764 pSMB->hdr.smb_buf_length += count;
766 pSMB->ByteCount = cpu_to_le16(count);
767 /* long_op set to 1 to allow for oplock break timeouts */
768 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
769 (struct smb_hdr *) pSMBr, &bytes_returned, 1);
770 #ifdef CONFIG_CIFS_STATS
771 atomic_inc(&tcon->num_opens);
774 cFYI(1, ("Error in Open = %d", rc));
776 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */
777 *netfid = pSMBr->Fid; /* cifs fid stays in le */
778 /* Let caller know file was created so we can set the mode. */
779 /* Do we care about the CreateAction in any other cases? */
780 if(cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
781 *pOplock |= CIFS_CREATE_ACTION;
783 memcpy((char *)pfile_info,(char *)&pSMBr->CreationTime,
784 36 /* CreationTime to Attributes */);
785 /* the file_info buf is endian converted by caller */
786 pfile_info->AllocationSize = pSMBr->AllocationSize;
787 pfile_info->EndOfFile = pSMBr->EndOfFile;
788 pfile_info->NumberOfLinks = cpu_to_le32(1);
792 cifs_buf_release(pSMB);
798 /* If no buffer passed in, then caller wants to do the copy
799 as in the case of readpages so the SMB buffer must be
800 freed by the caller */
803 CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
804 const int netfid, const unsigned int count,
805 const __u64 lseek, unsigned int *nbytes, char **buf)
808 READ_REQ *pSMB = NULL;
809 READ_RSP *pSMBr = NULL;
810 char *pReadData = NULL;
813 cFYI(1,("Reading %d bytes on fid %d",count,netfid));
816 rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
821 /* tcon and ses pointer are checked in smb_init */
822 if (tcon->ses->server == NULL)
823 return -ECONNABORTED;
825 pSMB->AndXCommand = 0xFF; /* none */
827 pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
828 pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
830 pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
831 pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
832 pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */
834 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
835 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
836 #ifdef CONFIG_CIFS_STATS
837 atomic_inc(&tcon->num_reads);
840 cERROR(1, ("Send error in read = %d", rc));
842 int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
843 data_length = data_length << 16;
844 data_length += le16_to_cpu(pSMBr->DataLength);
845 *nbytes = data_length;
847 /*check that DataLength would not go beyond end of SMB */
848 if ((data_length > CIFSMaxBufSize)
849 || (data_length > count)) {
850 cFYI(1,("bad length %d for count %d",data_length,count));
855 (char *) (&pSMBr->hdr.Protocol) +
856 le16_to_cpu(pSMBr->DataOffset);
857 /* if(rc = copy_to_user(buf, pReadData, data_length)) {
858 cERROR(1,("Faulting on read rc = %d",rc));
860 }*/ /* can not use copy_to_user when using page cache*/
862 memcpy(*buf,pReadData,data_length);
866 cifs_buf_release(pSMB);
870 /* Note: On -EAGAIN error only caller can retry on handle based calls
871 since file handle passed in no longer valid */
876 CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
877 const int netfid, const unsigned int count,
878 const __u64 offset, unsigned int *nbytes, const char *buf,
879 const char __user * ubuf, const int long_op)
882 WRITE_REQ *pSMB = NULL;
883 WRITE_RSP *pSMBr = NULL;
888 /* cFYI(1,("write at %lld %d bytes",offset,count));*/
889 rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
893 /* tcon and ses pointer are checked in smb_init */
894 if (tcon->ses->server == NULL)
895 return -ECONNABORTED;
897 pSMB->AndXCommand = 0xFF; /* none */
899 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
900 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
901 pSMB->Reserved = 0xFFFFFFFF;
905 /* Can increase buffer size if buffer is big enough in some cases - ie we
906 can send more if LARGE_WRITE_X capability returned by the server and if
907 our buffer is big enough or if we convert to iovecs on socket writes
908 and eliminate the copy to the CIFS buffer */
909 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
910 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
912 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
916 if (bytes_sent > count)
919 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
921 memcpy(pSMB->Data,buf,bytes_sent);
923 if(copy_from_user(pSMB->Data,ubuf,bytes_sent)) {
924 cifs_buf_release(pSMB);
929 cifs_buf_release(pSMB);
933 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
934 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
935 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
936 pSMB->hdr.smb_buf_length += bytes_sent+1;
937 pSMB->ByteCount = cpu_to_le16(byte_count);
939 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
940 (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
941 #ifdef CONFIG_CIFS_STATS
942 atomic_inc(&tcon->num_writes);
945 cFYI(1, ("Send error in write = %d", rc));
948 *nbytes = le16_to_cpu(pSMBr->CountHigh);
949 *nbytes = (*nbytes) << 16;
950 *nbytes += le16_to_cpu(pSMBr->Count);
953 cifs_buf_release(pSMB);
955 /* Note: On -EAGAIN error only caller can retry on handle based calls
956 since file handle passed in no longer valid */
961 #ifdef CONFIG_CIFS_EXPERIMENTAL
963 CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
964 const int netfid, const unsigned int count,
965 const __u64 offset, unsigned int *nbytes, const char *buf,
969 WRITE_REQ *pSMB = NULL;
975 cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
976 rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
979 /* tcon and ses pointer are checked in smb_init */
980 if (tcon->ses->server == NULL)
981 return -ECONNABORTED;
983 pSMB->AndXCommand = 0xFF; /* none */
985 pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
986 pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
987 pSMB->Reserved = 0xFFFFFFFF;
991 /* Can increase buffer size if buffer is big enough in some cases - ie
992 can send more if LARGE_WRITE_X capability returned by the server and if
993 our buffer is big enough or if we convert to iovecs on socket writes
994 and eliminate the copy to the CIFS buffer */
995 if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
996 bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
998 bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
1002 if (bytes_sent > count)
1005 cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
1007 byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
1008 pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
1009 pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
1010 smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
1011 pSMB->hdr.smb_buf_length += bytes_sent+1;
1012 pSMB->ByteCount = cpu_to_le16(byte_count);
1014 rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
1015 buf, bytes_sent, &bytes_returned, long_op);
1016 #ifdef CONFIG_CIFS_STATS
1017 atomic_inc(&tcon->num_writes);
1020 cFYI(1, ("Send error in write = %d", rc));
1023 WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
1024 *nbytes = le16_to_cpu(pSMBr->CountHigh);
1025 *nbytes = (*nbytes) << 16;
1026 *nbytes += le16_to_cpu(pSMBr->Count);
1029 cifs_small_buf_release(pSMB);
1031 /* Note: On -EAGAIN error only caller can retry on handle based calls
1032 since file handle passed in no longer valid */
1038 #endif /* CIFS_EXPERIMENTAL */
1041 CIFSSMBLock(const int xid, struct cifsTconInfo *tcon,
1042 const __u16 smb_file_id, const __u64 len,
1043 const __u64 offset, const __u32 numUnlock,
1044 const __u32 numLock, const __u8 lockType, const int waitFlag)
1047 LOCK_REQ *pSMB = NULL;
1048 LOCK_RSP *pSMBr = NULL;
1053 cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock));
1054 rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB);
1059 pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */
1061 if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) {
1062 timeout = -1; /* no response expected */
1064 } else if (waitFlag == TRUE) {
1065 timeout = 3; /* blocking operation, no timeout */
1066 pSMB->Timeout = cpu_to_le32(-1);/* blocking - do not time out */
1071 pSMB->NumberOfLocks = cpu_to_le16(numLock);
1072 pSMB->NumberOfUnlocks = cpu_to_le16(numUnlock);
1073 pSMB->LockType = lockType;
1074 pSMB->AndXCommand = 0xFF; /* none */
1075 pSMB->Fid = smb_file_id; /* netfid stays le */
1077 if((numLock != 0) || (numUnlock != 0)) {
1078 pSMB->Locks[0].Pid = cpu_to_le16(current->tgid);
1079 /* BB where to store pid high? */
1080 pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len);
1081 pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32));
1082 pSMB->Locks[0].OffsetLow = cpu_to_le32((u32)offset);
1083 pSMB->Locks[0].OffsetHigh = cpu_to_le32((u32)(offset>>32));
1084 count = sizeof(LOCKING_ANDX_RANGE);
1089 pSMB->hdr.smb_buf_length += count;
1090 pSMB->ByteCount = cpu_to_le16(count);
1092 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1093 (struct smb_hdr *) pSMBr, &bytes_returned, timeout);
1094 #ifdef CONFIG_CIFS_STATS
1095 atomic_inc(&tcon->num_locks);
1098 cFYI(1, ("Send error in Lock = %d", rc));
1100 cifs_small_buf_release(pSMB);
1102 /* Note: On -EAGAIN error only caller can retry on handle based calls
1103 since file handle passed in no longer valid */
1108 CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id)
1111 CLOSE_REQ *pSMB = NULL;
1112 CLOSE_RSP *pSMBr = NULL;
1114 cFYI(1, ("In CIFSSMBClose"));
1116 /* do not retry on dead session on close */
1117 rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB);
1123 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
1125 pSMB->FileID = (__u16) smb_file_id;
1126 pSMB->LastWriteTime = 0;
1127 pSMB->ByteCount = 0;
1128 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1129 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1130 #ifdef CONFIG_CIFS_STATS
1131 atomic_inc(&tcon->num_closes);
1135 /* EINTR is expected when user ctl-c to kill app */
1136 cERROR(1, ("Send error in Close = %d", rc));
1140 cifs_small_buf_release(pSMB);
1142 /* Since session is dead, file will be closed on server already */
1150 CIFSSMBRename(const int xid, struct cifsTconInfo *tcon,
1151 const char *fromName, const char *toName,
1152 const struct nls_table *nls_codepage, int remap)
1155 RENAME_REQ *pSMB = NULL;
1156 RENAME_RSP *pSMBr = NULL;
1158 int name_len, name_len2;
1161 cFYI(1, ("In CIFSSMBRename"));
1163 rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB,
1168 pSMB->BufferFormat = 0x04;
1169 pSMB->SearchAttributes =
1170 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1173 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1175 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1176 PATH_MAX, nls_codepage, remap);
1177 name_len++; /* trailing null */
1179 pSMB->OldFileName[name_len] = 0x04; /* pad */
1180 /* protocol requires ASCII signature byte on Unicode string */
1181 pSMB->OldFileName[name_len + 1] = 0x00;
1183 cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
1184 toName, PATH_MAX, nls_codepage, remap);
1185 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1186 name_len2 *= 2; /* convert to bytes */
1187 } else { /* BB improve the check for buffer overruns BB */
1188 name_len = strnlen(fromName, PATH_MAX);
1189 name_len++; /* trailing null */
1190 strncpy(pSMB->OldFileName, fromName, name_len);
1191 name_len2 = strnlen(toName, PATH_MAX);
1192 name_len2++; /* trailing null */
1193 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1194 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1195 name_len2++; /* trailing null */
1196 name_len2++; /* signature byte */
1199 count = 1 /* 1st signature byte */ + name_len + name_len2;
1200 pSMB->hdr.smb_buf_length += count;
1201 pSMB->ByteCount = cpu_to_le16(count);
1203 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1204 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1205 #ifdef CONFIG_CIFS_STATS
1206 atomic_inc(&tcon->num_renames);
1209 cFYI(1, ("Send error in rename = %d", rc));
1212 cifs_buf_release(pSMB);
1220 int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
1221 int netfid, char * target_name,
1222 const struct nls_table * nls_codepage, int remap)
1224 struct smb_com_transaction2_sfi_req *pSMB = NULL;
1225 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
1226 struct set_file_rename * rename_info;
1228 char dummy_string[30];
1230 int bytes_returned = 0;
1232 __u16 params, param_offset, offset, count, byte_count;
1234 cFYI(1, ("Rename to File by handle"));
1235 rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB,
1241 pSMB->MaxSetupCount = 0;
1245 pSMB->Reserved2 = 0;
1246 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
1247 offset = param_offset + params;
1249 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1250 rename_info = (struct set_file_rename *) data_offset;
1251 pSMB->MaxParameterCount = cpu_to_le16(2);
1252 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
1253 pSMB->SetupCount = 1;
1254 pSMB->Reserved3 = 0;
1255 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
1256 byte_count = 3 /* pad */ + params;
1257 pSMB->ParameterCount = cpu_to_le16(params);
1258 pSMB->TotalParameterCount = pSMB->ParameterCount;
1259 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1260 pSMB->DataOffset = cpu_to_le16(offset);
1261 /* construct random name ".cifs_tmp<inodenum><mid>" */
1262 rename_info->overwrite = cpu_to_le32(1);
1263 rename_info->root_fid = 0;
1264 /* unicode only call */
1265 if(target_name == NULL) {
1266 sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
1267 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1268 dummy_string, 24, nls_codepage, remap);
1270 len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
1271 target_name, PATH_MAX, nls_codepage, remap);
1273 rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
1274 count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2;
1275 byte_count += count;
1276 pSMB->DataCount = cpu_to_le16(count);
1277 pSMB->TotalDataCount = pSMB->DataCount;
1279 pSMB->InformationLevel =
1280 cpu_to_le16(SMB_SET_FILE_RENAME_INFORMATION);
1281 pSMB->Reserved4 = 0;
1282 pSMB->hdr.smb_buf_length += byte_count;
1283 pSMB->ByteCount = cpu_to_le16(byte_count);
1284 rc = SendReceive(xid, pTcon->ses, (struct smb_hdr *) pSMB,
1285 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1286 #ifdef CONFIG_CIFS_STATS
1287 atomic_inc(&pTcon->num_t2renames);
1290 cFYI(1,("Send error in Rename (by file handle) = %d", rc));
1293 cifs_buf_release(pSMB);
1295 /* Note: On -EAGAIN error only caller can retry on handle based calls
1296 since file handle passed in no longer valid */
1302 CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName,
1303 const __u16 target_tid, const char *toName, const int flags,
1304 const struct nls_table *nls_codepage, int remap)
1307 COPY_REQ *pSMB = NULL;
1308 COPY_RSP *pSMBr = NULL;
1310 int name_len, name_len2;
1313 cFYI(1, ("In CIFSSMBCopy"));
1315 rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB,
1320 pSMB->BufferFormat = 0x04;
1321 pSMB->Tid2 = target_tid;
1323 pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
1325 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1326 name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
1327 fromName, PATH_MAX, nls_codepage,
1329 name_len++; /* trailing null */
1331 pSMB->OldFileName[name_len] = 0x04; /* pad */
1332 /* protocol requires ASCII signature byte on Unicode string */
1333 pSMB->OldFileName[name_len + 1] = 0x00;
1334 name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1335 toName, PATH_MAX, nls_codepage, remap);
1336 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1337 name_len2 *= 2; /* convert to bytes */
1338 } else { /* BB improve the check for buffer overruns BB */
1339 name_len = strnlen(fromName, PATH_MAX);
1340 name_len++; /* trailing null */
1341 strncpy(pSMB->OldFileName, fromName, name_len);
1342 name_len2 = strnlen(toName, PATH_MAX);
1343 name_len2++; /* trailing null */
1344 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1345 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1346 name_len2++; /* trailing null */
1347 name_len2++; /* signature byte */
1350 count = 1 /* 1st signature byte */ + name_len + name_len2;
1351 pSMB->hdr.smb_buf_length += count;
1352 pSMB->ByteCount = cpu_to_le16(count);
1354 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1355 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1357 cFYI(1, ("Send error in copy = %d with %d files copied",
1358 rc, le16_to_cpu(pSMBr->CopyCount)));
1361 cifs_buf_release(pSMB);
1370 CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon,
1371 const char *fromName, const char *toName,
1372 const struct nls_table *nls_codepage)
1374 TRANSACTION2_SPI_REQ *pSMB = NULL;
1375 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1378 int name_len_target;
1380 int bytes_returned = 0;
1381 __u16 params, param_offset, offset, byte_count;
1383 cFYI(1, ("In Symlink Unix style"));
1385 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1390 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1392 cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
1393 /* find define for this maxpathcomponent */
1395 name_len++; /* trailing null */
1398 } else { /* BB improve the check for buffer overruns BB */
1399 name_len = strnlen(fromName, PATH_MAX);
1400 name_len++; /* trailing null */
1401 strncpy(pSMB->FileName, fromName, name_len);
1403 params = 6 + name_len;
1404 pSMB->MaxSetupCount = 0;
1408 pSMB->Reserved2 = 0;
1409 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1410 InformationLevel) - 4;
1411 offset = param_offset + params;
1413 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1414 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1416 cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
1417 /* find define for this maxpathcomponent */
1419 name_len_target++; /* trailing null */
1420 name_len_target *= 2;
1421 } else { /* BB improve the check for buffer overruns BB */
1422 name_len_target = strnlen(toName, PATH_MAX);
1423 name_len_target++; /* trailing null */
1424 strncpy(data_offset, toName, name_len_target);
1427 pSMB->MaxParameterCount = cpu_to_le16(2);
1428 /* BB find exact max on data count below from sess */
1429 pSMB->MaxDataCount = cpu_to_le16(1000);
1430 pSMB->SetupCount = 1;
1431 pSMB->Reserved3 = 0;
1432 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1433 byte_count = 3 /* pad */ + params + name_len_target;
1434 pSMB->DataCount = cpu_to_le16(name_len_target);
1435 pSMB->ParameterCount = cpu_to_le16(params);
1436 pSMB->TotalDataCount = pSMB->DataCount;
1437 pSMB->TotalParameterCount = pSMB->ParameterCount;
1438 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1439 pSMB->DataOffset = cpu_to_le16(offset);
1440 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_LINK);
1441 pSMB->Reserved4 = 0;
1442 pSMB->hdr.smb_buf_length += byte_count;
1443 pSMB->ByteCount = cpu_to_le16(byte_count);
1444 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1445 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1446 #ifdef CONFIG_CIFS_STATS
1447 atomic_inc(&tcon->num_symlinks);
1451 ("Send error in SetPathInfo (create symlink) = %d",
1456 cifs_buf_release(pSMB);
1459 goto createSymLinkRetry;
1465 CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1466 const char *fromName, const char *toName,
1467 const struct nls_table *nls_codepage, int remap)
1469 TRANSACTION2_SPI_REQ *pSMB = NULL;
1470 TRANSACTION2_SPI_RSP *pSMBr = NULL;
1473 int name_len_target;
1475 int bytes_returned = 0;
1476 __u16 params, param_offset, offset, byte_count;
1478 cFYI(1, ("In Create Hard link Unix style"));
1479 createHardLinkRetry:
1480 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1485 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1486 name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
1487 PATH_MAX, nls_codepage, remap);
1488 name_len++; /* trailing null */
1491 } else { /* BB improve the check for buffer overruns BB */
1492 name_len = strnlen(toName, PATH_MAX);
1493 name_len++; /* trailing null */
1494 strncpy(pSMB->FileName, toName, name_len);
1496 params = 6 + name_len;
1497 pSMB->MaxSetupCount = 0;
1501 pSMB->Reserved2 = 0;
1502 param_offset = offsetof(struct smb_com_transaction2_spi_req,
1503 InformationLevel) - 4;
1504 offset = param_offset + params;
1506 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
1507 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1509 cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
1510 nls_codepage, remap);
1511 name_len_target++; /* trailing null */
1512 name_len_target *= 2;
1513 } else { /* BB improve the check for buffer overruns BB */
1514 name_len_target = strnlen(fromName, PATH_MAX);
1515 name_len_target++; /* trailing null */
1516 strncpy(data_offset, fromName, name_len_target);
1519 pSMB->MaxParameterCount = cpu_to_le16(2);
1520 /* BB find exact max on data count below from sess*/
1521 pSMB->MaxDataCount = cpu_to_le16(1000);
1522 pSMB->SetupCount = 1;
1523 pSMB->Reserved3 = 0;
1524 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
1525 byte_count = 3 /* pad */ + params + name_len_target;
1526 pSMB->ParameterCount = cpu_to_le16(params);
1527 pSMB->TotalParameterCount = pSMB->ParameterCount;
1528 pSMB->DataCount = cpu_to_le16(name_len_target);
1529 pSMB->TotalDataCount = pSMB->DataCount;
1530 pSMB->ParameterOffset = cpu_to_le16(param_offset);
1531 pSMB->DataOffset = cpu_to_le16(offset);
1532 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_HLINK);
1533 pSMB->Reserved4 = 0;
1534 pSMB->hdr.smb_buf_length += byte_count;
1535 pSMB->ByteCount = cpu_to_le16(byte_count);
1536 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1537 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1538 #ifdef CONFIG_CIFS_STATS
1539 atomic_inc(&tcon->num_hardlinks);
1542 cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc));
1545 cifs_buf_release(pSMB);
1547 goto createHardLinkRetry;
1553 CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon,
1554 const char *fromName, const char *toName,
1555 const struct nls_table *nls_codepage, int remap)
1558 NT_RENAME_REQ *pSMB = NULL;
1559 RENAME_RSP *pSMBr = NULL;
1561 int name_len, name_len2;
1564 cFYI(1, ("In CIFSCreateHardLink"));
1565 winCreateHardLinkRetry:
1567 rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB,
1572 pSMB->SearchAttributes =
1573 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
1575 pSMB->Flags = cpu_to_le16(CREATE_HARD_LINK);
1576 pSMB->ClusterCount = 0;
1578 pSMB->BufferFormat = 0x04;
1580 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1582 cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
1583 PATH_MAX, nls_codepage, remap);
1584 name_len++; /* trailing null */
1586 pSMB->OldFileName[name_len] = 0; /* pad */
1587 pSMB->OldFileName[name_len + 1] = 0x04;
1589 cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
1590 toName, PATH_MAX, nls_codepage, remap);
1591 name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
1592 name_len2 *= 2; /* convert to bytes */
1593 } else { /* BB improve the check for buffer overruns BB */
1594 name_len = strnlen(fromName, PATH_MAX);
1595 name_len++; /* trailing null */
1596 strncpy(pSMB->OldFileName, fromName, name_len);
1597 name_len2 = strnlen(toName, PATH_MAX);
1598 name_len2++; /* trailing null */
1599 pSMB->OldFileName[name_len] = 0x04; /* 2nd buffer format */
1600 strncpy(&pSMB->OldFileName[name_len + 1], toName, name_len2);
1601 name_len2++; /* trailing null */
1602 name_len2++; /* signature byte */
1605 count = 1 /* string type byte */ + name_len + name_len2;
1606 pSMB->hdr.smb_buf_length += count;
1607 pSMB->ByteCount = cpu_to_le16(count);
1609 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1610 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1611 #ifdef CONFIG_CIFS_STATS
1612 atomic_inc(&tcon->num_hardlinks);
1615 cFYI(1, ("Send error in hard link (NT rename) = %d", rc));
1617 cifs_buf_release(pSMB);
1619 goto winCreateHardLinkRetry;
1625 CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
1626 const unsigned char *searchName,
1627 char *symlinkinfo, const int buflen,
1628 const struct nls_table *nls_codepage)
1630 /* SMB_QUERY_FILE_UNIX_LINK */
1631 TRANSACTION2_QPI_REQ *pSMB = NULL;
1632 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1636 __u16 params, byte_count;
1638 cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
1641 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1646 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1648 cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
1649 /* find define for this maxpathcomponent */
1651 name_len++; /* trailing null */
1653 } else { /* BB improve the check for buffer overruns BB */
1654 name_len = strnlen(searchName, PATH_MAX);
1655 name_len++; /* trailing null */
1656 strncpy(pSMB->FileName, searchName, name_len);
1659 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1660 pSMB->TotalDataCount = 0;
1661 pSMB->MaxParameterCount = cpu_to_le16(2);
1662 /* BB find exact max data count below from sess structure BB */
1663 pSMB->MaxDataCount = cpu_to_le16(4000);
1664 pSMB->MaxSetupCount = 0;
1668 pSMB->Reserved2 = 0;
1669 pSMB->ParameterOffset = cpu_to_le16(offsetof(
1670 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
1671 pSMB->DataCount = 0;
1672 pSMB->DataOffset = 0;
1673 pSMB->SetupCount = 1;
1674 pSMB->Reserved3 = 0;
1675 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
1676 byte_count = params + 1 /* pad */ ;
1677 pSMB->TotalParameterCount = cpu_to_le16(params);
1678 pSMB->ParameterCount = pSMB->TotalParameterCount;
1679 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_LINK);
1680 pSMB->Reserved4 = 0;
1681 pSMB->hdr.smb_buf_length += byte_count;
1682 pSMB->ByteCount = cpu_to_le16(byte_count);
1684 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1685 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1687 cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc));
1689 /* decode response */
1691 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
1692 if (rc || (pSMBr->ByteCount < 2))
1693 /* BB also check enough total bytes returned */
1694 rc = -EIO; /* bad smb */
1696 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
1697 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
1699 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1700 name_len = UniStrnlen((wchar_t *) ((char *)
1701 &pSMBr->hdr.Protocol +data_offset),
1702 min_t(const int, buflen,count) / 2);
1703 /* BB FIXME investigate remapping reserved chars here */
1704 cifs_strfromUCS_le(symlinkinfo,
1705 (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
1707 name_len, nls_codepage);
1709 strncpy(symlinkinfo,
1710 (char *) &pSMBr->hdr.Protocol +
1712 min_t(const int, buflen, count));
1714 symlinkinfo[buflen] = 0;
1715 /* just in case so calling code does not go off the end of buffer */
1718 cifs_buf_release(pSMB);
1720 goto querySymLinkRetry;
1725 CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
1726 const unsigned char *searchName,
1727 char *symlinkinfo, const int buflen,__u16 fid,
1728 const struct nls_table *nls_codepage)
1733 struct smb_com_transaction_ioctl_req * pSMB;
1734 struct smb_com_transaction_ioctl_rsp * pSMBr;
1736 cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName));
1737 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
1742 pSMB->TotalParameterCount = 0 ;
1743 pSMB->TotalDataCount = 0;
1744 pSMB->MaxParameterCount = cpu_to_le32(2);
1745 /* BB find exact data count max from sess structure BB */
1746 pSMB->MaxDataCount = cpu_to_le32(4000);
1747 pSMB->MaxSetupCount = 4;
1749 pSMB->ParameterOffset = 0;
1750 pSMB->DataCount = 0;
1751 pSMB->DataOffset = 0;
1752 pSMB->SetupCount = 4;
1753 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
1754 pSMB->ParameterCount = pSMB->TotalParameterCount;
1755 pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT);
1756 pSMB->IsFsctl = 1; /* FSCTL */
1757 pSMB->IsRootFlag = 0;
1758 pSMB->Fid = fid; /* file handle always le */
1759 pSMB->ByteCount = 0;
1761 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
1762 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
1764 cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc));
1765 } else { /* decode response */
1766 __u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
1767 __u32 data_count = le32_to_cpu(pSMBr->DataCount);
1768 if ((pSMBr->ByteCount < 2) || (data_offset > 512))
1769 /* BB also check enough total bytes returned */
1770 rc = -EIO; /* bad smb */
1772 if(data_count && (data_count < 2048)) {
1773 char * end_of_smb = pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
1775 struct reparse_data * reparse_buf = (struct reparse_data *)
1776 ((char *)&pSMBr->hdr.Protocol + data_offset);
1777 if((char*)reparse_buf >= end_of_smb) {
1781 if((reparse_buf->LinkNamesBuf +
1782 reparse_buf->TargetNameOffset +
1783 reparse_buf->TargetNameLen) >
1785 cFYI(1,("reparse buf extended beyond SMB"));
1790 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
1791 name_len = UniStrnlen((wchar_t *)
1792 (reparse_buf->LinkNamesBuf +
1793 reparse_buf->TargetNameOffset),
1794 min(buflen/2, reparse_buf->TargetNameLen / 2));
1795 cifs_strfromUCS_le(symlinkinfo,
1796 (wchar_t *) (reparse_buf->LinkNamesBuf +
1797 reparse_buf->TargetNameOffset),
1798 name_len, nls_codepage);
1799 } else { /* ASCII names */
1800 strncpy(symlinkinfo,reparse_buf->LinkNamesBuf +
1801 reparse_buf->TargetNameOffset,
1802 min_t(const int, buflen, reparse_buf->TargetNameLen));
1806 cFYI(1,("Invalid return data count on get reparse info ioctl"));
1808 symlinkinfo[buflen] = 0; /* just in case so the caller
1809 does not go off the end of the buffer */
1810 cFYI(1,("readlink result - %s ",symlinkinfo));
1814 cifs_buf_release(pSMB);
1816 /* Note: On -EAGAIN error only caller can retry on handle based calls
1817 since file handle passed in no longer valid */
1822 #ifdef CONFIG_CIFS_POSIX
1824 /*Convert an Access Control Entry from wire format to local POSIX xattr format*/
1825 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
1827 /* u8 cifs fields do not need le conversion */
1828 ace->e_perm = (__u16)cifs_ace->cifs_e_perm;
1829 ace->e_tag = (__u16)cifs_ace->cifs_e_tag;
1830 ace->e_id = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
1831 /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
1836 /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */
1837 static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
1838 const int acl_type,const int size_of_data_area)
1843 struct cifs_posix_ace * pACE;
1844 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)src;
1845 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)trgt;
1847 if (le16_to_cpu(cifs_acl->version) != CIFS_ACL_VERSION)
1850 if(acl_type & ACL_TYPE_ACCESS) {
1851 count = le16_to_cpu(cifs_acl->access_entry_count);
1852 pACE = &cifs_acl->ace_array[0];
1853 size = sizeof(struct cifs_posix_acl);
1854 size += sizeof(struct cifs_posix_ace) * count;
1855 /* check if we would go beyond end of SMB */
1856 if(size_of_data_area < size) {
1857 cFYI(1,("bad CIFS POSIX ACL size %d vs. %d",size_of_data_area,size));
1860 } else if(acl_type & ACL_TYPE_DEFAULT) {
1861 count = le16_to_cpu(cifs_acl->access_entry_count);
1862 size = sizeof(struct cifs_posix_acl);
1863 size += sizeof(struct cifs_posix_ace) * count;
1864 /* skip past access ACEs to get to default ACEs */
1865 pACE = &cifs_acl->ace_array[count];
1866 count = le16_to_cpu(cifs_acl->default_entry_count);
1867 size += sizeof(struct cifs_posix_ace) * count;
1868 /* check if we would go beyond end of SMB */
1869 if(size_of_data_area < size)
1876 size = posix_acl_xattr_size(count);
1877 if((buflen == 0) || (local_acl == NULL)) {
1878 /* used to query ACL EA size */
1879 } else if(size > buflen) {
1881 } else /* buffer big enough */ {
1882 local_acl->a_version = POSIX_ACL_XATTR_VERSION;
1883 for(i = 0;i < count ;i++) {
1884 cifs_convert_ace(&local_acl->a_entries[i],pACE);
1891 static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
1892 const posix_acl_xattr_entry * local_ace)
1894 __u16 rc = 0; /* 0 = ACL converted ok */
1896 cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
1897 cifs_ace->cifs_e_tag = (__u8)cpu_to_le16(local_ace->e_tag);
1898 /* BB is there a better way to handle the large uid? */
1899 if(local_ace->e_id == -1) {
1900 /* Probably no need to le convert -1 on any arch but can not hurt */
1901 cifs_ace->cifs_uid = cpu_to_le64(-1);
1903 cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
1904 /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
1908 /* Convert ACL from local Linux POSIX xattr to CIFS POSIX ACL wire format */
1909 static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int buflen,
1913 struct cifs_posix_acl * cifs_acl = (struct cifs_posix_acl *)parm_data;
1914 posix_acl_xattr_header * local_acl = (posix_acl_xattr_header *)pACL;
1918 if((buflen == 0) || (pACL == NULL) || (cifs_acl == NULL))
1921 count = posix_acl_xattr_count((size_t)buflen);
1922 cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
1923 count,buflen,local_acl->a_version));
1924 if(local_acl->a_version != 2) {
1925 cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
1928 cifs_acl->version = cpu_to_le16(1);
1929 if(acl_type == ACL_TYPE_ACCESS)
1930 cifs_acl->access_entry_count = count;
1931 else if(acl_type == ACL_TYPE_DEFAULT)
1932 cifs_acl->default_entry_count = count;
1934 cFYI(1,("unknown ACL type %d",acl_type));
1937 for(i=0;i<count;i++) {
1938 rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
1939 &local_acl->a_entries[i]);
1941 /* ACE not converted */
1946 rc = (__u16)(count * sizeof(struct cifs_posix_ace));
1947 rc += sizeof(struct cifs_posix_acl);
1948 /* BB add check to make sure ACL does not overflow SMB */
1954 CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
1955 const unsigned char *searchName,
1956 char *acl_inf, const int buflen, const int acl_type,
1957 const struct nls_table *nls_codepage, int remap)
1959 /* SMB_QUERY_POSIX_ACL */
1960 TRANSACTION2_QPI_REQ *pSMB = NULL;
1961 TRANSACTION2_QPI_RSP *pSMBr = NULL;
1965 __u16 params, byte_count;
1967 cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName));
1970 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
1975 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
1977 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
1978 PATH_MAX, nls_codepage, remap);
1979 name_len++; /* trailing null */
1981 pSMB->FileName[name_len] = 0;
1982 pSMB->FileName[name_len+1] = 0;
1983 } else { /* BB improve the check for buffer overruns BB */
1984 name_len = strnlen(searchName, PATH_MAX);
1985 name_len++; /* trailing null */
1986 strncpy(pSMB->FileName, searchName, name_len);
1989 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
1990 pSMB->TotalDataCount = 0;
1991 pSMB->MaxParameterCount = cpu_to_le16(2);
1992 /* BB find exact max data count below from sess structure BB */
1993 pSMB->MaxDataCount = cpu_to_le16(4000);
1994 pSMB->MaxSetupCount = 0;
1998 pSMB->Reserved2 = 0;
1999 pSMB->ParameterOffset = cpu_to_le16(
2000 offsetof(struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2001 pSMB->DataCount = 0;
2002 pSMB->DataOffset = 0;
2003 pSMB->SetupCount = 1;
2004 pSMB->Reserved3 = 0;
2005 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2006 byte_count = params + 1 /* pad */ ;
2007 pSMB->TotalParameterCount = cpu_to_le16(params);
2008 pSMB->ParameterCount = pSMB->TotalParameterCount;
2009 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_ACL);
2010 pSMB->Reserved4 = 0;
2011 pSMB->hdr.smb_buf_length += byte_count;
2012 pSMB->ByteCount = cpu_to_le16(byte_count);
2014 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2015 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2017 cFYI(1, ("Send error in Query POSIX ACL = %d", rc));
2019 /* decode response */
2021 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2022 if (rc || (pSMBr->ByteCount < 2))
2023 /* BB also check enough total bytes returned */
2024 rc = -EIO; /* bad smb */
2026 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2027 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2028 rc = cifs_copy_posix_acl(acl_inf,
2029 (char *)&pSMBr->hdr.Protocol+data_offset,
2030 buflen,acl_type,count);
2033 cifs_buf_release(pSMB);
2040 CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon,
2041 const unsigned char *fileName,
2042 const char *local_acl, const int buflen,
2044 const struct nls_table *nls_codepage, int remap)
2046 struct smb_com_transaction2_spi_req *pSMB = NULL;
2047 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
2051 int bytes_returned = 0;
2052 __u16 params, byte_count, data_count, param_offset, offset;
2054 cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName));
2056 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2060 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2062 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
2063 PATH_MAX, nls_codepage, remap);
2064 name_len++; /* trailing null */
2066 } else { /* BB improve the check for buffer overruns BB */
2067 name_len = strnlen(fileName, PATH_MAX);
2068 name_len++; /* trailing null */
2069 strncpy(pSMB->FileName, fileName, name_len);
2071 params = 6 + name_len;
2072 pSMB->MaxParameterCount = cpu_to_le16(2);
2073 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
2074 pSMB->MaxSetupCount = 0;
2078 pSMB->Reserved2 = 0;
2079 param_offset = offsetof(struct smb_com_transaction2_spi_req,
2080 InformationLevel) - 4;
2081 offset = param_offset + params;
2082 parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
2083 pSMB->ParameterOffset = cpu_to_le16(param_offset);
2085 /* convert to on the wire format for POSIX ACL */
2086 data_count = ACL_to_cifs_posix(parm_data,local_acl,buflen,acl_type);
2088 if(data_count == 0) {
2090 goto setACLerrorExit;
2092 pSMB->DataOffset = cpu_to_le16(offset);
2093 pSMB->SetupCount = 1;
2094 pSMB->Reserved3 = 0;
2095 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
2096 pSMB->InformationLevel = cpu_to_le16(SMB_SET_POSIX_ACL);
2097 byte_count = 3 /* pad */ + params + data_count;
2098 pSMB->DataCount = cpu_to_le16(data_count);
2099 pSMB->TotalDataCount = pSMB->DataCount;
2100 pSMB->ParameterCount = cpu_to_le16(params);
2101 pSMB->TotalParameterCount = pSMB->ParameterCount;
2102 pSMB->Reserved4 = 0;
2103 pSMB->hdr.smb_buf_length += byte_count;
2104 pSMB->ByteCount = cpu_to_le16(byte_count);
2105 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2106 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2108 cFYI(1, ("Set POSIX ACL returned %d", rc));
2112 cifs_buf_release(pSMB);
2118 /* BB fix tabs in this function FIXME BB */
2120 CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
2121 const int netfid, __u64 * pExtAttrBits, __u64 *pMask)
2124 struct smb_t2_qfi_req *pSMB = NULL;
2125 struct smb_t2_qfi_rsp *pSMBr = NULL;
2127 __u16 params, byte_count;
2129 cFYI(1,("In GetExtAttr"));
2134 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2139 params = 2 /* level */ +2 /* fid */;
2140 pSMB->t2.TotalDataCount = 0;
2141 pSMB->t2.MaxParameterCount = cpu_to_le16(4);
2142 /* BB find exact max data count below from sess structure BB */
2143 pSMB->t2.MaxDataCount = cpu_to_le16(4000);
2144 pSMB->t2.MaxSetupCount = 0;
2145 pSMB->t2.Reserved = 0;
2147 pSMB->t2.Timeout = 0;
2148 pSMB->t2.Reserved2 = 0;
2149 pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req,
2151 pSMB->t2.DataCount = 0;
2152 pSMB->t2.DataOffset = 0;
2153 pSMB->t2.SetupCount = 1;
2154 pSMB->t2.Reserved3 = 0;
2155 pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION);
2156 byte_count = params + 1 /* pad */ ;
2157 pSMB->t2.TotalParameterCount = cpu_to_le16(params);
2158 pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount;
2159 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS);
2162 pSMB->hdr.smb_buf_length += byte_count;
2163 pSMB->t2.ByteCount = cpu_to_le16(byte_count);
2165 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2166 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2168 cFYI(1, ("error %d in GetExtAttr", rc));
2170 /* decode response */
2171 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2172 if (rc || (pSMBr->ByteCount < 2))
2173 /* BB also check enough total bytes returned */
2174 /* If rc should we check for EOPNOSUPP and
2175 disable the srvino flag? or in caller? */
2176 rc = -EIO; /* bad smb */
2178 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2179 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2180 struct file_chattr_info * pfinfo;
2181 /* BB Do we need a cast or hash here ? */
2183 cFYI(1, ("Illegal size ret in GetExtAttr"));
2187 pfinfo = (struct file_chattr_info *)
2188 (data_offset + (char *) &pSMBr->hdr.Protocol);
2189 *pExtAttrBits = le64_to_cpu(pfinfo->mode);
2190 *pMask = le64_to_cpu(pfinfo->mask);
2194 cifs_buf_release(pSMB);
2196 goto GetExtAttrRetry;
2201 #endif /* CONFIG_POSIX */
2204 CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon,
2205 const unsigned char *searchName,
2206 FILE_ALL_INFO * pFindData,
2207 const struct nls_table *nls_codepage, int remap)
2209 /* level 263 SMB_QUERY_FILE_ALL_INFO */
2210 TRANSACTION2_QPI_REQ *pSMB = NULL;
2211 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2215 __u16 params, byte_count;
2217 /* cFYI(1, ("In QPathInfo path %s", searchName)); */
2219 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2224 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2226 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2227 PATH_MAX, nls_codepage, remap);
2228 name_len++; /* trailing null */
2230 } else { /* BB improve the check for buffer overruns BB */
2231 name_len = strnlen(searchName, PATH_MAX);
2232 name_len++; /* trailing null */
2233 strncpy(pSMB->FileName, searchName, name_len);
2236 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2237 pSMB->TotalDataCount = 0;
2238 pSMB->MaxParameterCount = cpu_to_le16(2);
2239 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2240 pSMB->MaxSetupCount = 0;
2244 pSMB->Reserved2 = 0;
2245 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2246 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2247 pSMB->DataCount = 0;
2248 pSMB->DataOffset = 0;
2249 pSMB->SetupCount = 1;
2250 pSMB->Reserved3 = 0;
2251 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2252 byte_count = params + 1 /* pad */ ;
2253 pSMB->TotalParameterCount = cpu_to_le16(params);
2254 pSMB->ParameterCount = pSMB->TotalParameterCount;
2255 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_ALL_INFO);
2256 pSMB->Reserved4 = 0;
2257 pSMB->hdr.smb_buf_length += byte_count;
2258 pSMB->ByteCount = cpu_to_le16(byte_count);
2260 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2261 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2263 cFYI(1, ("Send error in QPathInfo = %d", rc));
2264 } else { /* decode response */
2265 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2267 if (rc || (pSMBr->ByteCount < 40))
2268 rc = -EIO; /* bad smb */
2269 else if (pFindData){
2270 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2271 memcpy((char *) pFindData,
2272 (char *) &pSMBr->hdr.Protocol +
2273 data_offset, sizeof (FILE_ALL_INFO));
2277 cifs_buf_release(pSMB);
2279 goto QPathInfoRetry;
2285 CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
2286 const unsigned char *searchName,
2287 FILE_UNIX_BASIC_INFO * pFindData,
2288 const struct nls_table *nls_codepage, int remap)
2290 /* SMB_QUERY_FILE_UNIX_BASIC */
2291 TRANSACTION2_QPI_REQ *pSMB = NULL;
2292 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2294 int bytes_returned = 0;
2296 __u16 params, byte_count;
2298 cFYI(1, ("In QPathInfo (Unix) the path %s", searchName));
2300 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2305 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2307 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2308 PATH_MAX, nls_codepage, remap);
2309 name_len++; /* trailing null */
2311 } else { /* BB improve the check for buffer overruns BB */
2312 name_len = strnlen(searchName, PATH_MAX);
2313 name_len++; /* trailing null */
2314 strncpy(pSMB->FileName, searchName, name_len);
2317 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
2318 pSMB->TotalDataCount = 0;
2319 pSMB->MaxParameterCount = cpu_to_le16(2);
2320 /* BB find exact max SMB PDU from sess structure BB */
2321 pSMB->MaxDataCount = cpu_to_le16(4000);
2322 pSMB->MaxSetupCount = 0;
2326 pSMB->Reserved2 = 0;
2327 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2328 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2329 pSMB->DataCount = 0;
2330 pSMB->DataOffset = 0;
2331 pSMB->SetupCount = 1;
2332 pSMB->Reserved3 = 0;
2333 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2334 byte_count = params + 1 /* pad */ ;
2335 pSMB->TotalParameterCount = cpu_to_le16(params);
2336 pSMB->ParameterCount = pSMB->TotalParameterCount;
2337 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC);
2338 pSMB->Reserved4 = 0;
2339 pSMB->hdr.smb_buf_length += byte_count;
2340 pSMB->ByteCount = cpu_to_le16(byte_count);
2342 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2343 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2345 cFYI(1, ("Send error in QPathInfo = %d", rc));
2346 } else { /* decode response */
2347 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2349 if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) {
2350 rc = -EIO; /* bad smb */
2352 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2353 memcpy((char *) pFindData,
2354 (char *) &pSMBr->hdr.Protocol +
2356 sizeof (FILE_UNIX_BASIC_INFO));
2359 cifs_buf_release(pSMB);
2361 goto UnixQPathInfoRetry;
2366 #if 0 /* function unused at present */
2367 int CIFSFindSingle(const int xid, struct cifsTconInfo *tcon,
2368 const char *searchName, FILE_ALL_INFO * findData,
2369 const struct nls_table *nls_codepage)
2371 /* level 257 SMB_ */
2372 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2373 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2377 __u16 params, byte_count;
2379 cFYI(1, ("In FindUnique"));
2381 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2386 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2388 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
2389 /* find define for this maxpathcomponent */
2391 name_len++; /* trailing null */
2393 } else { /* BB improve the check for buffer overruns BB */
2394 name_len = strnlen(searchName, PATH_MAX);
2395 name_len++; /* trailing null */
2396 strncpy(pSMB->FileName, searchName, name_len);
2399 params = 12 + name_len /* includes null */ ;
2400 pSMB->TotalDataCount = 0; /* no EAs */
2401 pSMB->MaxParameterCount = cpu_to_le16(2);
2402 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2403 pSMB->MaxSetupCount = 0;
2407 pSMB->Reserved2 = 0;
2408 pSMB->ParameterOffset = cpu_to_le16(
2409 offsetof(struct smb_com_transaction2_ffirst_req,InformationLevel) - 4);
2410 pSMB->DataCount = 0;
2411 pSMB->DataOffset = 0;
2412 pSMB->SetupCount = 1; /* one byte, no need to le convert */
2413 pSMB->Reserved3 = 0;
2414 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2415 byte_count = params + 1 /* pad */ ;
2416 pSMB->TotalParameterCount = cpu_to_le16(params);
2417 pSMB->ParameterCount = pSMB->TotalParameterCount;
2418 pSMB->SearchAttributes =
2419 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2421 pSMB->SearchCount = cpu_to_le16(16); /* BB increase */
2422 pSMB->SearchFlags = cpu_to_le16(1);
2423 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2424 pSMB->SearchStorageType = 0; /* BB what should we set this to? BB */
2425 pSMB->hdr.smb_buf_length += byte_count;
2426 pSMB->ByteCount = cpu_to_le16(byte_count);
2428 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2429 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2432 cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
2433 } else { /* decode response */
2434 #ifdef CONFIG_CIFS_STATS
2435 atomic_inc(&tcon->num_ffirst);
2440 cifs_buf_release(pSMB);
2442 goto findUniqueRetry;
2446 #endif /* end unused (temporarily) function */
2448 /* xid, tcon, searchName and codepage are input parms, rest are returned */
2450 CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
2451 const char *searchName,
2452 const struct nls_table *nls_codepage,
2454 struct cifs_search_info * psrch_inf, int remap, const char dirsep)
2456 /* level 257 SMB_ */
2457 TRANSACTION2_FFIRST_REQ *pSMB = NULL;
2458 TRANSACTION2_FFIRST_RSP *pSMBr = NULL;
2459 T2_FFIRST_RSP_PARMS * parms;
2461 int bytes_returned = 0;
2463 __u16 params, byte_count;
2465 cFYI(1, ("In FindFirst for %s",searchName));
2468 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2473 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2475 cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
2476 PATH_MAX, nls_codepage, remap);
2477 /* We can not add the asterik earlier in case
2478 it got remapped to 0xF03A as if it were part of the
2479 directory name instead of a wildcard */
2481 pSMB->FileName[name_len] = dirsep;
2482 pSMB->FileName[name_len+1] = 0;
2483 pSMB->FileName[name_len+2] = '*';
2484 pSMB->FileName[name_len+3] = 0;
2485 name_len += 4; /* now the trailing null */
2486 pSMB->FileName[name_len] = 0; /* null terminate just in case */
2487 pSMB->FileName[name_len+1] = 0;
2489 } else { /* BB add check for overrun of SMB buf BB */
2490 name_len = strnlen(searchName, PATH_MAX);
2491 /* BB fix here and in unicode clause above ie
2492 if(name_len > buffersize-header)
2493 free buffer exit; BB */
2494 strncpy(pSMB->FileName, searchName, name_len);
2495 pSMB->FileName[name_len] = dirsep;
2496 pSMB->FileName[name_len+1] = '*';
2497 pSMB->FileName[name_len+2] = 0;
2501 params = 12 + name_len /* includes null */ ;
2502 pSMB->TotalDataCount = 0; /* no EAs */
2503 pSMB->MaxParameterCount = cpu_to_le16(10);
2504 pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf -
2505 MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2506 pSMB->MaxSetupCount = 0;
2510 pSMB->Reserved2 = 0;
2511 byte_count = params + 1 /* pad */ ;
2512 pSMB->TotalParameterCount = cpu_to_le16(params);
2513 pSMB->ParameterCount = pSMB->TotalParameterCount;
2514 pSMB->ParameterOffset = cpu_to_le16(
2515 offsetof(struct smb_com_transaction2_ffirst_req, SearchAttributes) - 4);
2516 pSMB->DataCount = 0;
2517 pSMB->DataOffset = 0;
2518 pSMB->SetupCount = 1; /* one byte, no need to make endian neutral */
2519 pSMB->Reserved3 = 0;
2520 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_FIRST);
2521 pSMB->SearchAttributes =
2522 cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM |
2524 pSMB->SearchCount= cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO));
2525 pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END |
2526 CIFS_SEARCH_RETURN_RESUME);
2527 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2529 /* BB what should we set StorageType to? Does it matter? BB */
2530 pSMB->SearchStorageType = 0;
2531 pSMB->hdr.smb_buf_length += byte_count;
2532 pSMB->ByteCount = cpu_to_le16(byte_count);
2534 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2535 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2536 #ifdef CONFIG_CIFS_STATS
2537 atomic_inc(&tcon->num_ffirst);
2540 if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */
2541 /* BB Add code to handle unsupported level rc */
2542 cFYI(1, ("Error in FindFirst = %d", rc));
2545 cifs_buf_release(pSMB);
2547 /* BB eventually could optimize out free and realloc of buf */
2550 goto findFirstRetry;
2551 } else { /* decode response */
2552 /* BB remember to free buffer if error BB */
2553 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2555 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2556 psrch_inf->unicode = TRUE;
2558 psrch_inf->unicode = FALSE;
2560 psrch_inf->ntwrk_buf_start = (char *)pSMBr;
2561 psrch_inf->srch_entries_start =
2562 (char *) &pSMBr->hdr.Protocol +
2563 le16_to_cpu(pSMBr->t2.DataOffset);
2564 parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol +
2565 le16_to_cpu(pSMBr->t2.ParameterOffset));
2567 if(parms->EndofSearch)
2568 psrch_inf->endOfSearch = TRUE;
2570 psrch_inf->endOfSearch = FALSE;
2572 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2573 psrch_inf->index_of_last_entry =
2574 psrch_inf->entries_in_buffer;
2575 *pnetfid = parms->SearchHandle;
2577 cifs_buf_release(pSMB);
2584 int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
2585 __u16 searchHandle, struct cifs_search_info * psrch_inf)
2587 TRANSACTION2_FNEXT_REQ *pSMB = NULL;
2588 TRANSACTION2_FNEXT_RSP *pSMBr = NULL;
2589 T2_FNEXT_RSP_PARMS * parms;
2590 char *response_data;
2592 int bytes_returned, name_len;
2593 __u16 params, byte_count;
2595 cFYI(1, ("In FindNext"));
2597 if(psrch_inf->endOfSearch == TRUE)
2600 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2605 params = 14; /* includes 2 bytes of null string, converted to LE below */
2607 pSMB->TotalDataCount = 0; /* no EAs */
2608 pSMB->MaxParameterCount = cpu_to_le16(8);
2609 pSMB->MaxDataCount =
2610 cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00);
2611 pSMB->MaxSetupCount = 0;
2615 pSMB->Reserved2 = 0;
2616 pSMB->ParameterOffset = cpu_to_le16(
2617 offsetof(struct smb_com_transaction2_fnext_req,SearchHandle) - 4);
2618 pSMB->DataCount = 0;
2619 pSMB->DataOffset = 0;
2620 pSMB->SetupCount = 1;
2621 pSMB->Reserved3 = 0;
2622 pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
2623 pSMB->SearchHandle = searchHandle; /* always kept as le */
2625 cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
2626 /* test for Unix extensions */
2627 /* if (tcon->ses->capabilities & CAP_UNIX) {
2628 pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
2629 psrch_inf->info_level = SMB_FIND_FILE_UNIX;
2631 pSMB->InformationLevel =
2632 cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
2633 psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
2635 pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
2636 pSMB->ResumeKey = psrch_inf->resume_key;
2638 cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME);
2640 name_len = psrch_inf->resume_name_len;
2642 if(name_len < PATH_MAX) {
2643 memcpy(pSMB->ResumeFileName, psrch_inf->presume_name, name_len);
2644 byte_count += name_len;
2645 /* 14 byte parm len above enough for 2 byte null terminator */
2646 pSMB->ResumeFileName[name_len] = 0;
2647 pSMB->ResumeFileName[name_len+1] = 0;
2650 goto FNext2_err_exit;
2652 byte_count = params + 1 /* pad */ ;
2653 pSMB->TotalParameterCount = cpu_to_le16(params);
2654 pSMB->ParameterCount = pSMB->TotalParameterCount;
2655 pSMB->hdr.smb_buf_length += byte_count;
2656 pSMB->ByteCount = cpu_to_le16(byte_count);
2658 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2659 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2660 #ifdef CONFIG_CIFS_STATS
2661 atomic_inc(&tcon->num_fnext);
2665 psrch_inf->endOfSearch = TRUE;
2666 rc = 0; /* search probably was closed at end of search above */
2668 cFYI(1, ("FindNext returned = %d", rc));
2669 } else { /* decode response */
2670 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2673 /* BB fixme add lock for file (srch_info) struct here */
2674 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
2675 psrch_inf->unicode = TRUE;
2677 psrch_inf->unicode = FALSE;
2678 response_data = (char *) &pSMBr->hdr.Protocol +
2679 le16_to_cpu(pSMBr->t2.ParameterOffset);
2680 parms = (T2_FNEXT_RSP_PARMS *)response_data;
2681 response_data = (char *)&pSMBr->hdr.Protocol +
2682 le16_to_cpu(pSMBr->t2.DataOffset);
2683 cifs_buf_release(psrch_inf->ntwrk_buf_start);
2684 psrch_inf->srch_entries_start = response_data;
2685 psrch_inf->ntwrk_buf_start = (char *)pSMB;
2686 if(parms->EndofSearch)
2687 psrch_inf->endOfSearch = TRUE;
2689 psrch_inf->endOfSearch = FALSE;
2691 psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount);
2692 psrch_inf->index_of_last_entry +=
2693 psrch_inf->entries_in_buffer;
2694 /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */
2696 /* BB fixme add unlock here */
2701 /* BB On error, should we leave previous search buf (and count and
2702 last entry fields) intact or free the previous one? */
2704 /* Note: On -EAGAIN error only caller can retry on handle based calls
2705 since file handle passed in no longer valid */
2708 cifs_buf_release(pSMB);
2714 CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle)
2717 FINDCLOSE_REQ *pSMB = NULL;
2718 CLOSE_RSP *pSMBr = NULL; /* BB removeme BB */
2721 cFYI(1, ("In CIFSSMBFindClose"));
2722 rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB);
2724 /* no sense returning error if session restarted
2725 as file handle has been closed */
2731 pSMBr = (CLOSE_RSP *)pSMB; /* BB removeme BB */
2732 pSMB->FileID = searchHandle;
2733 pSMB->ByteCount = 0;
2734 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2735 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2737 cERROR(1, ("Send error in FindClose = %d", rc));
2739 #ifdef CONFIG_CIFS_STATS
2740 atomic_inc(&tcon->num_fclose);
2742 cifs_small_buf_release(pSMB);
2744 /* Since session is dead, search handle closed on server already */
2751 #ifdef CONFIG_CIFS_EXPERIMENTAL
2753 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
2754 const unsigned char *searchName,
2755 __u64 * inode_number,
2756 const struct nls_table *nls_codepage, int remap)
2759 TRANSACTION2_QPI_REQ *pSMB = NULL;
2760 TRANSACTION2_QPI_RSP *pSMBr = NULL;
2761 int name_len, bytes_returned;
2762 __u16 params, byte_count;
2764 cFYI(1,("In GetSrvInodeNum for %s",searchName));
2768 GetInodeNumberRetry:
2769 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
2775 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
2777 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
2778 PATH_MAX,nls_codepage, remap);
2779 name_len++; /* trailing null */
2781 } else { /* BB improve the check for buffer overruns BB */
2782 name_len = strnlen(searchName, PATH_MAX);
2783 name_len++; /* trailing null */
2784 strncpy(pSMB->FileName, searchName, name_len);
2787 params = 2 /* level */ + 4 /* rsrvd */ + name_len /* incl null */ ;
2788 pSMB->TotalDataCount = 0;
2789 pSMB->MaxParameterCount = cpu_to_le16(2);
2790 /* BB find exact max data count below from sess structure BB */
2791 pSMB->MaxDataCount = cpu_to_le16(4000);
2792 pSMB->MaxSetupCount = 0;
2796 pSMB->Reserved2 = 0;
2797 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2798 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
2799 pSMB->DataCount = 0;
2800 pSMB->DataOffset = 0;
2801 pSMB->SetupCount = 1;
2802 pSMB->Reserved3 = 0;
2803 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
2804 byte_count = params + 1 /* pad */ ;
2805 pSMB->TotalParameterCount = cpu_to_le16(params);
2806 pSMB->ParameterCount = pSMB->TotalParameterCount;
2807 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
2808 pSMB->Reserved4 = 0;
2809 pSMB->hdr.smb_buf_length += byte_count;
2810 pSMB->ByteCount = cpu_to_le16(byte_count);
2812 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
2813 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2815 cFYI(1, ("error %d in QueryInternalInfo", rc));
2817 /* decode response */
2818 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2819 if (rc || (pSMBr->ByteCount < 2))
2820 /* BB also check enough total bytes returned */
2821 /* If rc should we check for EOPNOSUPP and
2822 disable the srvino flag? or in caller? */
2823 rc = -EIO; /* bad smb */
2825 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2826 __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
2827 struct file_internal_info * pfinfo;
2828 /* BB Do we need a cast or hash here ? */
2830 cFYI(1, ("Illegal size ret in QryIntrnlInf"));
2832 goto GetInodeNumOut;
2834 pfinfo = (struct file_internal_info *)
2835 (data_offset + (char *) &pSMBr->hdr.Protocol);
2836 *inode_number = pfinfo->UniqueId;
2840 cifs_buf_release(pSMB);
2842 goto GetInodeNumberRetry;
2845 #endif /* CIFS_EXPERIMENTAL */
2848 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
2849 const unsigned char *searchName,
2850 unsigned char **targetUNCs,
2851 unsigned int *number_of_UNC_in_array,
2852 const struct nls_table *nls_codepage, int remap)
2854 /* TRANS2_GET_DFS_REFERRAL */
2855 TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL;
2856 TRANSACTION2_GET_DFS_REFER_RSP *pSMBr = NULL;
2857 struct dfs_referral_level_3 * referrals = NULL;
2863 __u16 params, byte_count;
2864 *number_of_UNC_in_array = 0;
2867 cFYI(1, ("In GetDFSRefer the path %s", searchName));
2871 rc = smb_init(SMB_COM_TRANSACTION2, 15, NULL, (void **) &pSMB,
2876 /* server pointer checked in called function,
2877 but should never be null here anyway */
2878 pSMB->hdr.Mid = GetNextMid(ses->server);
2879 pSMB->hdr.Tid = ses->ipc_tid;
2880 pSMB->hdr.Uid = ses->Suid;
2881 if (ses->capabilities & CAP_STATUS32) {
2882 pSMB->hdr.Flags2 |= SMBFLG2_ERR_STATUS;
2884 if (ses->capabilities & CAP_DFS) {
2885 pSMB->hdr.Flags2 |= SMBFLG2_DFS;
2888 if (ses->capabilities & CAP_UNICODE) {
2889 pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
2891 cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
2892 searchName, PATH_MAX, nls_codepage, remap);
2893 name_len++; /* trailing null */
2895 } else { /* BB improve the check for buffer overruns BB */
2896 name_len = strnlen(searchName, PATH_MAX);
2897 name_len++; /* trailing null */
2898 strncpy(pSMB->RequestFileName, searchName, name_len);
2901 params = 2 /* level */ + name_len /*includes null */ ;
2902 pSMB->TotalDataCount = 0;
2903 pSMB->DataCount = 0;
2904 pSMB->DataOffset = 0;
2905 pSMB->MaxParameterCount = 0;
2906 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
2907 pSMB->MaxSetupCount = 0;
2911 pSMB->Reserved2 = 0;
2912 pSMB->ParameterOffset = cpu_to_le16(offsetof(
2913 struct smb_com_transaction2_get_dfs_refer_req, MaxReferralLevel) - 4);
2914 pSMB->SetupCount = 1;
2915 pSMB->Reserved3 = 0;
2916 pSMB->SubCommand = cpu_to_le16(TRANS2_GET_DFS_REFERRAL);
2917 byte_count = params + 3 /* pad */ ;
2918 pSMB->ParameterCount = cpu_to_le16(params);
2919 pSMB->TotalParameterCount = pSMB->ParameterCount;
2920 pSMB->MaxReferralLevel = cpu_to_le16(3);
2921 pSMB->hdr.smb_buf_length += byte_count;
2922 pSMB->ByteCount = cpu_to_le16(byte_count);
2924 rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
2925 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
2927 cFYI(1, ("Send error in GetDFSRefer = %d", rc));
2928 } else { /* decode response */
2929 /* BB Add logic to parse referrals here */
2930 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
2932 if (rc || (pSMBr->ByteCount < 17)) /* BB also check enough total bytes returned */
2933 rc = -EIO; /* bad smb */
2935 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
2936 __u16 data_count = le16_to_cpu(pSMBr->t2.DataCount);
2939 ("Decoding GetDFSRefer response. BCC: %d Offset %d",
2940 pSMBr->ByteCount, data_offset));
2942 (struct dfs_referral_level_3 *)
2943 (8 /* sizeof start of data block */ +
2945 (char *) &pSMBr->hdr.Protocol);
2946 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",
2947 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)));
2948 /* BB This field is actually two bytes in from start of
2949 data block so we could do safety check that DataBlock
2950 begins at address of pSMBr->NumberOfReferrals */
2951 *number_of_UNC_in_array = le16_to_cpu(pSMBr->NumberOfReferrals);
2953 /* BB Fix below so can return more than one referral */
2954 if(*number_of_UNC_in_array > 1)
2955 *number_of_UNC_in_array = 1;
2957 /* get the length of the strings describing refs */
2959 for(i=0;i<*number_of_UNC_in_array;i++) {
2960 /* make sure that DfsPathOffset not past end */
2961 __u16 offset = le16_to_cpu(referrals->DfsPathOffset);
2962 if (offset > data_count) {
2963 /* if invalid referral, stop here and do
2964 not try to copy any more */
2965 *number_of_UNC_in_array = i;
2968 temp = ((char *)referrals) + offset;
2970 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2971 name_len += UniStrnlen((wchar_t *)temp,data_count);
2973 name_len += strnlen(temp,data_count);
2976 /* BB add check that referral pointer does not fall off end PDU */
2979 /* BB add check for name_len bigger than bcc */
2981 kmalloc(name_len+1+ (*number_of_UNC_in_array),GFP_KERNEL);
2982 if(*targetUNCs == NULL) {
2986 /* copy the ref strings */
2988 (struct dfs_referral_level_3 *)
2989 (8 /* sizeof data hdr */ +
2991 (char *) &pSMBr->hdr.Protocol);
2993 for(i=0;i<*number_of_UNC_in_array;i++) {
2994 temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
2995 if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
2996 cifs_strfromUCS_le(*targetUNCs,
2997 (wchar_t *) temp, name_len, nls_codepage);
2999 strncpy(*targetUNCs,temp,name_len);
3001 /* BB update target_uncs pointers */
3011 cifs_buf_release(pSMB);
3020 CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData)
3022 /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
3023 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3024 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3025 FILE_SYSTEM_INFO *response_data;
3027 int bytes_returned = 0;
3028 __u16 params, byte_count;
3030 cFYI(1, ("In QFSInfo"));
3032 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3037 params = 2; /* level */
3038 pSMB->TotalDataCount = 0;
3039 pSMB->MaxParameterCount = cpu_to_le16(2);
3040 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3041 pSMB->MaxSetupCount = 0;
3045 pSMB->Reserved2 = 0;
3046 byte_count = params + 1 /* pad */ ;
3047 pSMB->TotalParameterCount = cpu_to_le16(params);
3048 pSMB->ParameterCount = pSMB->TotalParameterCount;
3049 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3050 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3051 pSMB->DataCount = 0;
3052 pSMB->DataOffset = 0;
3053 pSMB->SetupCount = 1;
3054 pSMB->Reserved3 = 0;
3055 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3056 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_SIZE_INFO);
3057 pSMB->hdr.smb_buf_length += byte_count;
3058 pSMB->ByteCount = cpu_to_le16(byte_count);
3060 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3061 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3063 cERROR(1, ("Send error in QFSInfo = %d", rc));
3064 } else { /* decode response */
3065 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3067 if (rc || (pSMBr->ByteCount < 24)) /* BB alsO CHEck enough total bytes returned */
3068 rc = -EIO; /* bad smb */
3070 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3072 ("Decoding qfsinfo response. BCC: %d Offset %d",
3073 pSMBr->ByteCount, data_offset));
3077 *) (((char *) &pSMBr->hdr.Protocol) +
3080 le32_to_cpu(response_data->BytesPerSector) *
3081 le32_to_cpu(response_data->
3082 SectorsPerAllocationUnit);
3084 le64_to_cpu(response_data->TotalAllocationUnits);
3085 FSData->f_bfree = FSData->f_bavail =
3086 le64_to_cpu(response_data->FreeAllocationUnits);
3088 ("Blocks: %lld Free: %lld Block size %ld",
3089 (unsigned long long)FSData->f_blocks,
3090 (unsigned long long)FSData->f_bfree,
3094 cifs_buf_release(pSMB);
3103 CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon)
3105 /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */
3106 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3107 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3108 FILE_SYSTEM_ATTRIBUTE_INFO *response_data;
3110 int bytes_returned = 0;
3111 __u16 params, byte_count;
3113 cFYI(1, ("In QFSAttributeInfo"));
3115 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3120 params = 2; /* level */
3121 pSMB->TotalDataCount = 0;
3122 pSMB->MaxParameterCount = cpu_to_le16(2);
3123 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3124 pSMB->MaxSetupCount = 0;
3128 pSMB->Reserved2 = 0;
3129 byte_count = params + 1 /* pad */ ;
3130 pSMB->TotalParameterCount = cpu_to_le16(params);
3131 pSMB->ParameterCount = pSMB->TotalParameterCount;
3132 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3133 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3134 pSMB->DataCount = 0;
3135 pSMB->DataOffset = 0;
3136 pSMB->SetupCount = 1;
3137 pSMB->Reserved3 = 0;
3138 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3139 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_ATTRIBUTE_INFO);
3140 pSMB->hdr.smb_buf_length += byte_count;
3141 pSMB->ByteCount = cpu_to_le16(byte_count);
3143 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3144 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3146 cERROR(1, ("Send error in QFSAttributeInfo = %d", rc));
3147 } else { /* decode response */
3148 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3150 if (rc || (pSMBr->ByteCount < 13)) { /* BB also check enough bytes returned */
3151 rc = -EIO; /* bad smb */
3153 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3155 (FILE_SYSTEM_ATTRIBUTE_INFO
3156 *) (((char *) &pSMBr->hdr.Protocol) +
3158 memcpy(&tcon->fsAttrInfo, response_data,
3159 sizeof (FILE_SYSTEM_ATTRIBUTE_INFO));
3162 cifs_buf_release(pSMB);
3165 goto QFSAttributeRetry;
3171 CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
3173 /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */
3174 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3175 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3176 FILE_SYSTEM_DEVICE_INFO *response_data;
3178 int bytes_returned = 0;
3179 __u16 params, byte_count;
3181 cFYI(1, ("In QFSDeviceInfo"));
3183 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3188 params = 2; /* level */
3189 pSMB->TotalDataCount = 0;
3190 pSMB->MaxParameterCount = cpu_to_le16(2);
3191 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3192 pSMB->MaxSetupCount = 0;
3196 pSMB->Reserved2 = 0;
3197 byte_count = params + 1 /* pad */ ;
3198 pSMB->TotalParameterCount = cpu_to_le16(params);
3199 pSMB->ParameterCount = pSMB->TotalParameterCount;
3200 pSMB->ParameterOffset = cpu_to_le16(offsetof(
3201 struct smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3203 pSMB->DataCount = 0;
3204 pSMB->DataOffset = 0;
3205 pSMB->SetupCount = 1;
3206 pSMB->Reserved3 = 0;
3207 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3208 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FS_DEVICE_INFO);
3209 pSMB->hdr.smb_buf_length += byte_count;
3210 pSMB->ByteCount = cpu_to_le16(byte_count);
3212 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3213 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3215 cFYI(1, ("Send error in QFSDeviceInfo = %d", rc));
3216 } else { /* decode response */
3217 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3219 if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
3220 rc = -EIO; /* bad smb */
3222 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3224 (FILE_SYSTEM_DEVICE_INFO *)
3225 (((char *) &pSMBr->hdr.Protocol) +
3227 memcpy(&tcon->fsDevInfo, response_data,
3228 sizeof (FILE_SYSTEM_DEVICE_INFO));
3231 cifs_buf_release(pSMB);
3234 goto QFSDeviceRetry;
3240 CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon)
3242 /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */
3243 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3244 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3245 FILE_SYSTEM_UNIX_INFO *response_data;
3247 int bytes_returned = 0;
3248 __u16 params, byte_count;
3250 cFYI(1, ("In QFSUnixInfo"));
3252 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3257 params = 2; /* level */
3258 pSMB->TotalDataCount = 0;
3259 pSMB->DataCount = 0;
3260 pSMB->DataOffset = 0;
3261 pSMB->MaxParameterCount = cpu_to_le16(2);
3262 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3263 pSMB->MaxSetupCount = 0;
3267 pSMB->Reserved2 = 0;
3268 byte_count = params + 1 /* pad */ ;
3269 pSMB->ParameterCount = cpu_to_le16(params);
3270 pSMB->TotalParameterCount = pSMB->ParameterCount;
3271 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3272 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3273 pSMB->SetupCount = 1;
3274 pSMB->Reserved3 = 0;
3275 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3276 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_CIFS_UNIX_INFO);
3277 pSMB->hdr.smb_buf_length += byte_count;
3278 pSMB->ByteCount = cpu_to_le16(byte_count);
3280 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3281 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3283 cERROR(1, ("Send error in QFSUnixInfo = %d", rc));
3284 } else { /* decode response */
3285 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3287 if (rc || (pSMBr->ByteCount < 13)) {
3288 rc = -EIO; /* bad smb */
3290 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3292 (FILE_SYSTEM_UNIX_INFO
3293 *) (((char *) &pSMBr->hdr.Protocol) +
3295 memcpy(&tcon->fsUnixInfo, response_data,
3296 sizeof (FILE_SYSTEM_UNIX_INFO));
3299 cifs_buf_release(pSMB);
3309 CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
3311 /* level 0x200 SMB_SET_CIFS_UNIX_INFO */
3312 TRANSACTION2_SETFSI_REQ *pSMB = NULL;
3313 TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
3315 int bytes_returned = 0;
3316 __u16 params, param_offset, offset, byte_count;
3318 cFYI(1, ("In SETFSUnixInfo"));
3320 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3325 params = 4; /* 2 bytes zero followed by info level. */
3326 pSMB->MaxSetupCount = 0;
3330 pSMB->Reserved2 = 0;
3331 param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
3332 offset = param_offset + params;
3334 pSMB->MaxParameterCount = cpu_to_le16(4);
3335 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3336 pSMB->SetupCount = 1;
3337 pSMB->Reserved3 = 0;
3338 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
3339 byte_count = 1 /* pad */ + params + 12;
3341 pSMB->DataCount = cpu_to_le16(12);
3342 pSMB->ParameterCount = cpu_to_le16(params);
3343 pSMB->TotalDataCount = pSMB->DataCount;
3344 pSMB->TotalParameterCount = pSMB->ParameterCount;
3345 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3346 pSMB->DataOffset = cpu_to_le16(offset);
3350 pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
3353 pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
3354 pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
3355 pSMB->ClientUnixCap = cpu_to_le64(cap);
3357 pSMB->hdr.smb_buf_length += byte_count;
3358 pSMB->ByteCount = cpu_to_le16(byte_count);
3360 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3361 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3363 cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
3364 } else { /* decode response */
3365 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3367 rc = -EIO; /* bad smb */
3370 cifs_buf_release(pSMB);
3373 goto SETFSUnixRetry;
3381 CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
3382 struct kstatfs *FSData)
3384 /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */
3385 TRANSACTION2_QFSI_REQ *pSMB = NULL;
3386 TRANSACTION2_QFSI_RSP *pSMBr = NULL;
3387 FILE_SYSTEM_POSIX_INFO *response_data;
3389 int bytes_returned = 0;
3390 __u16 params, byte_count;
3392 cFYI(1, ("In QFSPosixInfo"));
3394 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3399 params = 2; /* level */
3400 pSMB->TotalDataCount = 0;
3401 pSMB->DataCount = 0;
3402 pSMB->DataOffset = 0;
3403 pSMB->MaxParameterCount = cpu_to_le16(2);
3404 pSMB->MaxDataCount = cpu_to_le16(100); /* BB find exact max SMB PDU from sess structure BB */
3405 pSMB->MaxSetupCount = 0;
3409 pSMB->Reserved2 = 0;
3410 byte_count = params + 1 /* pad */ ;
3411 pSMB->ParameterCount = cpu_to_le16(params);
3412 pSMB->TotalParameterCount = pSMB->ParameterCount;
3413 pSMB->ParameterOffset = cpu_to_le16(offsetof(struct
3414 smb_com_transaction2_qfsi_req, InformationLevel) - 4);
3415 pSMB->SetupCount = 1;
3416 pSMB->Reserved3 = 0;
3417 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_FS_INFORMATION);
3418 pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_POSIX_FS_INFO);
3419 pSMB->hdr.smb_buf_length += byte_count;
3420 pSMB->ByteCount = cpu_to_le16(byte_count);
3422 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3423 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3425 cFYI(1, ("Send error in QFSUnixInfo = %d", rc));
3426 } else { /* decode response */
3427 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
3429 if (rc || (pSMBr->ByteCount < 13)) {
3430 rc = -EIO; /* bad smb */
3432 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
3434 (FILE_SYSTEM_POSIX_INFO
3435 *) (((char *) &pSMBr->hdr.Protocol) +
3438 le32_to_cpu(response_data->BlockSize);
3440 le64_to_cpu(response_data->TotalBlocks);
3442 le64_to_cpu(response_data->BlocksAvail);
3443 if(response_data->UserBlocksAvail == -1) {
3444 FSData->f_bavail = FSData->f_bfree;
3447 le64_to_cpu(response_data->UserBlocksAvail);
3449 if(response_data->TotalFileNodes != -1)
3451 le64_to_cpu(response_data->TotalFileNodes);
3452 if(response_data->FreeFileNodes != -1)
3454 le64_to_cpu(response_data->FreeFileNodes);
3457 cifs_buf_release(pSMB);
3466 /* We can not use write of zero bytes trick to
3467 set file size due to need for large file support. Also note that
3468 this SetPathInfo is preferred to SetFileInfo based method in next
3469 routine which is only needed to work around a sharing violation bug
3470 in Samba which this routine can run into */
3473 CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3474 __u64 size, int SetAllocation,
3475 const struct nls_table *nls_codepage, int remap)
3477 struct smb_com_transaction2_spi_req *pSMB = NULL;
3478 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
3479 struct file_end_of_file_info *parm_data;
3482 int bytes_returned = 0;
3483 __u16 params, byte_count, data_count, param_offset, offset;
3485 cFYI(1, ("In SetEOF"));
3487 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3492 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3494 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3495 PATH_MAX, nls_codepage, remap);
3496 name_len++; /* trailing null */
3498 } else { /* BB improve the check for buffer overruns BB */
3499 name_len = strnlen(fileName, PATH_MAX);
3500 name_len++; /* trailing null */
3501 strncpy(pSMB->FileName, fileName, name_len);
3503 params = 6 + name_len;
3504 data_count = sizeof (struct file_end_of_file_info);
3505 pSMB->MaxParameterCount = cpu_to_le16(2);
3506 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
3507 pSMB->MaxSetupCount = 0;
3511 pSMB->Reserved2 = 0;
3512 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3513 InformationLevel) - 4;
3514 offset = param_offset + params;
3516 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3517 pSMB->InformationLevel =
3518 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3520 pSMB->InformationLevel =
3521 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3522 } else /* Set File Size */ {
3523 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3524 pSMB->InformationLevel =
3525 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3527 pSMB->InformationLevel =
3528 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3532 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3534 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3535 pSMB->DataOffset = cpu_to_le16(offset);
3536 pSMB->SetupCount = 1;
3537 pSMB->Reserved3 = 0;
3538 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3539 byte_count = 3 /* pad */ + params + data_count;
3540 pSMB->DataCount = cpu_to_le16(data_count);
3541 pSMB->TotalDataCount = pSMB->DataCount;
3542 pSMB->ParameterCount = cpu_to_le16(params);
3543 pSMB->TotalParameterCount = pSMB->ParameterCount;
3544 pSMB->Reserved4 = 0;
3545 pSMB->hdr.smb_buf_length += byte_count;
3546 parm_data->FileSize = cpu_to_le64(size);
3547 pSMB->ByteCount = cpu_to_le16(byte_count);
3548 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3549 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3551 cFYI(1, ("SetPathInfo (file size) returned %d", rc));
3554 cifs_buf_release(pSMB);
3563 CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size,
3564 __u16 fid, __u32 pid_of_opener, int SetAllocation)
3566 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3567 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3569 struct file_end_of_file_info *parm_data;
3571 int bytes_returned = 0;
3572 __u16 params, param_offset, offset, byte_count, count;
3574 cFYI(1, ("SetFileSize (via SetFileInfo) %lld",
3576 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3581 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3583 pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3584 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));
3587 pSMB->MaxSetupCount = 0;
3591 pSMB->Reserved2 = 0;
3592 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3593 offset = param_offset + params;
3595 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3597 count = sizeof(struct file_end_of_file_info);
3598 pSMB->MaxParameterCount = cpu_to_le16(2);
3599 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3600 pSMB->SetupCount = 1;
3601 pSMB->Reserved3 = 0;
3602 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3603 byte_count = 3 /* pad */ + params + count;
3604 pSMB->DataCount = cpu_to_le16(count);
3605 pSMB->ParameterCount = cpu_to_le16(params);
3606 pSMB->TotalDataCount = pSMB->DataCount;
3607 pSMB->TotalParameterCount = pSMB->ParameterCount;
3608 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3610 (struct file_end_of_file_info *) (((char *) &pSMB->hdr.Protocol) +
3612 pSMB->DataOffset = cpu_to_le16(offset);
3613 parm_data->FileSize = cpu_to_le64(size);
3616 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3617 pSMB->InformationLevel =
3618 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO2);
3620 pSMB->InformationLevel =
3621 cpu_to_le16(SMB_SET_FILE_ALLOCATION_INFO);
3622 } else /* Set File Size */ {
3623 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3624 pSMB->InformationLevel =
3625 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO2);
3627 pSMB->InformationLevel =
3628 cpu_to_le16(SMB_SET_FILE_END_OF_FILE_INFO);
3630 pSMB->Reserved4 = 0;
3631 pSMB->hdr.smb_buf_length += byte_count;
3632 pSMB->ByteCount = cpu_to_le16(byte_count);
3633 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3634 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3637 ("Send error in SetFileInfo (SetFileSize) = %d",
3642 cifs_small_buf_release(pSMB);
3644 /* Note: On -EAGAIN error only caller can retry on handle based calls
3645 since file handle passed in no longer valid */
3650 /* Some legacy servers such as NT4 require that the file times be set on
3651 an open handle, rather than by pathname - this is awkward due to
3652 potential access conflicts on the open, but it is unavoidable for these
3653 old servers since the only other choice is to go from 100 nanosecond DCE
3654 time and resort to the original setpathinfo level which takes the ancient
3655 DOS time format with 2 second granularity */
3657 CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data,
3660 struct smb_com_transaction2_sfi_req *pSMB = NULL;
3661 struct smb_com_transaction2_sfi_rsp *pSMBr = NULL;
3664 int bytes_returned = 0;
3665 __u16 params, param_offset, offset, byte_count, count;
3667 cFYI(1, ("Set Times (via SetFileInfo)"));
3668 rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB);
3673 pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB;
3675 /* At this point there is no need to override the current pid
3676 with the pid of the opener, but that could change if we someday
3677 use an existing handle (rather than opening one on the fly) */
3678 /* pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener);
3679 pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16));*/
3682 pSMB->MaxSetupCount = 0;
3686 pSMB->Reserved2 = 0;
3687 param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
3688 offset = param_offset + params;
3690 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3692 count = sizeof (FILE_BASIC_INFO);
3693 pSMB->MaxParameterCount = cpu_to_le16(2);
3694 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB PDU from sess */
3695 pSMB->SetupCount = 1;
3696 pSMB->Reserved3 = 0;
3697 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION);
3698 byte_count = 3 /* pad */ + params + count;
3699 pSMB->DataCount = cpu_to_le16(count);
3700 pSMB->ParameterCount = cpu_to_le16(params);
3701 pSMB->TotalDataCount = pSMB->DataCount;
3702 pSMB->TotalParameterCount = pSMB->ParameterCount;
3703 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3704 pSMB->DataOffset = cpu_to_le16(offset);
3706 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3707 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3709 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3710 pSMB->Reserved4 = 0;
3711 pSMB->hdr.smb_buf_length += byte_count;
3712 pSMB->ByteCount = cpu_to_le16(byte_count);
3713 memcpy(data_offset,data,sizeof(FILE_BASIC_INFO));
3714 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3715 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3717 cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc));
3720 cifs_small_buf_release(pSMB);
3722 /* Note: On -EAGAIN error only caller can retry on handle based calls
3723 since file handle passed in no longer valid */
3730 CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName,
3731 const FILE_BASIC_INFO * data,
3732 const struct nls_table *nls_codepage, int remap)
3734 TRANSACTION2_SPI_REQ *pSMB = NULL;
3735 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3738 int bytes_returned = 0;
3740 __u16 params, param_offset, offset, byte_count, count;
3742 cFYI(1, ("In SetTimes"));
3745 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3750 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3752 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3753 PATH_MAX, nls_codepage, remap);
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_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;
3774 data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
3775 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3776 pSMB->DataOffset = cpu_to_le16(offset);
3777 pSMB->SetupCount = 1;
3778 pSMB->Reserved3 = 0;
3779 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3780 byte_count = 3 /* pad */ + params + count;
3782 pSMB->DataCount = cpu_to_le16(count);
3783 pSMB->ParameterCount = cpu_to_le16(params);
3784 pSMB->TotalDataCount = pSMB->DataCount;
3785 pSMB->TotalParameterCount = pSMB->ParameterCount;
3786 if (tcon->ses->capabilities & CAP_INFOLEVEL_PASSTHRU)
3787 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO2);
3789 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_BASIC_INFO);
3790 pSMB->Reserved4 = 0;
3791 pSMB->hdr.smb_buf_length += byte_count;
3792 memcpy(data_offset, data, sizeof (FILE_BASIC_INFO));
3793 pSMB->ByteCount = cpu_to_le16(byte_count);
3794 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3795 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3797 cFYI(1, ("SetPathInfo (times) returned %d", rc));
3800 cifs_buf_release(pSMB);
3808 /* Can not be used to set time stamps yet (due to old DOS time format) */
3809 /* Can be used to set attributes */
3810 #if 0 /* Possibly not needed - since it turns out that strangely NT4 has a bug
3811 handling it anyway and NT4 was what we thought it would be needed for
3812 Do not delete it until we prove whether needed for Win9x though */
3814 CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName,
3815 __u16 dos_attrs, const struct nls_table *nls_codepage)
3817 SETATTR_REQ *pSMB = NULL;
3818 SETATTR_RSP *pSMBr = NULL;
3823 cFYI(1, ("In SetAttrLegacy"));
3826 rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB,
3831 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3833 ConvertToUCS((__le16 *) pSMB->fileName, fileName,
3834 PATH_MAX, nls_codepage);
3835 name_len++; /* trailing null */
3837 } else { /* BB improve the check for buffer overruns BB */
3838 name_len = strnlen(fileName, PATH_MAX);
3839 name_len++; /* trailing null */
3840 strncpy(pSMB->fileName, fileName, name_len);
3842 pSMB->attr = cpu_to_le16(dos_attrs);
3843 pSMB->BufferFormat = 0x04;
3844 pSMB->hdr.smb_buf_length += name_len + 1;
3845 pSMB->ByteCount = cpu_to_le16(name_len + 1);
3846 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3847 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3849 cFYI(1, ("Error in LegacySetAttr = %d", rc));
3852 cifs_buf_release(pSMB);
3855 goto SetAttrLgcyRetry;
3859 #endif /* temporarily unneeded SetAttr legacy function */
3862 CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon,
3863 char *fileName, __u64 mode, __u64 uid, __u64 gid,
3864 dev_t device, const struct nls_table *nls_codepage,
3867 TRANSACTION2_SPI_REQ *pSMB = NULL;
3868 TRANSACTION2_SPI_RSP *pSMBr = NULL;
3871 int bytes_returned = 0;
3872 FILE_UNIX_BASIC_INFO *data_offset;
3873 __u16 params, param_offset, offset, count, byte_count;
3875 cFYI(1, ("In SetUID/GID/Mode"));
3877 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
3882 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
3884 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
3885 PATH_MAX, nls_codepage, remap);
3886 name_len++; /* trailing null */
3888 } else { /* BB improve the check for buffer overruns BB */
3889 name_len = strnlen(fileName, PATH_MAX);
3890 name_len++; /* trailing null */
3891 strncpy(pSMB->FileName, fileName, name_len);
3894 params = 6 + name_len;
3895 count = sizeof (FILE_UNIX_BASIC_INFO);
3896 pSMB->MaxParameterCount = cpu_to_le16(2);
3897 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find exact max SMB PDU from sess structure BB */
3898 pSMB->MaxSetupCount = 0;
3902 pSMB->Reserved2 = 0;
3903 param_offset = offsetof(struct smb_com_transaction2_spi_req,
3904 InformationLevel) - 4;
3905 offset = param_offset + params;
3907 (FILE_UNIX_BASIC_INFO *) ((char *) &pSMB->hdr.Protocol +
3909 memset(data_offset, 0, count);
3910 pSMB->DataOffset = cpu_to_le16(offset);
3911 pSMB->ParameterOffset = cpu_to_le16(param_offset);
3912 pSMB->SetupCount = 1;
3913 pSMB->Reserved3 = 0;
3914 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
3915 byte_count = 3 /* pad */ + params + count;
3916 pSMB->ParameterCount = cpu_to_le16(params);
3917 pSMB->DataCount = cpu_to_le16(count);
3918 pSMB->TotalParameterCount = pSMB->ParameterCount;
3919 pSMB->TotalDataCount = pSMB->DataCount;
3920 pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC);
3921 pSMB->Reserved4 = 0;
3922 pSMB->hdr.smb_buf_length += byte_count;
3923 data_offset->Uid = cpu_to_le64(uid);
3924 data_offset->Gid = cpu_to_le64(gid);
3925 /* better to leave device as zero when it is */
3926 data_offset->DevMajor = cpu_to_le64(MAJOR(device));
3927 data_offset->DevMinor = cpu_to_le64(MINOR(device));
3928 data_offset->Permissions = cpu_to_le64(mode);
3931 data_offset->Type = cpu_to_le32(UNIX_FILE);
3932 else if(S_ISDIR(mode))
3933 data_offset->Type = cpu_to_le32(UNIX_DIR);
3934 else if(S_ISLNK(mode))
3935 data_offset->Type = cpu_to_le32(UNIX_SYMLINK);
3936 else if(S_ISCHR(mode))
3937 data_offset->Type = cpu_to_le32(UNIX_CHARDEV);
3938 else if(S_ISBLK(mode))
3939 data_offset->Type = cpu_to_le32(UNIX_BLOCKDEV);
3940 else if(S_ISFIFO(mode))
3941 data_offset->Type = cpu_to_le32(UNIX_FIFO);
3942 else if(S_ISSOCK(mode))
3943 data_offset->Type = cpu_to_le32(UNIX_SOCKET);
3946 pSMB->ByteCount = cpu_to_le16(byte_count);
3947 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3948 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
3950 cFYI(1, ("SetPathInfo (perms) returned %d", rc));
3954 cifs_buf_release(pSMB);
3960 int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
3961 const int notify_subdirs, const __u16 netfid,
3962 __u32 filter, const struct nls_table *nls_codepage)
3965 struct smb_com_transaction_change_notify_req * pSMB = NULL;
3966 struct smb_com_transaction_change_notify_rsp * pSMBr = NULL;
3969 cFYI(1, ("In CIFSSMBNotify for file handle %d",(int)netfid));
3970 rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB,
3975 pSMB->TotalParameterCount = 0 ;
3976 pSMB->TotalDataCount = 0;
3977 pSMB->MaxParameterCount = cpu_to_le32(2);
3978 /* BB find exact data count max from sess structure BB */
3979 pSMB->MaxDataCount = 0; /* same in little endian or be */
3980 pSMB->MaxSetupCount = 4;
3982 pSMB->ParameterOffset = 0;
3983 pSMB->DataCount = 0;
3984 pSMB->DataOffset = 0;
3985 pSMB->SetupCount = 4; /* single byte does not need le conversion */
3986 pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_NOTIFY_CHANGE);
3987 pSMB->ParameterCount = pSMB->TotalParameterCount;
3989 pSMB->WatchTree = 1; /* one byte - no le conversion needed */
3990 pSMB->Reserved2 = 0;
3991 pSMB->CompletionFilter = cpu_to_le32(filter);
3992 pSMB->Fid = netfid; /* file handle always le */
3993 pSMB->ByteCount = 0;
3995 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
3996 (struct smb_hdr *) pSMBr, &bytes_returned, -1);
3998 cFYI(1, ("Error in Notify = %d", rc));
4000 cifs_buf_release(pSMB);
4003 #ifdef CONFIG_CIFS_XATTR
4005 CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon,
4006 const unsigned char *searchName,
4007 char * EAData, size_t buf_size,
4008 const struct nls_table *nls_codepage, int remap)
4010 /* BB assumes one setup word */
4011 TRANSACTION2_QPI_REQ *pSMB = NULL;
4012 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4016 struct fea * temp_fea;
4018 __u16 params, byte_count;
4020 cFYI(1, ("In Query All EAs path %s", searchName));
4022 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4027 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4029 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4030 PATH_MAX, nls_codepage, remap);
4031 name_len++; /* trailing null */
4033 } else { /* BB improve the check for buffer overruns BB */
4034 name_len = strnlen(searchName, PATH_MAX);
4035 name_len++; /* trailing null */
4036 strncpy(pSMB->FileName, searchName, name_len);
4039 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4040 pSMB->TotalDataCount = 0;
4041 pSMB->MaxParameterCount = cpu_to_le16(2);
4042 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4043 pSMB->MaxSetupCount = 0;
4047 pSMB->Reserved2 = 0;
4048 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4049 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4050 pSMB->DataCount = 0;
4051 pSMB->DataOffset = 0;
4052 pSMB->SetupCount = 1;
4053 pSMB->Reserved3 = 0;
4054 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4055 byte_count = params + 1 /* pad */ ;
4056 pSMB->TotalParameterCount = cpu_to_le16(params);
4057 pSMB->ParameterCount = pSMB->TotalParameterCount;
4058 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4059 pSMB->Reserved4 = 0;
4060 pSMB->hdr.smb_buf_length += byte_count;
4061 pSMB->ByteCount = cpu_to_le16(byte_count);
4063 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4064 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4066 cFYI(1, ("Send error in QueryAllEAs = %d", rc));
4067 } else { /* decode response */
4068 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4070 /* BB also check enough total bytes returned */
4071 /* BB we need to improve the validity checking
4072 of these trans2 responses */
4073 if (rc || (pSMBr->ByteCount < 4))
4074 rc = -EIO; /* bad smb */
4075 /* else if (pFindData){
4076 memcpy((char *) pFindData,
4077 (char *) &pSMBr->hdr.Protocol +
4080 /* check that length of list is not more than bcc */
4081 /* check that each entry does not go beyond length
4083 /* check that each element of each entry does not
4084 go beyond end of list */
4085 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4086 struct fealist * ea_response_data;
4088 /* validate_trans2_offsets() */
4089 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4090 ea_response_data = (struct fealist *)
4091 (((char *) &pSMBr->hdr.Protocol) +
4093 name_len = le32_to_cpu(ea_response_data->list_len);
4094 cFYI(1,("ea length %d", name_len));
4096 /* returned EA size zeroed at top of function */
4097 cFYI(1,("empty EA list returned from server"));
4099 /* account for ea list len */
4101 temp_fea = ea_response_data->list;
4102 temp_ptr = (char *)temp_fea;
4103 while(name_len > 0) {
4107 rc += temp_fea->name_len;
4108 /* account for prefix user. and trailing null */
4110 if(rc<(int)buf_size) {
4111 memcpy(EAData,"user.",5);
4113 memcpy(EAData,temp_ptr,temp_fea->name_len);
4114 EAData+=temp_fea->name_len;
4115 /* null terminate name */
4117 EAData = EAData + 1;
4118 } else if(buf_size == 0) {
4119 /* skip copy - calc size only */
4121 /* stop before overrun buffer */
4125 name_len -= temp_fea->name_len;
4126 temp_ptr += temp_fea->name_len;
4127 /* account for trailing null */
4130 value_len = le16_to_cpu(temp_fea->value_len);
4131 name_len -= value_len;
4132 temp_ptr += value_len;
4133 /* BB check that temp_ptr is still within smb BB*/
4134 /* no trailing null to account for in value len */
4135 /* go on to next EA */
4136 temp_fea = (struct fea *)temp_ptr;
4142 cifs_buf_release(pSMB);
4149 ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon,
4150 const unsigned char * searchName,const unsigned char * ea_name,
4151 unsigned char * ea_value, size_t buf_size,
4152 const struct nls_table *nls_codepage, int remap)
4154 TRANSACTION2_QPI_REQ *pSMB = NULL;
4155 TRANSACTION2_QPI_RSP *pSMBr = NULL;
4159 struct fea * temp_fea;
4161 __u16 params, byte_count;
4163 cFYI(1, ("In Query EA path %s", searchName));
4165 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4170 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4172 cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
4173 PATH_MAX, nls_codepage, remap);
4174 name_len++; /* trailing null */
4176 } else { /* BB improve the check for buffer overruns BB */
4177 name_len = strnlen(searchName, PATH_MAX);
4178 name_len++; /* trailing null */
4179 strncpy(pSMB->FileName, searchName, name_len);
4182 params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */ ;
4183 pSMB->TotalDataCount = 0;
4184 pSMB->MaxParameterCount = cpu_to_le16(2);
4185 pSMB->MaxDataCount = cpu_to_le16(4000); /* BB find exact max SMB PDU from sess structure BB */
4186 pSMB->MaxSetupCount = 0;
4190 pSMB->Reserved2 = 0;
4191 pSMB->ParameterOffset = cpu_to_le16(offsetof(
4192 struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
4193 pSMB->DataCount = 0;
4194 pSMB->DataOffset = 0;
4195 pSMB->SetupCount = 1;
4196 pSMB->Reserved3 = 0;
4197 pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
4198 byte_count = params + 1 /* pad */ ;
4199 pSMB->TotalParameterCount = cpu_to_le16(params);
4200 pSMB->ParameterCount = pSMB->TotalParameterCount;
4201 pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS);
4202 pSMB->Reserved4 = 0;
4203 pSMB->hdr.smb_buf_length += byte_count;
4204 pSMB->ByteCount = cpu_to_le16(byte_count);
4206 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4207 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4209 cFYI(1, ("Send error in Query EA = %d", rc));
4210 } else { /* decode response */
4211 rc = validate_t2((struct smb_t2_rsp *)pSMBr);
4213 /* BB also check enough total bytes returned */
4214 /* BB we need to improve the validity checking
4215 of these trans2 responses */
4216 if (rc || (pSMBr->ByteCount < 4))
4217 rc = -EIO; /* bad smb */
4218 /* else if (pFindData){
4219 memcpy((char *) pFindData,
4220 (char *) &pSMBr->hdr.Protocol +
4223 /* check that length of list is not more than bcc */
4224 /* check that each entry does not go beyond length
4226 /* check that each element of each entry does not
4227 go beyond end of list */
4228 __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
4229 struct fealist * ea_response_data;
4231 /* validate_trans2_offsets() */
4232 /* BB to check if(start of smb + data_offset > &bcc+ bcc)*/
4233 ea_response_data = (struct fealist *)
4234 (((char *) &pSMBr->hdr.Protocol) +
4236 name_len = le32_to_cpu(ea_response_data->list_len);
4237 cFYI(1,("ea length %d", name_len));
4239 /* returned EA size zeroed at top of function */
4240 cFYI(1,("empty EA list returned from server"));
4242 /* account for ea list len */
4244 temp_fea = ea_response_data->list;
4245 temp_ptr = (char *)temp_fea;
4246 /* loop through checking if we have a matching
4247 name and then return the associated value */
4248 while(name_len > 0) {
4252 value_len = le16_to_cpu(temp_fea->value_len);
4253 /* BB validate that value_len falls within SMB,
4254 even though maximum for name_len is 255 */
4255 if(memcmp(temp_fea->name,ea_name,
4256 temp_fea->name_len) == 0) {
4259 /* account for prefix user. and trailing null */
4260 if(rc<=(int)buf_size) {
4262 temp_fea->name+temp_fea->name_len+1,
4264 /* ea values, unlike ea names,
4265 are not null terminated */
4266 } else if(buf_size == 0) {
4267 /* skip copy - calc size only */
4269 /* stop before overrun buffer */
4274 name_len -= temp_fea->name_len;
4275 temp_ptr += temp_fea->name_len;
4276 /* account for trailing null */
4279 name_len -= value_len;
4280 temp_ptr += value_len;
4281 /* no trailing null to account for in value len */
4282 /* go on to next EA */
4283 temp_fea = (struct fea *)temp_ptr;
4289 cifs_buf_release(pSMB);
4297 CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName,
4298 const char * ea_name, const void * ea_value,
4299 const __u16 ea_value_len, const struct nls_table *nls_codepage,
4302 struct smb_com_transaction2_spi_req *pSMB = NULL;
4303 struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
4304 struct fealist *parm_data;
4307 int bytes_returned = 0;
4308 __u16 params, param_offset, byte_count, offset, count;
4310 cFYI(1, ("In SetEA"));
4312 rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
4317 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
4319 cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
4320 PATH_MAX, nls_codepage, remap);
4321 name_len++; /* trailing null */
4323 } else { /* BB improve the check for buffer overruns BB */
4324 name_len = strnlen(fileName, PATH_MAX);
4325 name_len++; /* trailing null */
4326 strncpy(pSMB->FileName, fileName, name_len);
4329 params = 6 + name_len;
4331 /* done calculating parms using name_len of file name,
4332 now use name_len to calculate length of ea name
4333 we are going to create in the inode xattrs */
4337 name_len = strnlen(ea_name,255);
4339 count = sizeof(*parm_data) + ea_value_len + name_len + 1;
4340 pSMB->MaxParameterCount = cpu_to_le16(2);
4341 pSMB->MaxDataCount = cpu_to_le16(1000); /* BB find max SMB size from sess */
4342 pSMB->MaxSetupCount = 0;
4346 pSMB->Reserved2 = 0;
4347 param_offset = offsetof(struct smb_com_transaction2_spi_req,
4348 InformationLevel) - 4;
4349 offset = param_offset + params;
4350 pSMB->InformationLevel =
4351 cpu_to_le16(SMB_SET_FILE_EA);
4354 (struct fealist *) (((char *) &pSMB->hdr.Protocol) +
4356 pSMB->ParameterOffset = cpu_to_le16(param_offset);
4357 pSMB->DataOffset = cpu_to_le16(offset);
4358 pSMB->SetupCount = 1;
4359 pSMB->Reserved3 = 0;
4360 pSMB->SubCommand = cpu_to_le16(TRANS2_SET_PATH_INFORMATION);
4361 byte_count = 3 /* pad */ + params + count;
4362 pSMB->DataCount = cpu_to_le16(count);
4363 parm_data->list_len = cpu_to_le32(count);
4364 parm_data->list[0].EA_flags = 0;
4365 /* we checked above that name len is less than 255 */
4366 parm_data->list[0].name_len = (__u8)name_len;;
4367 /* EA names are always ASCII */
4369 strncpy(parm_data->list[0].name,ea_name,name_len);
4370 parm_data->list[0].name[name_len] = 0;
4371 parm_data->list[0].value_len = cpu_to_le16(ea_value_len);
4372 /* caller ensures that ea_value_len is less than 64K but
4373 we need to ensure that it fits within the smb */
4375 /*BB add length check that it would fit in negotiated SMB buffer size BB */
4376 /* if(ea_value_len > buffer_size - 512 (enough for header)) */
4378 memcpy(parm_data->list[0].name+name_len+1,ea_value,ea_value_len);
4380 pSMB->TotalDataCount = pSMB->DataCount;
4381 pSMB->ParameterCount = cpu_to_le16(params);
4382 pSMB->TotalParameterCount = pSMB->ParameterCount;
4383 pSMB->Reserved4 = 0;
4384 pSMB->hdr.smb_buf_length += byte_count;
4385 pSMB->ByteCount = cpu_to_le16(byte_count);
4386 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
4387 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
4389 cFYI(1, ("SetPathInfo (EA) returned %d", rc));
4392 cifs_buf_release(pSMB);